Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion libs/design-tokens/src/lib/sd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ const RN_NUMERIC_TYPES = new Set([
'fontWeight',
]);

/**
* Web rem 변환 대상 토큰 타입.
* tokens-studio align-types preprocessor가 spacing/borderRadius/borderWidth를 `dimension`으로 정규화하므로
* `dimension`을 포함시켜야 spacing/radius/border-width가 px → rem 변환된다.
*/
const WEB_REM_TYPES = new Set(['dimension', 'fontSize', 'lineHeight']);

/** rem 변환 base. CSS 표준 16px. */
const REM_BASE_PX = 16;

/** 배열·객체가 아닌 평범한 record 객체인지 검사. */
const isPlainObj = (v: unknown): v is Record<string, unknown> =>
!!v && typeof v === 'object' && !Array.isArray(v);
Expand Down Expand Up @@ -59,6 +69,42 @@ const rnNumberTransform: Transform = {
transform: (t: TransformedToken) => coerceNum(getTokenValue(t)),
};

/**
* Web용 rem 변환 transform. spacing/fontSize/lineHeight 값을 px → rem으로 변환.
* html font-size override에 반응하도록 unitless/px 값을 rem 기반으로 노출.
*/
const webRemTransform: Transform = {
name: 'ds/web/rem',
type: 'value',
transitive: true,
filter: (t) => {
const type = getTokenType(t);
return typeof type === 'string' && WEB_REM_TYPES.has(type);
},
transform: (t: TransformedToken) => {
const v = getTokenValue(t);
const n = toNumeric(v);
if (n === null) return v;
return `${stripTrailingZeros(n / REM_BASE_PX)}rem`;
},
};

/** 숫자 또는 숫자 문자열을 number로 변환. 단위가 붙어 있으면 null. */
const toNumeric = (v: unknown): number | null => {
if (typeof v === 'number') return Number.isFinite(v) ? v : null;
if (typeof v !== 'string') return null;
const s = v.trim();
if (!/^-?\d+(\.\d+)?$/.test(s)) return null;
const n = Number(s);
return Number.isFinite(n) ? n : null;
};

/** 부동소수점 표기에서 불필요한 trailing 0 제거. `0.1250000` → `0.125`. */
const stripTrailingZeros = (n: number): string => {
const s = n.toFixed(6);
return s.replace(/\.?0+$/, '');
};

let registered = false;

/** Tokens Studio + 자체 transform을 SD에 1회만 등록. 중복 호출 안전. */
Expand All @@ -67,6 +113,7 @@ const registerOnce = () => {
registered = true;
registerTokensStudio(StyleDictionary);
StyleDictionary.registerTransform(rnNumberTransform);
StyleDictionary.registerTransform(webRemTransform);
};

/** `arr`에서 `rm`에 포함된 항목을 제거한 새 배열을 반환. */
Expand All @@ -79,7 +126,11 @@ const baseTransforms = getTransforms({ platform: 'css' })
.filter((t): t is string => typeof t === 'string')
.filter((t) => !t.startsWith('name/'));

const WEB_TRANSFORMS = [...without(baseTransforms, ['ts/color/css/hexrgba']), 'name/kebab'];
const WEB_TRANSFORMS = [
...without(baseTransforms, ['ts/color/css/hexrgba', 'ts/size/px']),
'ds/web/rem',
'name/kebab',
];

const RN_TRANSFORMS = [
...without(baseTransforms, ['ts/size/px', 'ts/size/css/letterspacing', 'ts/color/css/hexrgba']),
Expand Down
21 changes: 19 additions & 2 deletions libs/design-tokens/tokens/dark/color.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"disabled": { "$value": "{neutral.ne700}", "$type": "color" },
"focusRipple": { "$value": "{primary.pr500}", "$type": "color" },
"outlinedFocusRipple": { "$value": "{primary.pr700}", "$type": "color" },
"outlinedHover": { "$value": "{primary.pr800}", "$type": "color" }
"outlinedHover": { "$value": "{primary.pr300}", "$type": "color" }
},
"text": {
"default": { "$value": "{neutral.ne100}", "$type": "color" },
Expand All @@ -47,17 +47,34 @@
"default": { "$value": "{neutral.ne900}", "$type": "color" },
"surface": { "$value": "{neutral.ne800}", "$type": "color" },
"dark": { "$value": "{neutral.ne100}", "$type": "color" },
"placeholder": { "$value": "{text.placeholder}", "$type": "color" },
"primary": { "$value": "{primary.pr700}", "$type": "color" },
"secondary": { "$value": "{secondary.se700}", "$type": "color" },
"error": { "$value": "{error.er700}", "$type": "color" },
"warning": { "$value": "{warning.wa700}", "$type": "color" },
"success": { "$value": "{success.su700}", "$type": "color" },
"grey": { "$value": "{neutral.ne600}", "$type": "color" }
"grey": { "$value": "{neutral.ne600}", "$type": "color" },
"disable": { "$value": "{text.disable}", "$type": "color" }
},
"icon": {
"default": { "$value": "{text.default}", "$type": "color" },
"contrastText": { "$value": "{text.contrastText}", "$type": "color" },
"disable": { "$value": "{text.disable}", "$type": "color" },
"error": { "$value": "{text.error}", "$type": "color" },
"light": { "$value": "{text.light}", "$type": "color" },
"link": { "$value": "{text.link}", "$type": "color" },
"linkSelected": { "$value": "{text.linkSelected}", "$type": "color" },
"placeholder": { "$value": "{text.placeholder}", "$type": "color" },
"primary": { "$value": "{text.primary}", "$type": "color" },
"secondary": { "$value": "{text.secondary}", "$type": "color" },
"success": { "$value": "{text.success}", "$type": "color" },
"warning": { "$value": "{text.warning}", "$type": "color" }
},
"stroke": {
"default": { "$value": "{neutral.ne700}", "$type": "color" },
"dark": { "$value": "{neutral.ne100}", "$type": "color" },
"light": { "$value": "{neutral.ne800}", "$type": "color" },
"disable": { "$value": "{text.disable}", "$type": "color" },
"primary": { "$value": "{primary.pr400}", "$type": "color" },
"secondary": { "$value": "{secondary.se400}", "$type": "color" },
"error": { "$value": "{error.er400}", "$type": "color" },
Expand Down
4 changes: 2 additions & 2 deletions libs/design-tokens/tokens/light/color.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@
"default": { "$value": "{primary.pr700}", "$type": "color" },
"hover": { "$value": "{primary.pr800}", "$type": "color" },
"disabled": { "$value": "{neutral.ne300}", "$type": "color" },
"focusRipple": { "$value": "{neutral.ne100}", "$type": "color" },
"focusRipple": { "$value": "{primary.pr500}", "$type": "color" },
"outlinedFocusRipple": { "$value": "{primary.pr700}", "$type": "color" },
"outlinedHover": { "$value": "{primary.pr100}", "$type": "color" }
},
"text": {
"default": { "$value": "{neutral.ne900}", "$type": "color" },
"light": { "$value": "{neutral.ne600}", "$type": "color" },
"placeholder": { "$value": "{neutral.ne400}", "$type": "color" },
"placeholder": { "$value": "{neutral.ne500}", "$type": "color" },
"disable": { "$value": "{neutral.ne500}", "$type": "color" },
"primary": { "$value": "{primary.pr700}", "$type": "color" },
"secondary": { "$value": "{secondary.se700}", "$type": "color" },
Expand Down
29 changes: 12 additions & 17 deletions libs/design-tokens/tokens/light/spacing.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
{
"spacing": {
"xxxsm": { "$value": "2", "$type": "spacing" },
"xxsm": { "$value": "{spacing.xxxsm} * 2", "$type": "spacing" },
"xsm": { "$value": "{spacing.xxxsm} * 3", "$type": "spacing" },
"sm": { "$value": "{spacing.xxxsm} * 4", "$type": "spacing" },
"sml": { "$value": "{spacing.xxxsm} * 6", "$type": "spacing" },
"md": { "$value": "{spacing.xxxsm} * 7", "$type": "spacing" },
"mdl": { "$value": "{spacing.xxxsm} * 8", "$type": "spacing" },
"lg": { "$value": "{spacing.xxxsm} * 10", "$type": "spacing" },
"xlg": { "$value": "{spacing.xxxsm} * 12", "$type": "spacing" },
"xl": { "$value": "{spacing.xxxsm} * 14", "$type": "spacing" },
"xxl": { "$value": "{spacing.xxxsm} * 16", "$type": "spacing" },
"3xl": { "$value": "{spacing.xxxsm} * 18", "$type": "spacing" },
"4xl": { "$value": "{spacing.xxxsm} * 20", "$type": "spacing" },
"5xl": { "$value": "{spacing.xxxsm} * 24", "$type": "spacing" },
"6xl": { "$value": "{spacing.xxxsm} * 32", "$type": "spacing" },
"7xl": { "$value": "{spacing.xxxsm} * 48", "$type": "spacing" },
"8xl": { "$value": "{spacing.xxxsm} * 64", "$type": "spacing" }
"2xs": { "$value": "2", "$type": "spacing" },
"xs": { "$value": "{spacing.2xs} * 2", "$type": "spacing" },
"sm": { "$value": "{spacing.2xs} * 3", "$type": "spacing" },
"md": { "$value": "{spacing.2xs} * 6", "$type": "spacing" },
"lg": { "$value": "{spacing.2xs} * 8", "$type": "spacing" },
"xl": { "$value": "{spacing.2xs} * 12", "$type": "spacing" },
"2xl": { "$value": "{spacing.2xs} * 16", "$type": "spacing" },
"3xl": { "$value": "{spacing.2xs} * 20", "$type": "spacing" },
"4xl": { "$value": "{spacing.2xs} * 24", "$type": "spacing" },
"5xl": { "$value": "{spacing.2xs} * 32", "$type": "spacing" },
"6xl": { "$value": "{spacing.2xs} * 48", "$type": "spacing" },
"7xl": { "$value": "{spacing.2xs} * 64", "$type": "spacing" }
}
}
13 changes: 13 additions & 0 deletions libs/react-ui/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import '../src/styles';
import { createElement } from 'react';

import type { Preview } from '@storybook/react';
import { INITIAL_VIEWPORTS } from 'storybook/viewport';

import { ThemeProvider } from '../src/theme/ThemeProvider';

const dsViewports = {
mobile: { name: 'Mobile', styles: { width: '375px', height: '812px' }, type: 'mobile' },
tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' }, type: 'tablet' },
desktop: { name: 'Desktop', styles: { width: '1440px', height: '900px' }, type: 'desktop' },
} as const;

const preview: Preview = {
parameters: {
controls: {
Expand All @@ -16,6 +23,12 @@ const preview: Preview = {
date: /Date$/i,
},
},
viewport: {
options: { ...dsViewports, ...INITIAL_VIEWPORTS },
},
},
initialGlobals: {
viewport: { value: 'responsive' },
},
tags: ['autodocs'],
globalTypes: {
Expand Down
18 changes: 8 additions & 10 deletions libs/react-ui/src/components/box/Box.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ const meta = {
tags: ['autodocs'],
parameters: {
layout: 'centered',
// TODO(a11y): 위반 수정 후 disable 제거
a11y: { disable: true },
},
args: {
children: '박스 내용',
Expand Down Expand Up @@ -107,19 +105,19 @@ export const WithBackground: Story = {
<div style={rowStyle}>
{(
[
'background.primary',
'background.secondary',
'background.success',
'background.error',
'background.warning',
'background.grey',
{ token: 'background.primary', fg: '#fff' },
{ token: 'background.secondary', fg: '#fff' },
{ token: 'background.success', fg: '#fff' },
{ token: 'background.error', fg: '#fff' },
{ token: 'background.warning', fg: '#fff' },
{ token: 'background.grey', fg: 'var(--ds-text-default)' },
] as const
).map((token) => (
).map(({ token, fg }) => (
<Box
key={token}
bg={token}
p="md"
style={{ borderRadius: '6px', color: '#fff', fontSize: '12px', whiteSpace: 'nowrap' }}
style={{ borderRadius: '6px', color: fg, fontSize: '12px', whiteSpace: 'nowrap' }}
>
{token}
</Box>
Expand Down
20 changes: 10 additions & 10 deletions libs/react-ui/src/components/button-base/button-base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
========================= */
$sizes: (
sm: (
px: var(--ds-spacing-sml),
py: var(--ds-spacing-xsm),
px: var(--ds-spacing-md),
py: var(--ds-spacing-sm),
radius: var(--ds-radius-sm),
ff: var(--ds-body-small-strong-font-family),
fs: var(--ds-body-small-strong-font-size),
Expand All @@ -15,7 +15,7 @@ $sizes: (
lh: var(--ds-body-small-strong-line-height),
),
md: (
px: var(--ds-spacing-xlg),
px: var(--ds-spacing-xl),
py: var(--ds-spacing-sm),
radius: var(--ds-radius-md),
ff: var(--ds-body-medium-strong-font-family),
Expand All @@ -25,8 +25,8 @@ $sizes: (
lh: var(--ds-body-medium-strong-line-height),
),
lg: (
px: var(--ds-spacing-xxl),
py: var(--ds-spacing-sml),
px: var(--ds-spacing-2xl),
py: var(--ds-spacing-md),
radius: var(--ds-radius-lg),
ff: var(--ds-body-large-strong-font-family),
fs: var(--ds-body-large-strong-font-size),
Expand Down Expand Up @@ -96,7 +96,7 @@ $colors: (
--ui-btn-font-size: #{map.get($s, fs)};
--ui-btn-font-weight: #{map.get($s, fw)};
--ui-btn-letter-spacing: #{map.get($s, ls)};
--ui-btn-line-height: calc(#{map.get($s, lh)} * 1px);
--ui-btn-line-height: #{map.get($s, lh)};
}

@mixin define-color-palette($color-key) {
Expand Down Expand Up @@ -125,17 +125,17 @@ $colors: (

.ui-button {
/* shape / spacing */
--ui-btn-px: var(--ds-spacing-xlg);
--ui-btn-px: var(--ds-spacing-xl);
--ui-btn-py: var(--ds-spacing-sm);
--ui-btn-radius: var(--ds-radius-md);
--ui-btn-gap: var(--ds-spacing-xsm);
--ui-btn-gap: var(--ds-spacing-sm);

/* typography (default = md strong) */
--ui-btn-font-family: var(--ds-body-medium-strong-font-family);
--ui-btn-font-size: var(--ds-body-medium-strong-font-size);
--ui-btn-font-weight: var(--ds-body-medium-strong-font-weight);
--ui-btn-letter-spacing: var(--ds-body-medium-strong-letter-spacing);
--ui-btn-line-height: calc(var(--ds-body-medium-strong-line-height) * 1px);
--ui-btn-line-height: var(--ds-body-medium-strong-line-height);

/* interactive */
--ui-btn-bg: transparent;
Expand All @@ -154,7 +154,7 @@ $colors: (
--ui-btn-focus-halo-color: var(--ds-primary-btn-focus-ripple);
--ui-btn-focus-width: var(--ds-semantic-border-focus);
--ui-btn-focus-outline-width: var(--ds-border-primary-width);
--ui-btn-focus-offset: var(--ds-spacing-xxsm);
--ui-btn-focus-offset: var(--ds-spacing-xs);

display: inline-flex;
align-items: center;
Expand Down
2 changes: 0 additions & 2 deletions libs/react-ui/src/components/button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ const meta = {
tags: ['autodocs'],
parameters: {
layout: 'centered',
// TODO(a11y): 위반 수정 후 disable 제거
a11y: { disable: true },
},
args: {
children: 'Button',
Expand Down
3 changes: 1 addition & 2 deletions libs/react-ui/src/components/fab/Fab.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ const meta = {
tags: ['autodocs'],
parameters: {
layout: 'centered',
// TODO(a11y): 위반 수정 후 disable 제거
a11y: { disable: true },
},
args: {
'aria-label': 'Action',
color: 'primary',
size: 'lg',
shape: 'circular',
Expand Down
Loading
Loading