Commit 0ec2f05f authored by Tasso Evangelista's avatar Tasso Evangelista

Add Text component

parent 53cda7c8
......@@ -5,17 +5,23 @@
"body": [
"import React from 'react';",
"",
"import { useStyle } from '../../hooks/styles';",
"import { useStyles } from '../../hooks/useStyles';",
"import { Box } from '../Box';",
"import styles from './styles.scss';",
"",
"",
"export function $1({",
"export const $1 = React.forwardRef(function $1({",
" className,",
" ...props",
"}) {",
" const $3ClassName = useStyle(styles, '$2', {}, className);",
" return <div className={$3ClassName} {...props} />;",
"}"
"}, ref) {",
" const classNames = useStyles(styles, ['$2'], {}, className);",
"",
" return <Box",
" className={classNames.$3}",
" ref={ref}",
" {...props}",
" />;",
"});"
],
},
"New component spec.js": {
......@@ -56,9 +62,7 @@
" .addDecorator(withKnobs)",
" .addDecorator(centered)",
" .addParameters({ jest: ['$1/spec'] })",
" .add('default', () =>",
" <$1 {...props()} />",
" );"
" .add('default', () => <$1 {...props()} />);"
],
},
"New component styles.scss": {
......@@ -66,17 +70,9 @@
"prefix": "fuselage-styles",
"body": [
"@import '../../helpers/mixins.scss';",
"@import '../../helpers/theme-var.scss';",
"@import '../../styles/color-palette.scss';",
"@import '../../styles/dimensions.scss';",
"@import '../../styles/typography.scss';",
"",
"\\$name: '$1';",
"",
"\\$default-theme: ();",
"@import '../../tokens/index.scss';",
"",
".$1 {",
" @include reset;",
"}",
],
},
......
@import '../../tokens/index.scss';
@import '../../styles/theme.scss';
.rcx-box {
box-sizing: border-box;
transition: all var(--theme-transitions-short-duration);
transition: all var-theme(transitions-short-duration);
letter-spacing: inherit;
font-family: inherit;
......
import React from 'react';
import { useStyles } from '../../hooks/useStyles';
import { Box } from '../Box';
import styles from './styles.scss';
export const Text = React.forwardRef(function Text({
className,
variant,
...props
}, ref) {
const classNames = useStyles(styles, ['text'], {
variant,
}, className);
return <Box
className={classNames.text}
ref={ref}
{...props}
/>;
});
import React from 'react';
import ReactDOM from 'react-dom';
import { Text } from './index';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<Text />, div);
ReactDOM.unmountComponentAtNode(div);
});
import centered from '@storybook/addon-centered/react';
import { withKnobs } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react';
import React from 'react';
import { createPropsFromKnobs } from '../../helpers/storybook';
import { Text } from './index';
const props = createPropsFromKnobs({
children: 'Lorem ipsum dolor sit amet',
variant: ['p1', [
'h1',
's1',
's2',
'p1',
'p2',
'c1',
'c2',
'micro',
]],
});
storiesOf('Elements|Text', module)
.addDecorator(withKnobs)
.addDecorator(centered)
.addParameters({ jest: ['Text/spec'] })
.add('default', () => <Text {...props()} />)
.add('h1 variant', () => <Text {...props({ variant: 'h1' })} />)
.add('s1 variant', () => <Text {...props({ variant: 's1' })} />)
.add('s2 variant', () => <Text {...props({ variant: 's2' })} />)
.add('p1 variant', () => <Text {...props({ variant: 'p1' })} />)
.add('p2 variant', () => <Text {...props({ variant: 'p2' })} />)
.add('c1 variant', () => <Text {...props({ variant: 'c1' })} />)
.add('c2 variant', () => <Text {...props({ variant: 'c2' })} />)
.add('micro variant', () => <Text {...props({ variant: 'micro' })} />);
@import '../../helpers/mixins.scss';
@import '../../styles/theme.scss';
@mixin variant($name) {
letter-spacing: var-theme(typography-#{$name}-letter-spacing);
font-family: var-theme(typography-#{$name}-font-family);
font-size: var-theme(typography-#{$name}-font-size);
font-weight: var-theme(typography-#{$name}-font-weight);
line-height: var-theme(typography-#{$name}-line-height);
}
.rcx-text {
@include variant(p1);
@each $name in map-keys(get-token('typography')) {
&--variant-#{$name} {
@include variant($name);
}
}
}
export const toREM = (length) => {
if (typeof length === 'number') {
return `${ length / 16 }rem`;
}
return length;
};
......@@ -2,12 +2,9 @@ import { useLayoutEffect, useMemo } from 'react';
import { flatMap } from '../helpers/flatMap';
import { fromCameltoKebabCase } from '../helpers/fromCamelToKebabCase';
import { useTheme } from './useTheme';
export const useStyle = (styles, root, modifiers = {}, forwardedClassName) => {
useTheme();
useLayoutEffect(() => {
styles.use();
......
import { useLayoutEffect } from 'react';
import theme from '../styles/theme';
import { fromCameltoKebabCase } from '../helpers/fromCamelToKebabCase';
const themeStyleId = 'rcx-theme';
let themeStyleElement;
let refCount = 0;
const serialize = (prefix, properties) =>
Object.entries(properties).reduce((vars, [name, value]) => [
...vars,
...typeof value === 'object'
? serialize(`${ prefix }-${ name }`, value)
: [`--${ prefix }-${ fromCameltoKebabCase(name) }: ${ value };`],
], []);
export const useTheme = () => {
useLayoutEffect(() => {
if (!themeStyleElement) {
themeStyleElement = document.createElement('style');
themeStyleElement.setAttribute('id', themeStyleId);
document.head.appendChild(themeStyleElement);
}
++refCount;
return () => {
if (--refCount <= 0 && themeStyleElement) {
themeStyleElement.remove();
themeStyleElement = null;
}
};
}, []);
useLayoutEffect(() => {
themeStyleElement.innerHTML = [
':root {',
...serialize('theme', theme),
'}',
].join('');
}, [theme, themeStyleElement]);
};
import { toREM } from '../helpers/toREM';
import { borders, spaces, transitions, typography } from '../tokens';
const toREM = (length) => {
if (typeof length === 'number') {
return `${ length / 16 }rem`;
}
return length;
};
const mapBorder = ({
width,
radius,
......@@ -25,6 +32,11 @@ const mapTypographicVariant = ({
});
export default {
'borders-default-width': toREM(borders.default.width),
'borders-default-radius': toREM(borders.default.radius),
'transitions-short-duration': toREM(transitions.shortDuration),
borders: Object.entries(borders).reduce((obj, [name, border]) => ({
...obj,
[name]: mapBorder(border),
......
@import '../tokens/index.scss';
@function toREM($length) {
@return #{$length / 16}rem;
}
@function var-theme($name) {
@if not map-has-key($theme, $name) {
@error 'The default theme has no var "#{$name}".';
}
@return var(--rcx-theme-#{$name}, map-get($theme, $name));
}
$theme: (
borders-default-width: torem(get-token('borders', 'default', 'width')),
borders-default-radius: torem(get-token('borders', 'default', 'radius')),
transitions-short-duration: get-token('transitions', 'short-duration'),
);
@each $name, $properties in get-token('typography') {
$theme: map-merge(
$theme,
(
typography-#{$name}-font-family: map-get($properties, font-family),
typography-#{$name}-font-size: torem(map-get($properties, font-size)),
typography-#{$name}-font-weight: map-get($properties, font-weight),
typography-#{$name}-letter-spacing: torem(map-get($properties, letter-spacing)),
typography-#{$name}-line-height: torem(map-get($properties, line-height)),
)
);
}
$borders: (
default: (
'width': 2px,
'radius': 2px,
'width': 2,
'radius': 2,
),
);
......@@ -12,6 +12,16 @@ $tokens: (
typography: $typography,
);
@function get-token($keys...) {
$node: $tokens;
@each $key in $keys {
$node: map-get($node, $key);
}
@return $node;
}
@function color($name) {
@if not map-get($colors, $name) {
@error There is no color named $name in the palette;
......
$spaces: (
0,
2px,
4px,
8px,
12px,
16px,
24px,
32px,
40px,
0: 0,
1: 2,
2: 4,
3: 8,
4: 12,
5: 16,
6: 24,
7: 32,
8: 40,
);
......@@ -16,60 +16,60 @@ $default-font-family:
sans-serif;
$typography: (
h1: (
'h1': (
font-family: $default-font-family,
font-size: 22,
font-weight: '400',
font-weight: 400,
letter-spacing: 0,
line-height: 32,
),
s1: (
's1': (
font-family: $default-font-family,
font-size: 16,
font-weight: '400',
font-weight: 400,
letter-spacing: 0,
line-height: 22,
),
s2: (
's2': (
font-family: $default-font-family,
font-size: 16,
font-weight: '500',
font-weight: 500,
letter-spacing: 0,
line-height: 22,
),
p1: (
'p1': (
font-family: $default-font-family,
font-size: 14,
font-weight: '400',
font-weight: 400,
letter-spacing: 0,
line-height: 20,
),
p2: (
'p2': (
font-family: $default-font-family,
font-size: 14,
font-weight: '500',
font-weight: 500,
letter-spacing: 0,
line-height: 20,
),
c1: (
'c1': (
font-family: $default-font-family,
font-size: 12,
font-weight: '400',
font-weight: 400,
letter-spacing: 0,
line-height: 16,
),
c2: (
'c2': (
font-family: $default-font-family,
font-size: 12,
font-weight: '600',
font-weight: 600,
letter-spacing: 0,
line-height: 16,
),
micro: (
'micro': (
font-family: $default-font-family,
font-size: 10,
font-weight: '600',
font-weight: 600,
letter-spacing: 0.2,
line-height: 12,
),
),;
);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment