feat(button): Redesign Button component based on 5th generation design system - #263
Conversation
🦋 Changeset detectedLatest commit: 1f95a0a The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
Yeom-JinHo
left a comment
There was a problem hiding this comment.
Radix Slot만 확인해주시겠어요~?
나머지는 좋습니다 : )
| base: { | ||
| vars: { | ||
| [buttonOrange]: '#FF7C27', | ||
| [buttonGradient]: 'linear-gradient(225deg, #FF4500 0%, #FFB24D 100%)', |
There was a problem hiding this comment.
여기 추후 토큰이 그라디언트 자체로 끼워지는건가요?
color.gradient?
There was a problem hiding this comment.
@Yeom-JinHo 넵넵 color.5th.gradient 처럼 5기 전용 그라디언트 토큰으로 들어가게 될 것 같습니다 hover 상태를 그라디언트 색상으로 진행하고 싶어하시더라고요!!
| <Comp ref={ref} type={type} className={className} disabled={disabled} {...props}> | ||
| {leftIcon && <span className={styles.iconWrapper}>{leftIcon}</span>} | ||
| {children} | ||
| {rightIcon && <span className={styles.iconWrapper}>{rightIcon}</span>} | ||
| </Comp> |
There was a problem hiding this comment.
There was a problem hiding this comment.
@Yeom-JinHo 진호님 감사합니다!! 버튼 컴포넌트가 이제 leftIcon, rightIcon이 있는 Button은 다중 자식 구조라서 Slottable을 적용하여 수정해서 재 반영해두겠습니다!! 리뷰 감사합니다 ~!
| [buttonOrange]: '#FF7C27', | ||
| [buttonGradient]: 'linear-gradient(225deg, #FF4500 0%, #FFB24D 100%)', | ||
| [buttonRed]: '#FE4E07', | ||
| }, |
There was a problem hiding this comment.
이것도 마찬가지로,
#258
에서 이미 semantic token 을 구축했으니,
여기만 독자적인 스타일을 쓰는 게 아니라,
시맨틱 토큰이 활용한 지 검토해주세요!
| }, | ||
| [ButtonSize.md]: { | ||
| height: '40px', | ||
| padding: '0 12px', |
There was a problem hiding this comment.
이것도 마찬가지로.
vars.spacing.component.md 처럼
시맨틱 토큰에 해당 내용이 있으니 확인해서 사용해주시면 좋을 것 같습니다.
| pointerEvents: 'none', | ||
| export const buttonOrange = createVar(); | ||
| export const buttonGradient = createVar(); | ||
| export const buttonRed = createVar(); |
There was a problem hiding this comment.
There was a problem hiding this comment.
지훈님 말씀처럼 가능한 토큰 시스템 이용해주시면 v2 token으로 마이그레이션할 때도 수월할 것 같아요!
| cursor: 'not-allowed', | ||
| pointerEvents: 'none', | ||
| border: 'none', | ||
| background: color.gray500, |
There was a problem hiding this comment.
backgroundColor: color.gray500,
가 이미 있어서 스타일이 중복되는 것 같습니다
| fontFamily: vars.typography.fontFamily, | ||
| ':focus-visible': { | ||
| outline: `2px solid ${vars.color.border.focus}`, | ||
| outline: `2px solid ${buttonOrange}`, |
There was a problem hiding this comment.
포커스링은 브랜드 컬러보다는,
blue 계열이 일반적으로 더 적합한 것 같습니다 (WCAG 구분 가능성)
@3o14 님 크로스체크 부탁드립니다
| primary: '#FF7C27', | ||
| secondary: '#FE4E07', | ||
| background: '#000000', | ||
| text: '#000000', |
There was a problem hiding this comment.
이거...
background 와 text 색이 같은데 이러면 색상이 잘 보일까요?
…accessibility improvements (#287) * chore: upgrade pnpm to 10.33.0 (#211) * fix(ci): add --if-present flag to pnpm filter commands (#238) * chore(commitlint): simplify config to conventional preset only (#237) * chore(husky): update branch naming rules (#239) * docs: sync convention sections with new rules (#240) * docs(#218): v1 token usage audit (#243) * fix(build): preserve css imports in sideEffects (#228) * fix(build): preserve css imports in sideEffects * fix(build): preserve css side effects in template * chore(changeset): add css sideEffects fix note * chore(changeset): fix package list and description * docs: sync README badges, license year, and CLAUDE.md pnpm version (#242) * docs: token architecture and naming convention (#246) * test(flex): strengthen contract coverage (#241) * refactor(flex): align story options with constants - replace hardcoded story options with Flex constants - keep Storybook controls aligned with the current contract values - reduce the risk of drift between implementation and story definitions * test(flex): strengthen contract coverage - align tests with the current Flex contract in side - use constants as the source of truth for direction, align, justify, and wrap cases - add coverage for normal values, asChild behavior, style overrides, ref forwarding, and common consumer usage patterns - verify the Flex test suite passes at the package level * test(flex): translate test descriptions to english --------- Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> * chore: remove unused eslint type declarations (#249) * chore: add build, typecheck, test:coverage scripts to root * chore: add missing scripts to packages * chore: sort scripts order across all packages * chore: remove plugin-figma-codegen package (#251) * feat(Button): 버튼 컴포넌트의 최소 WAI-ARIA 기본 접근성 개선 (#244) * chore: remove per-package .storybook configs (#250) * feat(tokens): define primitive token foundations (#248) * feat: primitive token * fix: ci error * docs: update spacing primitive token * docs: update radius primitive token * fix(Tooltip): 접근성(a11y) 개선 및 스타일 코드 개선 (#245) * fix(tooltip): add aria-label for screen readers * refactor(tooltip): migrate styles to vanilla-extract recipe * test(tooltip): improve accessibility test coverage * refactor(tooltip): use enum instead of string literal * fix(tooltip): resolve type import error * test(tooltip): translate test descriptions to English * chore(tooltip): remove export and add changeset * chore: enforce package.json consistency across the workspace (#252) * chore(chip): normalize package.json structure * chore(packages): align package.json across workspace * chore(tooling): add package.json consistency checker * chore(packages): add clean script to template and accordion * docs(claude): document package consistency policy * fix(tooling): tighten allowlist fieldPath matching * fix(tooling): harden policy allowlist validation * feat(tooling): police sideEffects field in package policy * fix(ci): mark consistency install step as non-blocking * chore: drop per-package storybook scripts * chore(tooling): promote test to hard rule, drop optionalScripts * fix(tooling): allow publishConfig hard rules to be allowlisted * docs(claude): sync package policy with enforced rules * chore(deps): sync lockfile with workspace catalogs * chore(tooling): namespace lint scripts (lint:biome, lint:package) * feat(tokens): introduce semantic token foundation and brand color alias strategy (#258) * feat(tokens): update primitive token JSON with extended scale Add missing color shades (gray.950, status colors), expanded radius, spacing, and typography scales to align with semantic token requirements. Confidence: high Scope-risk: narrow * feat(tokens): add semantic token JSON draft in DTCG format Introduce dark-mode semantic tokens for color, spacing, radius, and typography. All values reference primitive aliases only — no raw hex or px values. Each token includes two usage-scenario descriptions. Light-mode tokens are deferred (tokens/semantic/light/ has .gitkeep only). Confidence: high Scope-risk: narrow * feat(tokens): redesign CSS contract to match semantic token structure Rewrite vars contract to reflect semantic layers (color.background.*, color.foreground.*, color.accent.*, spacing.component.*, spacing.layout.*, radius.component.*, radius.layout.*). Extract darkBaseColor shared object and define four brand theme variants (default, 1st–4th). Constraint: dark mode is the default; light mode is deferred Rejected: per-theme contract files | increases maintenance surface Confidence: high Scope-risk: broad * feat(button): migrate styles to new semantic vars paths Update all token references to match the redesigned CSS contract: color.primary → color.accent.default, spacing.sm/lg → spacing.component.*, radius.md → radius.component.md, focus ring wired to color.border.focus. Confidence: high Scope-risk: narrow * chore(tokens): mark unused TS primitive exports as deprecated Add @deprecated JSDoc to opacity, zIndex, borderWidth/borderStyle, shadows, spacing, breakpoints, grid, and responsiveStyle. These TS source files will be removed alongside all other TS primitives once the JSON token pipeline is complete and components have migrated to vars.*. Directive: do not add new consumers of these exports Confidence: high Scope-risk: narrow * chore: changeset * feat(tokens): add brand primitive and update accent semantic alias - Add color.brand.{default,hover,subtle} to primitive/color.json with current cohort values (#ffb24d, #d9963f, #3b2005) - Update semantic accent.* to reference {color.brand.*} instead of blue to reflect actual brand color brand primitive acts as the single update point per cohort; semantic tokens and components require no changes on rebranding. * feat(tokens): add brandColor and update defaultTheme accent to orange - Export brandColor const from colors.ts (mirrors primitive brand.*) - Import brandColor in themes.css.ts and apply to defaultTheme accent replacing hardcoded blue values Note: colors.ts and themes.css.ts are deprecated and will be removed once the Style Dictionary pipeline is in place. * fix(theme): correct assignInlineVars contract mapping in ThemeProvider assignInlineVars(vars.color, theme) was passing ThemeColor { primary, secondary, background, text, gradient } to a contract that expects { accent, foreground, border, status, ... }, causing a TypeScript error and no-op CSS variable assignment. Fix by scoping to vars.color.accent and mapping ThemeColor fields: - primary → accent.default - secondary → accent.hover - background → accent.subtle * docs(tokens): add semantic token proposal with rebrand strategy - Document semantic token structure (color, spacing, radius, typography) - Add rebranding flow section explaining brand primitive alias pattern: update color.brand.* in primitive/color.json only on cohort change - Note W3C Design Token format compatibility with Token Studio v2 and Style Dictionary v4 for upcoming Figma pipeline integration * fix(tokens): remove duplicate named exports from themes.css.ts theme1st–theme4th were exported from both colors.ts (ThemeColor objects) and themes.css.ts (createGlobalTheme return values), causing TS2308 ambiguous re-export errors in src/index.ts. createGlobalTheme calls are CSS side effects; their return values are not consumed by any external code, so export keywords are removed. * Release (#256) Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: 이원주 <101818687+3o14@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> * chore: update changeset BC * docs: update semantic-proposal docs * docs: modify semantic proposal muted token * fix: modify spacing, radius themes * chore: update deprecated annotation --------- Co-authored-by: Evan <clcl6084@gmail.com> Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> * feat(tokens): add Style Dictionary v5 pipeline with W3C DTCG primitive tokens (#261) * feat: style dictionary pipeline * fix(tokens): adopt W3C DTCG format for primitives and fix token-names publish export * fix: restore broken pnpm-lock.yaml after merge conflict resolution * docs(md): unify ai context document (#257) * feat(Card): add ghost variant with transparent background and no border (#265) * feat(tokens): setup design token transformation pipeline and CI automation (#270) * chore: formatting * feat(tokens): setup design token transformation pipeline and CI automation * ci: commit transformed tokens * fix(accordion): add single/multiple open mode support(#255) (#254) * feat(accordion): add single/multiple open mode support * chore(accordion): add changeset for single/multiple mode feature * fix(accordian): improve controlled state handling and add initialValue prop * refactor(tooltip): replace trigger prop and improve WCAG compliance (#259) * refactor(tooltip): rename useTooltip.tsx to useTooltip.ts * perf(tooltip): throttle scroll/resize position update with rAF * feat(tooltip): support keyboard focus for hover trigger * refactor(tooltip): replace trigger prop with MUI-style listener controls * fix(tooltip): remove redundant isVisible condition in portal className * refactor(tooltip): remove redundant code and improve WCAG compliance - Remove always-true visible class from portal (portal only renders when isVisible=true) - Remove associated CSS opacity/transform/transition/pointerEvents overrides - Remove redundant position:fixed from inline styles (already in CSS base) - Remove redundant --tooltip-bg-color JS fallback (CSS already has var fallback) - Conditionally apply tabIndex=0 only when focus listener is active (WCAG 2.4.7) - Apply styles.button class only when asChild=false (WCAG 1.4.3) * chore: downgrade esbuild to ~0.24.0 to fix Storybook manager build esbuild 0.27 changed its behavior to refuse transforming syntax for old browser targets (es2020, chrome87). Storybook 8.5 manager build uses these hardcoded targets and breaks with 0.27. Downgrade to 0.24 as a temporary fix until Storybook is upgraded to support esbuild 0.27. * Revert "chore: downgrade esbuild to ~0.24.0 to fix Storybook manager build" This reverts commit e3e8a95. * refactor(tooltip): remove disableFocusListener prop Focus listener is always required for keyboard accessibility (WCAG 2.1.1). Removing this prop enforces accessible defaults and simplifies the API. * feat(tooltip): add fade-in animation on mount Uses @Keyframes instead of CSS transition to correctly animate on DOM insertion. Respects prefers-reduced-motion for accessibility (WCAG 2.3.3). * fix(tooltip): prevent focus event from interfering with click-controlled open state On first click, the browser fires focus before click, causing onFocus→requestOpen to set open=true before the onClick toggle sets it back to false. Fixed by tracking mousedown state so focus triggered by mouse click is ignored (keyboard focus still works). * chore: add changeset for tooltip API refactor * refactor(tooltip): restore disableFocusListener, remove hardcoded tabIndex, spread rest props - Restore disableFocusListener prop for click-only controlled mode support - Remove hardcoded tabIndex={0} to respect consumer element focusability - Spread ...rest onto wrapper so consumers can pass tabIndex, role, aria-* etc. - Merge className from rest with internal styles via clsx * test(tooltip): add missing coverage for mouseUp, scroll/resize, invalid placement * refactor(tooltip): apply PR review feedback - Change changeset from minor to major (trigger prop removal is breaking change) - Compose user event handlers with internal handlers via composeHandlers helper - Make placement and gap optional in useTooltip with default values * fix(tooltip): guard setInternalOpen with isControlled check in controlled mode Co-Authored-By: MinjiJeon <jinnyjeon@sweetspot.co.kr> --------- Co-authored-by: MinjiJeon <jinnyjeon@sweetspot.co.kr> * chore(biome): remove unsafe flag from claude hooks (#267) * chore: remove .github/decisions directory (#269) * chore(storybook): upgrade to v10.3.5 (#276) * fix(husky): update pre-push branch regex for dev (#278) * chore: add title option to release workflow (#277) * chore(templates): simplify component template to minimal pattern (#268) * chore(tokens): token JSON file integration (#274) * chore: .claudeingore file (#279) * feat(button): Redesign Button component based on 5th generation design system (#263) * feat(button): 5세대 디자인 시스템 기반 버튼 컴포넌트 전면 개편 * feat(button): add to changeset docs * fix(Button): use Slottable for multi-child asChild compatibility * fix(Button): apply to typecheck CI * refactor(theme): replace brand-color ThemeProvider with light/dark mode toggle (#282) * chore: replace existing data-theme * chore: update theme provider render and themes.css.ts * chore: claude allow reading tokens/dist * chore: update theme packages * chore: update themes css * chore: changeset * chore: theme utils test * chore: update changeset * chore: delete optional * chore: modify changeset * chore: add TODO comments for pending light mode * chore: widen tokens dist read permission scope * chore: resolve conflicts from main into dev (#286) * Release (#256) Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: 이원주 <101818687+3o14@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> * Version Packages (#260) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: add title option to release workflow (#266) --------- Co-authored-by: Evan <clcl6084@gmail.com> Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> Co-authored-by: y09n <euihyun.yang.9x@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: Evan <clcl6084@gmail.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> Co-authored-by: MinjiJeon <jinnyjeon@sweetspot.co.kr> Co-authored-by: y09n <euihyun.yang.9x@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* chore: upgrade pnpm to 10.33.0 (#211) * fix(ci): add --if-present flag to pnpm filter commands (#238) * chore(commitlint): simplify config to conventional preset only (#237) * chore(husky): update branch naming rules (#239) * docs: sync convention sections with new rules (#240) * docs(#218): v1 token usage audit (#243) * fix(build): preserve css imports in sideEffects (#228) * fix(build): preserve css imports in sideEffects * fix(build): preserve css side effects in template * chore(changeset): add css sideEffects fix note * chore(changeset): fix package list and description * docs: sync README badges, license year, and CLAUDE.md pnpm version (#242) * docs: token architecture and naming convention (#246) * test(flex): strengthen contract coverage (#241) * refactor(flex): align story options with constants - replace hardcoded story options with Flex constants - keep Storybook controls aligned with the current contract values - reduce the risk of drift between implementation and story definitions * test(flex): strengthen contract coverage - align tests with the current Flex contract in side - use constants as the source of truth for direction, align, justify, and wrap cases - add coverage for normal values, asChild behavior, style overrides, ref forwarding, and common consumer usage patterns - verify the Flex test suite passes at the package level * test(flex): translate test descriptions to english --------- Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> * chore: remove unused eslint type declarations (#249) * chore: add build, typecheck, test:coverage scripts to root * chore: add missing scripts to packages * chore: sort scripts order across all packages * chore: remove plugin-figma-codegen package (#251) * feat(Button): 버튼 컴포넌트의 최소 WAI-ARIA 기본 접근성 개선 (#244) * chore: remove per-package .storybook configs (#250) * feat(tokens): define primitive token foundations (#248) * feat: primitive token * fix: ci error * docs: update spacing primitive token * docs: update radius primitive token * fix(Tooltip): 접근성(a11y) 개선 및 스타일 코드 개선 (#245) * fix(tooltip): add aria-label for screen readers * refactor(tooltip): migrate styles to vanilla-extract recipe * test(tooltip): improve accessibility test coverage * refactor(tooltip): use enum instead of string literal * fix(tooltip): resolve type import error * test(tooltip): translate test descriptions to English * chore(tooltip): remove export and add changeset * chore: enforce package.json consistency across the workspace (#252) * chore(chip): normalize package.json structure * chore(packages): align package.json across workspace * chore(tooling): add package.json consistency checker * chore(packages): add clean script to template and accordion * docs(claude): document package consistency policy * fix(tooling): tighten allowlist fieldPath matching * fix(tooling): harden policy allowlist validation * feat(tooling): police sideEffects field in package policy * fix(ci): mark consistency install step as non-blocking * chore: drop per-package storybook scripts * chore(tooling): promote test to hard rule, drop optionalScripts * fix(tooling): allow publishConfig hard rules to be allowlisted * docs(claude): sync package policy with enforced rules * chore(deps): sync lockfile with workspace catalogs * chore(tooling): namespace lint scripts (lint:biome, lint:package) * feat(tokens): introduce semantic token foundation and brand color alias strategy (#258) * feat(tokens): update primitive token JSON with extended scale Add missing color shades (gray.950, status colors), expanded radius, spacing, and typography scales to align with semantic token requirements. Confidence: high Scope-risk: narrow * feat(tokens): add semantic token JSON draft in DTCG format Introduce dark-mode semantic tokens for color, spacing, radius, and typography. All values reference primitive aliases only — no raw hex or px values. Each token includes two usage-scenario descriptions. Light-mode tokens are deferred (tokens/semantic/light/ has .gitkeep only). Confidence: high Scope-risk: narrow * feat(tokens): redesign CSS contract to match semantic token structure Rewrite vars contract to reflect semantic layers (color.background.*, color.foreground.*, color.accent.*, spacing.component.*, spacing.layout.*, radius.component.*, radius.layout.*). Extract darkBaseColor shared object and define four brand theme variants (default, 1st–4th). Constraint: dark mode is the default; light mode is deferred Rejected: per-theme contract files | increases maintenance surface Confidence: high Scope-risk: broad * feat(button): migrate styles to new semantic vars paths Update all token references to match the redesigned CSS contract: color.primary → color.accent.default, spacing.sm/lg → spacing.component.*, radius.md → radius.component.md, focus ring wired to color.border.focus. Confidence: high Scope-risk: narrow * chore(tokens): mark unused TS primitive exports as deprecated Add @deprecated JSDoc to opacity, zIndex, borderWidth/borderStyle, shadows, spacing, breakpoints, grid, and responsiveStyle. These TS source files will be removed alongside all other TS primitives once the JSON token pipeline is complete and components have migrated to vars.*. Directive: do not add new consumers of these exports Confidence: high Scope-risk: narrow * chore: changeset * feat(tokens): add brand primitive and update accent semantic alias - Add color.brand.{default,hover,subtle} to primitive/color.json with current cohort values (#ffb24d, #d9963f, #3b2005) - Update semantic accent.* to reference {color.brand.*} instead of blue to reflect actual brand color brand primitive acts as the single update point per cohort; semantic tokens and components require no changes on rebranding. * feat(tokens): add brandColor and update defaultTheme accent to orange - Export brandColor const from colors.ts (mirrors primitive brand.*) - Import brandColor in themes.css.ts and apply to defaultTheme accent replacing hardcoded blue values Note: colors.ts and themes.css.ts are deprecated and will be removed once the Style Dictionary pipeline is in place. * fix(theme): correct assignInlineVars contract mapping in ThemeProvider assignInlineVars(vars.color, theme) was passing ThemeColor { primary, secondary, background, text, gradient } to a contract that expects { accent, foreground, border, status, ... }, causing a TypeScript error and no-op CSS variable assignment. Fix by scoping to vars.color.accent and mapping ThemeColor fields: - primary → accent.default - secondary → accent.hover - background → accent.subtle * docs(tokens): add semantic token proposal with rebrand strategy - Document semantic token structure (color, spacing, radius, typography) - Add rebranding flow section explaining brand primitive alias pattern: update color.brand.* in primitive/color.json only on cohort change - Note W3C Design Token format compatibility with Token Studio v2 and Style Dictionary v4 for upcoming Figma pipeline integration * fix(tokens): remove duplicate named exports from themes.css.ts theme1st–theme4th were exported from both colors.ts (ThemeColor objects) and themes.css.ts (createGlobalTheme return values), causing TS2308 ambiguous re-export errors in src/index.ts. createGlobalTheme calls are CSS side effects; their return values are not consumed by any external code, so export keywords are removed. * Release (#256) Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: 이원주 <101818687+3o14@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> * chore: update changeset BC * docs: update semantic-proposal docs * docs: modify semantic proposal muted token * fix: modify spacing, radius themes * chore: update deprecated annotation --------- Co-authored-by: Evan <clcl6084@gmail.com> Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> * feat(tokens): add Style Dictionary v5 pipeline with W3C DTCG primitive tokens (#261) * feat: style dictionary pipeline * fix(tokens): adopt W3C DTCG format for primitives and fix token-names publish export * fix: restore broken pnpm-lock.yaml after merge conflict resolution * docs(md): unify ai context document (#257) * feat(Card): add ghost variant with transparent background and no border (#265) * feat(tokens): setup design token transformation pipeline and CI automation (#270) * chore: formatting * feat(tokens): setup design token transformation pipeline and CI automation * ci: commit transformed tokens * fix(accordion): add single/multiple open mode support(#255) (#254) * feat(accordion): add single/multiple open mode support * chore(accordion): add changeset for single/multiple mode feature * fix(accordian): improve controlled state handling and add initialValue prop * refactor(tooltip): replace trigger prop and improve WCAG compliance (#259) * refactor(tooltip): rename useTooltip.tsx to useTooltip.ts * perf(tooltip): throttle scroll/resize position update with rAF * feat(tooltip): support keyboard focus for hover trigger * refactor(tooltip): replace trigger prop with MUI-style listener controls * fix(tooltip): remove redundant isVisible condition in portal className * refactor(tooltip): remove redundant code and improve WCAG compliance - Remove always-true visible class from portal (portal only renders when isVisible=true) - Remove associated CSS opacity/transform/transition/pointerEvents overrides - Remove redundant position:fixed from inline styles (already in CSS base) - Remove redundant --tooltip-bg-color JS fallback (CSS already has var fallback) - Conditionally apply tabIndex=0 only when focus listener is active (WCAG 2.4.7) - Apply styles.button class only when asChild=false (WCAG 1.4.3) * chore: downgrade esbuild to ~0.24.0 to fix Storybook manager build esbuild 0.27 changed its behavior to refuse transforming syntax for old browser targets (es2020, chrome87). Storybook 8.5 manager build uses these hardcoded targets and breaks with 0.27. Downgrade to 0.24 as a temporary fix until Storybook is upgraded to support esbuild 0.27. * Revert "chore: downgrade esbuild to ~0.24.0 to fix Storybook manager build" This reverts commit e3e8a95. * refactor(tooltip): remove disableFocusListener prop Focus listener is always required for keyboard accessibility (WCAG 2.1.1). Removing this prop enforces accessible defaults and simplifies the API. * feat(tooltip): add fade-in animation on mount Uses @Keyframes instead of CSS transition to correctly animate on DOM insertion. Respects prefers-reduced-motion for accessibility (WCAG 2.3.3). * fix(tooltip): prevent focus event from interfering with click-controlled open state On first click, the browser fires focus before click, causing onFocus→requestOpen to set open=true before the onClick toggle sets it back to false. Fixed by tracking mousedown state so focus triggered by mouse click is ignored (keyboard focus still works). * chore: add changeset for tooltip API refactor * refactor(tooltip): restore disableFocusListener, remove hardcoded tabIndex, spread rest props - Restore disableFocusListener prop for click-only controlled mode support - Remove hardcoded tabIndex={0} to respect consumer element focusability - Spread ...rest onto wrapper so consumers can pass tabIndex, role, aria-* etc. - Merge className from rest with internal styles via clsx * test(tooltip): add missing coverage for mouseUp, scroll/resize, invalid placement * refactor(tooltip): apply PR review feedback - Change changeset from minor to major (trigger prop removal is breaking change) - Compose user event handlers with internal handlers via composeHandlers helper - Make placement and gap optional in useTooltip with default values * fix(tooltip): guard setInternalOpen with isControlled check in controlled mode Co-Authored-By: MinjiJeon <jinnyjeon@sweetspot.co.kr> --------- Co-authored-by: MinjiJeon <jinnyjeon@sweetspot.co.kr> * chore(biome): remove unsafe flag from claude hooks (#267) * chore: remove .github/decisions directory (#269) * chore(storybook): upgrade to v10.3.5 (#276) * fix(husky): update pre-push branch regex for dev (#278) * chore: add title option to release workflow (#277) * chore(templates): simplify component template to minimal pattern (#268) * chore(tokens): token JSON file integration (#274) * chore: .claudeingore file (#279) * feat(button): Redesign Button component based on 5th generation design system (#263) * feat(button): 5세대 디자인 시스템 기반 버튼 컴포넌트 전면 개편 * feat(button): add to changeset docs * fix(Button): use Slottable for multi-child asChild compatibility * fix(Button): apply to typecheck CI * refactor(theme): replace brand-color ThemeProvider with light/dark mode toggle (#282) * chore: replace existing data-theme * chore: update theme provider render and themes.css.ts * chore: claude allow reading tokens/dist * chore: update theme packages * chore: update themes css * chore: changeset * chore: theme utils test * chore: update changeset * chore: delete optional * chore: modify changeset * chore: add TODO comments for pending light mode * chore: widen tokens dist read permission scope * chore: resolve conflicts from main into dev (#286) * Release (#256) Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: 이원주 <101818687+3o14@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> * Version Packages (#260) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: add title option to release workflow (#266) --------- Co-authored-by: Evan <clcl6084@gmail.com> Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: YOUNGBEEN, KIM <62539910+KYBee@users.noreply.github.com> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> Co-authored-by: y09n <euihyun.yang.9x@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix(tokens): restore token CSS chain and add ./styles.css entrypoint (#291) packages/tokens/tsup.config.ts was the only package that redefined the root tsup config instead of inheriting it, and it omitted the vanilla-extract esbuild plugin. Two failures followed: - contract.css.ts was bundled as plain TS, so importing dist threw at runtime ("Styles were unable to be assigned to a file"). This also broke @sipe-team/side, which re-exports @sipe-team/tokens. - The --side-* bridge CSS was never emitted, and no CSS entrypoint existed to load the token values. Button — the only component consuming vars.* — rendered with padding, border-radius, font-size, font-weight, font-family and gap all collapsed to initial values. Inherit the root tsup config, and ship a single ./styles.css that concatenates the Style Dictionary value layer with the vanilla-extract bridge — splitting them would let a consumer load half the chain and break silently. sideEffects moves from false to ["**/*.css"] for a separate reason: it is what stops a downstream bundler from dropping the consumer's `import '@sipe-team/tokens/styles.css'`. It was not the cause of the missing bridge CSS (verified: the bridge emits fine under sideEffects:false once the plugin is present). 17 of 21 packages already use this value. tokens.yaml called `build:tokens` standalone, which no longer works now that the Style Dictionary step concatenates the tsup-emitted bridge — point it at `build` (tsup && build:tokens). Verified: dangling var() references in the built Storybook bundle go from 11 to 0; importing tokens/dist no longer throws; a clean checkout running the Tokens workflow's commands exits 0. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * build(release): gate publish behind export map validation (#289) * fix(accordion,grid): compile vanilla-extract styles into dist Both packages declared a local tsup config without the vanilla-extract plugin, so their `.css.ts` styles were never compiled and the `dist/index.css` behind `./styles.css` never made it into the tarball. Reuse the shared root config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(reset): point reset.css export at the emitted stylesheet The export referenced `./dist/reset.css`, but the build emits `./dist/index.css`, so `@sipe-team/reset/reset.css` failed to resolve for consumers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(tokens): emit resolvable token-names barrel declarations The generated barrel re-exported `./primitive` and `./semantic` without runtime extensions, so `@sipe-team/tokens/token-names` failed to resolve under node16 ESM. Declaration files need the extension; the types-only semantic layer needs no runtime module, since TypeScript resolves `./semantic.js` to `semantic.d.ts` by extension substitution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * build(release): gate publish behind publint and attw Packages point `exports` at `src/` and swap it for `dist/` via `publishConfig.exports`, a pnpm-only behaviour. The published export map is therefore never exercised by a local build, typecheck, or test run — which is how accordion, grid, reset and tokens all shipped export maps that do not resolve. Pack every package with pnpm and validate the resulting tarball, the same bytes the registry receives. `npm pack` cannot be used: it ignores the publishConfig swap, so every entrypoint reports as unresolvable. CSS subpaths are excluded from attw only, since stylesheets never carry type declarations; publint still proves they are in the tarball. `changeset publish` now runs behind this check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: run the publishability gate on pull requests Gating only at publish time would surface a broken export map after the version PR is already merged. As a parallel job it costs no extra wall-clock, and it gates the changesets version PR itself. The work is skipped when the diff cannot affect a tarball, while the job still runs so it stays usable as a required check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: serialize releases with a concurrency group Two merges landing while a release is in flight would run `changeset publish` concurrently against the registry. Cancellation stays off: interrupting a publish mid-flight is how packages end up half-released. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: drop the paths filter from the publishability gate Skipping the gate when the diff could not affect a tarball took an eleven-line diff step, two step-level conditions, and a full-depth checkout. It bought only runner time on docs-only pull requests — the job runs alongside CI, so it never cost wall-clock to begin with. Not worth the machinery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: run the publishability check as its own release step The `release` script existed only because changesets/action does not run its `publish` input through a shell, so the check could not be chained onto it. A step before the action gates the publish just as well — a failure there fails the job, so the action never runs. That drops the script, and with it the footgun of a `pnpm release` that looks like a dry run and is not. `pnpm lint:publish` stays, so the gate is still runnable locally. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(www): render workspace components in Docusaurus and document Accordion The docs site had no path for rendering a workspace component: www declared no @sipe-team dependency, and workspace `exports` resolves to raw `src/*.ts`, which webpack cannot consume. Add the vanilla-extract webpack plugin so Docusaurus compiles the packages' `.css.ts` from source — docs pages import @sipe-team/* directly, with no prebuilt dist, alias table, CSS injection, or build ordering. Adding a component is then just a www dependency plus its MDX page. - add Preview: renders children server-side with a "Show code" toggle. No react-live, no BrowserOnly — an example that only appeared after hydration would not prove the component server-renders - accordion.mdx with hand-written prop tables read off the source. No prop extraction, so packages/ stays untouched - _TEMPLATE.md fixes the five core sections; Accessibility and Known limitations are optional trailing sections a component adds when warranted Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(www): give Preview a dark stage and tighten its frame Dark-only components landed as a dark card floating on a light neutral frame, which read as a broken render. Add an opt-in `theme="dark"` to Preview that swaps the stage to a dark canvas, so the example reads as deliberate; the Accordion examples use it. Also compact the stage padding and fold the "Show code" toggle into the card as a left-aligned footer instead of a floating right-aligned button. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(www): document Button, the first vars-consuming component (#298) * docs(www): document Button and make the token chain survive production Button is the only component that reads `vars`, so it's the first to need the Style Dictionary value layer — and it exposed a production-only break: every `var(--side-*)` resolved to nothing while dev worked and hid it. Root cause: under source compilation the token bridge was emitted twice — once by the injected `@sipe-team/tokens/styles.css`, and again by vanilla-extract recompiling tokens' `themes.css.ts` through Button's `vars` import. Docusaurus's advanced cssnano collapses the duplicated `@layer theme { … }` to a bare `@layer theme;`, stripping the whole bridge. Fix: - alias `@sipe-team/tokens` to its built dist so its theme is compiled once (via `build:tokens`); the bridge now has a single copy and full CSS minification stays on. Components still compile from source - inject `@sipe-team/tokens/styles.css` for the Style Dictionary value layer (`--color-*` etc.), which is not vanilla-extract and can't come from source button.mdx documents variant/size/leftIcon/rightIcon/asChild from source, with hand-written prop tables. packages/ is untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(www): sharpen Button captions, fix Back arrow, clarify disabled example - Variant/Size captions now say when to reach for each option instead of just restating the names, matching the accordion pilot's teaching tone - the "With icons" example pointed a right chevron at "Back"; split the inline icon into ArrowLeft/ArrowRight so Back points left and Next points right - the Disabled example showed two identical unlabelled buttons; label them Fill/Outline and note that disabled styling is uniform across variants, so the sameness reads as an intentional demonstration rather than a mistake Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Merge pull request #299 from sipe-team/docs/avatar-docs-jinho docs(www): document Avatar (+ fix onError loop and asChild sizing) * docs(www): document Checkbox (+ fix inline SVG assets and defaultChecked warning) (#301) * fix(checkbox): inline SVG marks and consume defaultChecked - inline the check/indeterminate marks as data: URIs instead of url("public/*.svg"); esbuild resolved those paths but source-compiling consumers (webpack + vanilla-extract plugin, e.g. the docs site) could not, breaking their production build - destructure defaultChecked in Root so it seeds the uncontrolled initial state only and no longer leaks through context onto the input alongside the always-set checked, which triggered React's checked+defaultChecked warning Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(www): document Checkbox Add the Checkbox component docs page (Preview-based MDX) covering the Root/Input/Label parts, controlled/uncontrolled usage, indeterminate and disabled states, and the API reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(checkbox): keep the inlined mark SVGs readable Store the check/indeterminate marks as plain SVG markup and encode them with encodeURIComponent at build time (via a small svgToDataUri helper) instead of a hand-encoded data-URI blob. Same portable data-URI output, but the source stays readable and editable. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(www): document Typography (#300) Add the Typography component docs page (Preview-based MDX) covering usage, size/weight/color examples, the asChild semantic-element note, anatomy, and the API reference. Also refresh _TEMPLATE.md to describe the source-compilation setup instead of the stale dist-alias note. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(flex): support responsive prop values (#284) * feat(flex): support responsive prop values * test(flex): cover responsive prop contract * docs(flex): add responsive story * fix(flex): export responsive helper types * fix(flex): isolate responsive gap values --------- Co-authored-by: Jinho Yeom <81306489+Yeom-JinHo@users.noreply.github.com> Co-authored-by: Evan <clcl6084@gmail.com> Co-authored-by: 이원주 <101818687+3o14@users.noreply.github.com> Co-authored-by: KYBee <kybee@KYBeeui-Macmini.local> Co-authored-by: 오소현 <53892427+osohyun0224@users.noreply.github.com> Co-authored-by: Minji Jeon <105787441+minji0214@users.noreply.github.com> Co-authored-by: MinjiJeon <jinnyjeon@sweetspot.co.kr> Co-authored-by: y09n <euihyun.yang.9x@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Jinho Yeom <pwlsghq@naver.com>

Fixed #214 #215 #216
Changes
피그마 파일 바로 가기 5세대 디자인 시스템에 맞춰 Button 컴포넌트를 전면 개편했습니다.
타입 시스템 변경
sm | lg→sm | md | lg | xl(4단계로 확장)filled | outline | ghost→fill | outline | ghost(filled→fill네이밍 변경)leftIcon,rightIconprops 추가 (ReactNode 타입, 상위 컴포넌트에서 아이콘 전달)사이즈별 스펙
smmdlgxlVariant 스타일
fill#FF7C27(5th orange)#000outline#FF7C27#FF7C27ghost#FF7C27Interaction 상태 (fill 기준)
#FF7C27linear-gradient(225deg, #FF4500 0%, #FFB24D 100%)#FE4E07#71717A(텍스트:#52525B)#FE4E07색상 시스템 변경
vars.color.primary(테마 의존) →createVar()로 버튼 전용 색상 변수 선언buttonOrange (#FF7C27),buttonGradient,buttonRed (#FE4E07)— 5세대 디자인 토큰에 맞춘 고정 색상color.gray500,color.gray600) 직접 참조토큰 변경
packages/tokens/src/colors/colors.ts에theme5th추가 (primary:#FF7C27, secondary:#FE4E07, gradient)변경된 파일
packages/button/src/Button.tsxpackages/button/src/Button.css.tspackages/button/src/Button.stories.tsxpackages/button/src/Button.test.tsxpackages/tokens/src/colors/colors.tstheme5th및themeColor['5th']추가Visuals
스토리북에서 다음 스토리를 확인할 수 있습니다:
Basic— 기본 fill/lg 버튼Variants— fill, outline, ghost 비교Sizes— sm, md, lg, xl 비교Disabled— 각 variant별 disabled 상태WithLeftIcon— 검색 아이콘 + 텍스트WithRightIcon— 텍스트 + 화살표 아이콘WithBothIcons— 다운로드 아이콘 + 텍스트 + 셰브론 아이콘AllVariantsAndSizes— 전체 variant x size 매트릭스Checklist
Additional Discussion Points
ButtonVariant.filled→ButtonVariant.fill로 변경되었습니다. 기존에variant="filled"를 사용하는 곳이 있다면variant="fill"로 수정이 필요합니다.ButtonSize에서 기본값이lg로 유지되지만, 기존sm | lg에서sm | md | lg | xl로 확장되었습니다.vars.color.primary)에서 분리되어createVar()로 독립적으로 관리됩니다. 향후 테마 연동이 필요한 경우buttonOrange등의 CSS 변수를 외부에서 override할 수 있습니다.