Skip to content

dev ← alpha#1385

Draft
te6-in wants to merge 20 commits intodevfrom
alpha
Draft

dev ← alpha#1385
te6-in wants to merge 20 commits intodevfrom
alpha

Conversation

@te6-in
Copy link
Copy Markdown
Member

@te6-in te6-in commented Mar 24, 2026

리베이스 머지해요

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 반응형 디자인 지원 추가: Box, Flex, Grid, Stack 컴포넌트에서 중단점 기반 반응형 속성 사용 가능 (예: padding={{ base: "x4", md: "x6" }})
    • 새로운 훅 추가: useBreakpoint() - 현재 활성화된 중단점 반환, useBreakpointValue() - 반응형 객체에서 값 조회
  • 버그 수정

    • Grid 컴포넌트에서 display="none" 사용 가능하도록 개선
  • 문서

    • 반응형 디자인 개념 페이지 및 각 레이아웃 컴포넌트 문서 업데이트

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 24, 2026

⚠️ No Changeset found

Latest commit: 8101876

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@te6-in te6-in marked this pull request as draft March 24, 2026 08:28
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 24, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 34633ecb-87bf-4077-a94d-909e827688b9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

요약

반응형 스타일링 시스템이 SEED Design에 추가되었습니다. 새로운 PostCSS 플러그인, 브레이크포인트 감지 훅, 제공자 컴포넌트, 그리고 레이아웃 컴포넌트 업데이트를 통해 padding={{ base: ..., md: ... }}과 같은 반응형 객체 기반 스타일링이 가능해집니다.

변경사항

코호트 / 파일(들) 요약
PostCSS 반응형 플러그인
ecosystem/postcss-responsive/src/index.ts, ecosystem/postcss-responsive/src/index.test.ts, ecosystem/postcss-responsive/tsconfig.json
새로운 PostCSS 플러그인으로 --responsive 마크가 있는 CSS 커스텀 속성을 감지하고 브레이크포인트별 미디어 쿼리 블록을 자동 생성. 기본 브레이크포인트 검증 및 마커 커스터마이제이션 지원 포함.
브레이크포인트 스토어 & 프리미티브
packages/react/src/primitives/breakpoint-store.ts
현재 활성 브레이크포인트를 window.matchMedia를 통해 추적하고 외부 상태 구독 패턴으로 관리. 구독자가 없을 때 리스너 정리 로직 포함.
브레이크포인트 훅
packages/react/src/hooks/useBreakpoint.ts, packages/react/src/hooks/useBreakpoint.test.tsx
현재 활성 브레이크포인트 이름을 반환하는 useBreakpoint() 훅. 옵션의 기본값 및 컨텍스트 기반 설정 지원.
반응형 값 훅
packages/react/src/hooks/useBreakpointValue.ts, packages/react/src/hooks/useBreakpointValue.test.tsx
활성 브레이크포인트에 대응하는 값을 반응형 객체에서 해석하는 useBreakpointValue<T>() 훅. 누락된 브레이크포인트에 대해 하위 브레이크포인트로 폴백.
브레이크포인트 제공자
packages/react/src/providers/BreakpointProvider.tsx
컨텍스트 기반 브레이크포인트 상태 제공 컴포넌트. 선택적 기본값 설정 및 SSR 지원.
반응형 타입 유틸리티
packages/react/src/types/responsive.ts
ResponsiveValue<T>, UnwrapResponsive<T>, BreakpointThreshold 타입 및 isResponsiveObject() 런타임 검사 함수 추가.
스타일 유틸 업데이트
packages/react/src/utils/styled.tsx
resolveResponsive() 함수로 반응형 값을 브레이크포인트별 CSS 변수로 변환. StyleProps에서 width, padding, display, gap, flexDirection 등이 ResponsiveValue<...> 지원.
컴포넌트 업데이트
packages/react/src/components/Box/Box.tsx, packages/react/src/components/Flex/Flex.tsx, packages/react/src/components/Grid/Grid.tsx, packages/react/src/components/Icon/Icon.tsx, packages/react/src/components/ResponsivePair/ResponsivePair.tsx
Box에 hideFrom 프롭 추가. Flex/Grid의 display, columns, rowsResponsiveValue<...>로 업그레이드. Icon의 size에서 비반응형 래핑 제거. ResponsivePair를 CSS 커스텀 속성 기반으로 리팩토링.
CSS 프리셋 업데이트
packages/qvism-preset/src/global.ts, packages/qvism-preset/src/index.ts, packages/qvism-preset/src/recipes/*
CSS 커스텀 속성을 --responsive 접미사로 리네이밍. postcss-responsive 플러그인을 PostCSS 파이프라인에 통합. 모든 레시피(ActionButton, BottomSheet, HelpBubble, ListItem, Skeleton)에서 반응형 속성으로 업데이트.
브레이크포인트 정의
packages/qvism-preset/src/utils/breakpoint.ts
base: 0, sm: 480, md: 768, lg: 1280, xl: 1440의 브레이크포인트 값 및 breakpoints.up() 미디어 쿼리 헬퍼 정의.
공용 API 내보내기
packages/react/src/index.ts
useBreakpoint, useBreakpointValue, BreakpointProvider 및 관련 타입들을 공개 API로 내보내기.
반응형 디자인 문서
docs/content/react/components/concepts/responsive-design.mdx
브레이크포인트 정의, 반응형 프롭 구문, 지원 속성 카테고리, hideFrom 사용, 그리고 SSR 시 BreakpointProvider 사용법 문서화.
컴포넌트별 문서
docs/content/react/components/(foundation)/layout/box.mdx, .../flex.mdx, .../grid.mdx, .../h-stack.mdx, .../v-stack.mdx
각 레이아웃 컴포넌트에 "반응형 디자인" 섹션 추가 및 반응형 디자인 개념 페이지로의 링크.
반응형 예제
docs/examples/react/responsive-design/responsive-props.tsx, responsive-display.tsx, responsive-grid.tsx, use-breakpoint.tsx, use-breakpoint-value.tsx, hide-from.tsx
반응형 패딩, 조건부 표시, 반응형 그리드, 브레이크포인트 훅 사용 예제 6개 추가.
스토리북 설정
docs/.storybook/preview.ts, docs/stories/utils/parameters.ts
브레이크포인트 기반 뷰포트 맵 생성 및 VIEWPORT_MODES 내보내기. Chromatic 다중 뷰포트 테스트 구성.
스토리북 스토리 업데이트
docs/stories/Box.stories.tsx, docs/stories/Flex.stories.tsx, docs/stories/Grid.stories.tsx, docs/stories/Stack.stories.tsx, docs/stories/ResponsivePair.stories.tsx
반응형 속성 테스트 케이스 추가 및 모든 스토리에 VIEWPORT_MODES Chromatic 설정 적용.
체인지셋 및 설정
.changeset/responsive-styling.md
@seed-design/css@seed-design/react에 대한 마이너 버전 업데이트 문서화.

시퀀스 다이어그램

sequenceDiagram
    actor User
    participant Browser
    participant BreakpointProvider
    participant BreakpointStore as Breakpoint<br/>Store
    participant useBreakpoint
    participant useBreakpointValue
    participant LayoutComponent as Layout<br/>Component
    participant PostCSSPlugin as PostCSS<br/>Plugin

    User->>Browser: Viewport 크기 변경
    Browser->>BreakpointStore: matchMedia 이벤트 발생
    BreakpointStore->>BreakpointStore: 활성 브레이크포인트 재계산
    BreakpointStore->>useBreakpoint: 구독자에 변경 알림
    useBreakpoint->>BreakpointProvider: 현재 브레이크포인트 제공
    BreakpointProvider->>LayoutComponent: 컨텍스트 값 업데이트
    
    LayoutComponent->>useBreakpointValue: 활성 브레이크포인트에<br/>대한 값 요청
    useBreakpointValue->>useBreakpointValue: 반응형 객체에서<br/>현재 BP 값 해석
    useBreakpointValue-->>LayoutComponent: 해석된 값 반환
    
    LayoutComponent->>PostCSSPlugin: --responsive 마크된<br/>CSS 변수 사용
    PostCSSPlugin-->>LayoutComponent: 브레이크포인트별<br/>미디어 쿼리 적용
Loading

예상 코드 리뷰 노력

🎯 4 (복잡함) | ⏱️ ~60분

관련된 PRs

  • feat: breakpoint & responsive styling support #1326: 동일한 브레이크포인트/반응형 스타일링 기능 세트를 구현—postcss-responsive 플러그인, 브레이크포인트 토큰, resolveResponsive/useBreakpoint/useBreakpointValue/BreakpointProvider 및 breakpoint-store 런타임, 반응형 타입/유틸리티, 그리고 컴포넌트 변경사항(Box/Flex/Grid/Icon/ResponsivePair 및 styled.useStyleProps)—이므로 코드 수준에서 직접적으로 관련됨.

시를 바치며

🐰 반응형 레이아웃 춤을 춘다,
브레이크포인트마다 새로운 옷을 입고
PostCSS 마법이 CSS를 부려내니,
Box와 Flex가 쌓고 펼쳐지며
모바일부터 데스크톱까지
우아하게 흘러가는 디자인의 춤 🎨✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning 제목 'dev ← alpha'는 풀 리퀘스트의 소스 브랜치에서 대상 브랜치로의 병합 방향만 나타내며, 실제 변경 내용(반응형 디자인 지원, 새로운 훅, PostCSS 플러그인 등)을 전혀 설명하지 않습니다. 제목을 변경하여 이 PR의 주요 변경 사항을 명확히 설명하는 내용으로 수정하세요. 예: 'Add responsive design support with breakpoints, hooks, and postcss plugin' 또는 'Implement responsive styling system with breakpoint utilities and CSS variable cascades'
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch alpha

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 24, 2026

Alpha Preview (Stackflow SPA)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 24, 2026

Alpha Preview (Storybook)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 24, 2026

Alpha Preview (Docs)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react/src/components/Grid/Grid.tsx (1)

61-86: ⚠️ Potential issue | 🟡 Minor

displayName 누락

코딩 가이드라인에 따르면 모든 컴포넌트는 forwardRefdisplayName을 사용해야 합니다. Grid 컴포넌트에 displayName이 설정되어 있지 않습니다.

🔧 수정 제안
 export const Grid = React.forwardRef<HTMLDivElement, GridProps>((props, ref) => {
   // ... component body
 });
+
+Grid.displayName = "Grid";

As per coding guidelines, "All components must use forwardRef and displayName for proper ref forwarding and component identification".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/src/components/Grid/Grid.tsx` around lines 61 - 86, The Grid
component uses React.forwardRef but is missing a displayName; add a displayName
property after the forwardRef declaration by assigning Grid.displayName = "Grid"
so the component is properly identified in devtools and stacks; locate the
exported const Grid from React.forwardRef and append the displayName assignment
immediately after its definition.
🧹 Nitpick comments (4)
packages/react/src/components/Flex/Flex.tsx (1)

42-58: displayName 설정이 누락되었습니다.

코딩 가이드라인에 따르면 모든 컴포넌트는 forwardRefdisplayName을 사용해야 합니다. Flex 컴포넌트에 displayName이 설정되어 있지 않습니다.

♻️ displayName 추가 제안
 export const Flex = React.forwardRef<HTMLDivElement, FlexProps>((props, ref) => {
   const { direction, wrap, align, justify, grow, shrink, ...rest } = props;

   return (
     <Box
       ref={ref}
       display="flex"
       flexDirection={direction}
       flexWrap={wrap}
       alignItems={align}
       justifyContent={justify}
       flexGrow={grow}
       flexShrink={shrink}
       {...rest}
     />
   );
 });
+
+Flex.displayName = "Flex";

As per coding guidelines, "All components must use forwardRef and displayName for proper ref forwarding and component identification".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/src/components/Flex/Flex.tsx` around lines 42 - 58, The Flex
component created via React.forwardRef (function name Flex, props type
FlexProps) is missing a displayName; set Flex.displayName = "Flex" immediately
after the forwardRef declaration to satisfy the coding guideline requiring all
forwardRef components to have a displayName for proper ref forwarding and
component identification.
packages/react/src/components/ResponsivePair/ResponsivePair.tsx (1)

14-44: displayName 설정이 누락되었습니다.

코딩 가이드라인에 따르면 모든 컴포넌트는 forwardRefdisplayName을 사용해야 합니다.

♻️ displayName 추가 제안
 export const ResponsivePair = React.forwardRef<HTMLDivElement, ResponsivePairProps>(
   (props, ref) => {
     // ... component body
   },
 );
+
+ResponsivePair.displayName = "ResponsivePair";

As per coding guidelines, "All components must use forwardRef and displayName for proper ref forwarding and component identification".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/src/components/ResponsivePair/ResponsivePair.tsx` around lines
14 - 44, The ResponsivePair component uses React.forwardRef but lacks a
displayName; after the forwardRef declaration assign ResponsivePair.displayName
= "ResponsivePair" so the component is identifiable in devtools and
errors—locate the forwardRef export named ResponsivePair and add the displayName
assignment immediately after its definition.
packages/react/src/components/Box/Box.tsx (1)

25-28: hideFrom 스타일 로직 중복을 추출하는 것을 고려해 보세요.

asChild와 non-asChild 렌더 경로에서 동일한 스타일 객체 생성 로직이 반복됩니다. 이를 변수로 추출하면 유지보수성이 향상됩니다.

♻️ 스타일 로직 추출 제안
 export const Box = React.forwardRef<HTMLDivElement, BoxProps>((props, ref) => {
   const { hideFrom, ...rest } = props;
   const { style, restProps } = useStyleProps(rest);
   const { as: Comp = "div", asChild = false, className, ...nativeProps } = restProps;
+  
+  const mergedStyle = {
+    ...style,
+    ...(hideFrom && { [`--seed-box-display-${hideFrom}`]: "none" }),
+  };

   if (asChild) {
     return (
       <Slot
         ref={ref}
         className={clsx("seed-box", className)}
-        style={{
-          ...style,
-          ...(hideFrom && { [`--seed-box-display-${hideFrom}`]: "none" }),
-        }}
+        style={mergedStyle}
         {...nativeProps}
       />
     );
   }

   return (
     <Comp
       ref={ref}
       className={clsx("seed-box", className)}
-      style={{
-        ...style,
-        ...(hideFrom && { [`--seed-box-display-${hideFrom}`]: "none" }),
-      }}
+      style={mergedStyle}
       {...nativeProps}
     />
   );
 });

Also applies to: 38-41

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/src/components/Box/Box.tsx` around lines 25 - 28, The Box
component duplicates the style object creation for the hideFrom logic in both
the asChild and non-asChild render paths; extract the merged style into a single
variable (e.g., mergedStyle or computedStyle) that starts from the incoming
style prop and conditionally adds the hideFrom token when hideFrom is truthy,
then use that variable in both JSX branches instead of recreating the object;
ensure you reference the existing hideFrom prop, the style prop, and the asChild
render branch so the change applies to both code paths.
packages/react/src/hooks/useBreakpointValue.test.tsx (1)

8-42: 테스트 유틸리티 중복 고려

mockMatchMediasetViewport 헬퍼가 useBreakpoint.test.tsx에서도 동일하게 구현되어 있습니다. 공유 테스트 유틸리티 모듈로 추출하면 유지보수성이 향상됩니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/src/hooks/useBreakpointValue.test.tsx` around lines 8 - 42,
Duplicate test helpers (mockMatchMedia, setViewport, currentWidth, entries)
exist in this repo; extract them into a shared test utility module (e.g.,
test/utils/matchMedia.ts) and export the necessary symbols (mockMatchMedia,
setViewport, ChangeHandler type if used) then update useBreakpointValue.test.tsx
and useBreakpoint.test.tsx to import these helpers instead of re-defining them;
ensure the exported mock correctly registers/unregisters handlers and that tests
call setViewport to simulate width changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/.storybook/preview.ts`:
- Around line 5-6: The import of ViewportMap from "storybook/viewport" is
invalid and causes build failures; either install `@storybook/addon-viewport` and
replace the import with a type import like import type { Viewport } from
"@storybook/addon-viewport" (and update any ViewportMap usages to the correct
type), or remove the type annotation entirely and proceed without ViewportMap;
additionally remove the duplicated viewport configuration block so only one
viewport definition remains (look for the viewport settings surrounding the
breakpoints usage and the duplicated block in preview.ts).

In `@docs/content/react/components/`(foundation)/layout/flex.mdx:
- Around line 19-24: Clarify that not all Flex props accept responsive objects
by listing which props support responsive values (e.g., justify, align, wrap if
applicable) or by adding a short type table/example for the Flex component
(reference the Flex component and prop names like justify, align, wrap) and
update the "Responsive Design" paragraph in
docs/content/react/components/(foundation)/layout/flex.mdx to show an explicit
example of supported prop syntax and/or link to the types; also apply the same
wording change to the other layout docs that reuse this paragraph to avoid
inconsistency.

In `@packages/react/src/components/Box/Box.tsx`:
- Around line 15-45: The Box component created with React.forwardRef is missing
a displayName; add a displayName property to the forwarded component (e.g., set
Box.displayName = "Box" immediately after the export const Box =
React.forwardRef(...) declaration) so the forwarded ref component is properly
identified in DevTools and error messages.

In `@packages/react/src/types/responsive.ts`:
- Around line 17-18: The type guard isResponsiveObject currently treats any
non-null object (excluding arrays) as a ResponsiveObject, causing plain objects
like { foo: 1 } to be misinterpreted as breakpoint maps; update
isResponsiveObject to also verify that the object's keys are valid breakpoint
keys only (e.g., get Object.keys(value) and ensure every key is one of the known
breakpoint identifiers or exists in the theme.breakpoints map) so it returns
true only when the object is a breakpoint-keyed map; reference the
isResponsiveObject function and the ResponsiveObject/Theme breakpoint keys when
implementing this narrower check.

---

Outside diff comments:
In `@packages/react/src/components/Grid/Grid.tsx`:
- Around line 61-86: The Grid component uses React.forwardRef but is missing a
displayName; add a displayName property after the forwardRef declaration by
assigning Grid.displayName = "Grid" so the component is properly identified in
devtools and stacks; locate the exported const Grid from React.forwardRef and
append the displayName assignment immediately after its definition.

---

Nitpick comments:
In `@packages/react/src/components/Box/Box.tsx`:
- Around line 25-28: The Box component duplicates the style object creation for
the hideFrom logic in both the asChild and non-asChild render paths; extract the
merged style into a single variable (e.g., mergedStyle or computedStyle) that
starts from the incoming style prop and conditionally adds the hideFrom token
when hideFrom is truthy, then use that variable in both JSX branches instead of
recreating the object; ensure you reference the existing hideFrom prop, the
style prop, and the asChild render branch so the change applies to both code
paths.

In `@packages/react/src/components/Flex/Flex.tsx`:
- Around line 42-58: The Flex component created via React.forwardRef (function
name Flex, props type FlexProps) is missing a displayName; set Flex.displayName
= "Flex" immediately after the forwardRef declaration to satisfy the coding
guideline requiring all forwardRef components to have a displayName for proper
ref forwarding and component identification.

In `@packages/react/src/components/ResponsivePair/ResponsivePair.tsx`:
- Around line 14-44: The ResponsivePair component uses React.forwardRef but
lacks a displayName; after the forwardRef declaration assign
ResponsivePair.displayName = "ResponsivePair" so the component is identifiable
in devtools and errors—locate the forwardRef export named ResponsivePair and add
the displayName assignment immediately after its definition.

In `@packages/react/src/hooks/useBreakpointValue.test.tsx`:
- Around line 8-42: Duplicate test helpers (mockMatchMedia, setViewport,
currentWidth, entries) exist in this repo; extract them into a shared test
utility module (e.g., test/utils/matchMedia.ts) and export the necessary symbols
(mockMatchMedia, setViewport, ChangeHandler type if used) then update
useBreakpointValue.test.tsx and useBreakpoint.test.tsx to import these helpers
instead of re-defining them; ensure the exported mock correctly
registers/unregisters handlers and that tests call setViewport to simulate width
changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3864cf01-493e-4bc2-84c9-a2c3883465b8

📥 Commits

Reviewing files that changed from the base of the PR and between 59a6524 and 054d6eb.

⛔ Files ignored due to path filters (25)
  • bun.lock is excluded by !**/*.lock
  • docs/public/__docs__/index.json is excluded by !**/public/**/*
  • ecosystem/postcss-responsive/package.json is excluded by !**/package.json
  • packages/css/all.css is excluded by !packages/css/**/*
  • packages/css/all.layered.css is excluded by !packages/css/**/*
  • packages/css/all.layered.min.css is excluded by !packages/css/**/*
  • packages/css/all.min.css is excluded by !packages/css/**/*
  • packages/css/base.css is excluded by !packages/css/**/*
  • packages/css/base.layered.css is excluded by !packages/css/**/*
  • packages/css/base.layered.min.css is excluded by !packages/css/**/*
  • packages/css/base.min.css is excluded by !packages/css/**/*
  • packages/css/breakpoints/index.d.ts is excluded by !packages/css/**/*
  • packages/css/breakpoints/index.mjs is excluded by !packages/css/**/*
  • packages/css/package.json is excluded by !**/package.json, !packages/css/**/*
  • packages/css/recipes/action-button.css is excluded by !packages/css/**/*
  • packages/css/recipes/action-button.layered.css is excluded by !packages/css/**/*
  • packages/css/recipes/bottom-sheet.css is excluded by !packages/css/**/*
  • packages/css/recipes/bottom-sheet.layered.css is excluded by !packages/css/**/*
  • packages/css/recipes/help-bubble.css is excluded by !packages/css/**/*
  • packages/css/recipes/help-bubble.layered.css is excluded by !packages/css/**/*
  • packages/css/recipes/list-item.css is excluded by !packages/css/**/*
  • packages/css/recipes/list-item.layered.css is excluded by !packages/css/**/*
  • packages/css/recipes/skeleton.css is excluded by !packages/css/**/*
  • packages/css/recipes/skeleton.layered.css is excluded by !packages/css/**/*
  • packages/qvism-preset/package.json is excluded by !**/package.json
📒 Files selected for processing (45)
  • .changeset/responsive-styling.md
  • docs/.storybook/preview.ts
  • docs/content/react/components/(foundation)/layout/box.mdx
  • docs/content/react/components/(foundation)/layout/flex.mdx
  • docs/content/react/components/(foundation)/layout/grid.mdx
  • docs/content/react/components/(foundation)/layout/h-stack.mdx
  • docs/content/react/components/(foundation)/layout/v-stack.mdx
  • docs/content/react/components/concepts/responsive-design.mdx
  • docs/examples/react/responsive-design/hide-from.tsx
  • docs/examples/react/responsive-design/responsive-display.tsx
  • docs/examples/react/responsive-design/responsive-grid.tsx
  • docs/examples/react/responsive-design/responsive-props.tsx
  • docs/examples/react/responsive-design/use-breakpoint-value.tsx
  • docs/examples/react/responsive-design/use-breakpoint.tsx
  • docs/stories/Box.stories.tsx
  • docs/stories/Flex.stories.tsx
  • docs/stories/Grid.stories.tsx
  • docs/stories/ResponsivePair.stories.tsx
  • docs/stories/Stack.stories.tsx
  • docs/stories/utils/parameters.ts
  • ecosystem/postcss-responsive/src/index.test.ts
  • ecosystem/postcss-responsive/src/index.ts
  • ecosystem/postcss-responsive/tsconfig.json
  • packages/qvism-preset/src/global.ts
  • packages/qvism-preset/src/index.ts
  • packages/qvism-preset/src/recipes/action-button.ts
  • packages/qvism-preset/src/recipes/bottom-sheet.ts
  • packages/qvism-preset/src/recipes/help-bubble.ts
  • packages/qvism-preset/src/recipes/list-item.ts
  • packages/qvism-preset/src/recipes/skeleton.ts
  • packages/qvism-preset/src/utils/breakpoint.ts
  • packages/react/src/components/Box/Box.tsx
  • packages/react/src/components/Flex/Flex.tsx
  • packages/react/src/components/Grid/Grid.tsx
  • packages/react/src/components/Icon/Icon.tsx
  • packages/react/src/components/ResponsivePair/ResponsivePair.tsx
  • packages/react/src/hooks/useBreakpoint.test.tsx
  • packages/react/src/hooks/useBreakpoint.ts
  • packages/react/src/hooks/useBreakpointValue.test.tsx
  • packages/react/src/hooks/useBreakpointValue.ts
  • packages/react/src/index.ts
  • packages/react/src/primitives/breakpoint-store.ts
  • packages/react/src/providers/BreakpointProvider.tsx
  • packages/react/src/types/responsive.ts
  • packages/react/src/utils/styled.tsx

Comment thread docs/.storybook/preview.ts
Comment thread docs/content/react/components/(foundation)/layout/flex.mdx
Comment thread packages/react/src/components/Box/Box.tsx
Comment thread packages/react/src/types/responsive.ts
@te6-in te6-in force-pushed the alpha branch 2 times, most recently from 18e13a7 to d1ad8aa Compare April 3, 2026 11:36
te6-in and others added 8 commits April 7, 2026 18:49
# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css
…ions (#1396)

* feat(rootage): add viewport-width token collection with mode descriptions

Add viewport-width as a new TokenCollection axis (base/sm/md/lg/xl)
for responsive design support. Also introduce ModeEntry type to allow
optional descriptions on collection modes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bun install

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(rootage): unify ModeEntry type to object-only format

Remove string support from ModeEntry type, requiring all modes to use
{ id: string; description?: string } format. This simplifies the parser
logic by eliminating typeof string branching in token-collections.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(rootage): improve viewport-width mode descriptions

Use orientation-aware language (세로/가로 모드) and consistent
word pairs (좁은/넓은), fix 데스크탑 → 데스크톱 spelling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(rootage): add viewport-width token collection with mode descriptions

Add viewport-width as a new TokenCollection axis (base/sm/md/lg/xl)
for responsive design support. Also introduce ModeEntry type to allow
optional descriptions on collection modes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: simplify ModeDeclaration schema; fix consumers; implement basic css language for viewport-width

* refactor

* revert: revert collections description; generate

---------

Co-authored-by: 정현수 <hyeonsu.github@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(footer): add Footer component, recipe, blocks, icons, and docs

- Add FooterLinkText component with namespace pattern (packages/react)
- Add footer recipe with size/variant support (packages/qvism-preset)
- Add generated CSS for footer recipe (packages/css)
- Add footer block presets (footer-01 through footer-04) with SNS icons
- Add BlockCodeTabs component for block documentation
- Add icon registry (blog, facebook, github, instagram, kakaotalk, medium, youtube)
- Add footer MDX documentation and storybook stories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* changeset

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove deprecated color & gradient tokens

* chore: remove deprecated layout options in StyleProps

* chore: remove deprecated size/weight options in Switch/Checkbox

* chore: remove variant=brandSolid in chip tabs

* docs

* fix(examples): fix stackflow-spa build errors from deprecated option removal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update snippet

* chore: remove rounded variants from image-frame recipe

* fix: remove references to removed tokens

* docs

* fix

* docs

* docs

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(chip-tabs): consume chip rootage for trigger styles

Replace chip-tab vars with chip vars in chip-tabs recipe where
token values are identical. Remove brandSolid variant and switch
disabled styling from individual color overrides to opacity-based
approach matching chip component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.css
#	packages/css/all.layered.css
#	packages/css/all.layered.min.css
#	packages/css/all.min.css
#	packages/css/recipes/chip-tabs.css
#	packages/css/recipes/chip-tabs.layered.css
#	packages/qvism-preset/src/recipes/chip-tabs.ts

* chore: remove chip-tab rootage

* docs: remove reference to removed componentspec

* docs
* feat: implement layout

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* test(layout): add storybook story

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
te6-in and others added 10 commits April 10, 2026 11:20
…1446)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…bleLayer hook (#1410)

* feat(menu): add Menu compound component primitives

Scaffold Menu styled components using Primitive.* elements as
placeholders for future headless and recipe integration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(menu): wrap Base UI Menu primitives as headless layer

Replace Primitive-based placeholders with @base-ui-components/react
Menu primitives. MenuPositioner internally wraps Portal + Positioner.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(menu): add recipe, submenu support, and stackflow-spa example

- Add qvism-preset menu slot recipe with size variant and tokens
- Wire recipe to React components via createSlotRecipeContext
- Add MenuSubmenuRoot and MenuSubmenuTrigger exports
- Add ActivityMenu with basic, grouped, nested, disabled demos

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat(menu): add headless useMenu hook with TDD test suite

Implement useMenu hook on top of @floating-ui/react@0.27 (public API),
composing useClick, useRole, useDismiss, useListNavigation, useTypeahead,
and useInteractions for a fully headless menu with:
- Open/close state (controlled + uncontrolled)
- Arrow key navigation with loopFocus
- Typeahead character search
- Escape and outside click dismiss
- Modal scroll lock
- data-* attributes (data-open, data-highlighted, data-disabled)

42/47 core tests passing, 2/16 submenu tests passing.
Remaining core gaps: group aria-labelledby wiring, Enter/Space item
activation on non-button elements, drag-from-trigger interaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(menu): add Enter/Space activation for non-button items, cleanup unused ref

- Add onKeyDown handler to getItemProps for Enter/Space click simulation
  on div-based menu items (floating-ui only handles buttons natively)
- Remove unused groupLabelIdMap ref

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(menu): align useMenu API with SEED headless pattern, update test harnesses

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(menu): add headless React components, context, and exports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(menu): use headless components in test harnesses

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor

* feat: menu implementation

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* refactor: remove @radix-ui/react-dialog; add @seed-design/dismissable-layer

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* docs: menu

* feat: allow customizing the portalled root of menu

* docs

* feat: implement matching reference width

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* refactor

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* refactor

* fix: fix dismissing menu on bottom sheet by clicking outside dismissing bottom sheet as well

* fix(menu): use dynamic available height from Floating UI size middleware

Use Floating UI's size middleware to dynamically constrain menu max-height
to the actual available viewport space, preventing overflow when the
trigger is near viewport edges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat(menu): add rootage specs for menu and menu-item

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat: remove modal option

* feat: add pressBehavior option; refactor callbacks

* test(dismissible-layer): fix failing tests and migrate to userEvent

- Fix 3 failing tests after pressBehavior default changed to "confirm"
- Add NOOP defaults for required callbacks in test helpers
- Migrate 12 tests from fireEvent to userEvent where applicable

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: fix types

* test(menu): fix flaky typeahead tests

- Add missing waitForFocus() for rAF-deferred focus to settle
- Remove invalid Space typeahead test (useTypeahead doesn't provide
  item-level handlers; Space activates items by design)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(menu): replace MenuDivider with CSS auto-divider between groups

Use `group + group::before` pseudo-element to automatically render
dividers between consecutive MenuGroup elements, eliminating the need
for a separate MenuDivider component. Removes the divider slot, component,
and all consumer usage across headless, react, docs, and examples.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dismissible-layer): only cascade-dismiss child layers, not siblings

removeLayer previously cascade-dismissed ALL layers added after the
removed one, treating them as nested children. This incorrectly
dismissed independent sibling layers (e.g., two separate menus).

Add parentNode tracking to the Layer interface so removeLayer only
cascade-dismisses layers that explicitly declare the removed node as
their parent. Add DismissibleParentContext (following base-ui's
FloatingNodeContext pattern) so nested layers automatically know their
parent via React context propagation through portals.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(menu): provide DismissibleParentContext to fix sibling menu dismiss

Wrap children of MenuContent, DialogContent, and DrawerContent with
DismissibleParentContext.Provider so nested dismissible layers (e.g.,
menu inside dialog) correctly cascade-dismiss while sibling menus
remain independent.

Add sibling menu tests covering both mouse and touch interactions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(dismissible-layer): extract DismissibleLayer headless component

Replace manual useDismissibleLayer + ref composition + props merging +
DismissibleParentContext.Provider in each consumer with a single
<DismissibleLayer> wrapper component. Follows the Presence component
pattern using Radix Slot to merge ref and props onto the child element.

Consumers (Menu, Dialog, Drawer) no longer need to know about
DismissibleParentContext or layerNode — the component handles it
internally. Remove DismissibleParentContext and useDismissibleParentNode
from public exports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs

* docs

* fix: add missing forwardRef

* fix: fix focusscope not working

* fix: remove content focus style from dialog recipe

* docs

* fix: fix flip not happening before opening; apply x axis transform origin

* feat

* docs

* fix: fix styles

* fix(dialog): add missing displayName to DialogPositioner

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(drawer): remove duplicate defaultPrevented check in onPressOutside

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(menu): add rationale comment to commented-out highlight code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dismissible-layer): reset isFocusInsideReactTreeRef on effect cleanup

When `enabled` toggles off→on without focus leaving the layer (e.g.,
programmatic state change), onBlurCapture never fires and the ref stays
stale. The first focus-outside event after re-enable is silently ignored.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(presence): remove as any casts from usePresence and Presence

- stylesRef: {} as any → proper CSSStyleDeclaration | null with guarded access
- ref callback: accept HTMLElement | null to match React's ref contract
- state machine reducer: narrowed from as any to Record<string, MachineState<M>>

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(menu): narrow MenuRootProps to not extend HTMLAttributes

MenuRoot renders no DOM element (it's a context provider only). Extending
HTMLAttributes and PrimitiveProps exposed className, style, onClick etc.
as valid props that were silently ignored. Now matches Dialog/Drawer/Popover
Root pattern: UseMenuProps + children.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dismissible-layer): re-compute index after cascade-dismiss in removeLayer

Cascade-dismiss calls child.dismiss() which can trigger recursive
removeLayer, shifting indices in the layers array. The pre-computed
index could become stale, causing splice to remove the wrong layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dismissible-layer): widen onPressOutside type to PointerEvent | TouchEvent

Touch-drag dismiss paths in use-pointer-down-outside produce real
TouchEvents. Remove the as unknown as PointerEvent cast (violates
TECH.md) and widen the callback type through the chain:
- use-pointer-down-outside onPressOutside
- useDismissibleLayer onPressOutside
- Menu/Dialog/Drawer interactOutside detail event types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dismissible-layer): add duplicate-registration guard in addLayer

Unlike Radix which uses Set (implicitly idempotent), our layer stack uses
arrays for ordering. Add explicit findIndex + splice guard to prevent
double-registration from React strict mode re-running effects.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(menu): comment out unused getSubmenuTriggerProps

Not consumed by any component yet. Commented out with "implement when
submenu is needed" to match the highlight code convention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test(dismissible-layer): verify Escape does not propagate when inner layer ignores it

Confirms that the isTopMost guard in useEscapeKeydown prevents Escape
from reaching outer layers, even when the inner layer's handler does not
call preventDefault. This is not a behavioral regression from Radix —
SEED's architecture gates Escape to the topmost layer only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dismissible-layer): fix body.style.pointerEvents leak in nested blocking layers

The per-layer save/restore pattern failed when React cleaned up effects
bottom-up: the child that saved the original value couldn't restore
(parent still blocking), and the parent that survived longest had null
(never saved). The original value was orphaned permanently.

Follow Radix's proven pattern: save the original value to a module-level
variable when the first blocking layer mounts, restore when the last
unmounts. This decouples save/restore from mount/unmount order.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: move comment

* docs(drawer): clarify onFocusOutside empty handler intent

Replace ambiguous TODO comment with explanation of why the handler is
intentionally empty. The protection from PR #1187 (e.preventDefault on
onFocusOutside) is no longer needed — the new DismissibleLayer handles
cascade dismiss via onCascadeDismiss instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add cases for onOpenChange reason

* chore: comment

* refactor: rename label to typeaheadLabel

* fix: allow focusing outer elements when drawer has modal=false

* fix: fix bottom sheet modal=true styles

* fix: fix registry component types; ref passing

* docs: fix label

* fix: fix drawer modal behavior

* change: update menu registry and stories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(dialog,drawer): apply aria-hidden to siblings when modal is open

Add `hideOthers` from `aria-hidden` package to Dialog and Drawer so
screen-reader virtual cursors can no longer reach background content
while a modal overlay is active.

- Dialog: add `modal` prop (default true) controlling FocusScope trap,
  aria-modal attribute, and aria-hidden on siblings
- Drawer: add aria-hidden on siblings when `modal && isOpen`
- Docs: add `modal={isActive}` to Keeping Mounted patterns for
  Alert Dialog, Bottom Sheet, and Menu Sheet

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(examples): add missing modal={isActive} to Keeping Mounted patterns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dialog,drawer): use useState callback ref for hideOthers timing

Presence defers child mounting by one render cycle when re-entering
(useLayoutEffect dispatches MOUNT, which triggers a re-render).
With useRef, the useEffect fires before children mount, so
contentRef.current is null and hideOthers is never called on reopen.

Switch to useState callback ref (same pattern as useDismissibleLayer)
so that setContentNode triggers a re-render, causing the useEffect to
re-evaluate with the actual DOM node.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(react): add SideNavigation compound component skeleton

Scaffold the SideNavigation compound component with 13 slots:
Root (nav), Header, Content, Footer, Group, GroupLabel,
MenuGroup (Collapsible.Root), MenuGroupContent (Collapsible.Content),
MenuItem, MenuItemTrigger (Collapsible.Trigger), MenuSubItem,
Trigger, and Inset.

Also adds Primitive.nav to react-primitive for semantic navigation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(react): rename SideNavigation menu item components and add usage example

Rename for clarity:
- MenuItem → MenuItemButton (standalone navigation)
- MenuGroup → MenuItemCollapsibleRoot
- MenuGroupContent → MenuItemCollapsibleContent
- MenuItemTrigger → MenuItemCollapsibleTrigger
- MenuSubItem → MenuItemCollapsibleItem

Add ActivitySideNavigation in stackflow-spa as a bare usage example
demonstrating all compound component slots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

# Conflicts:
#	examples/stackflow-spa/src/activities/ActivityHome.tsx
#	examples/stackflow-spa/src/stackflow/Stack.tsx
#	examples/stackflow-spa/src/stackflow/stackflow.config.ts

* feat(qvism-preset): add SideNavigation recipes and wire to React components

Add three recipes in side-navigation.ts:
- sideNavigation (slot recipe): layout slots for root, header, content, footer, group, groupLabel, trigger
- sideNavigationInset (single recipe): no-op placeholder for Inset (lives outside Root context)
- sideNavigationMenuItem (slot recipe): item, collapsibleContent, chevron slots

Update React components to use createSlotRecipeContext pattern:
- Root uses withProvider, child slots use withContext
- MenuItemCollapsibleRoot uses withRootProvider for menuItem context
- MenuItemButton and Inset use standalone recipe calls (Badge pattern)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat(react-headless): add SideNavigation headless package with collapse coordination

Introduce @seed-design/react-side-navigation with:
- useSideNavigation: collapsed state management (controllable pattern)
- useSideNavigationCollapsible: sidebar-aware collapsible (useCollapsible superset)
- Compound components: Provider, Root, Trigger, MenuItemCollapsible*
- Derived state pattern (effectiveOpen = collapsed ? false : userOpen)
- Provider separated from Root to support sibling Inset access

Update styled layer to consume headless components and add collapse recipes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* refactor(react-headless): remove sidebar uncollapse on collapsible trigger click

Remove the behavior where clicking a collapsible trigger in collapsed
state would uncollapse the sidebar and open the collapsible. In collapsed
state, collapsible open requests are now ignored. This interaction will
be replaced with hover-based Menu behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(side-navigation): improve scrollbar handling and collapse state preservation

- Use CSS-only panel collapse (scrollbar-gutter + overflow) instead of JS state reset
  to preserve collapsible open/close state across sidebar collapse/expand cycles
- Enforce single-line labels with ellipsis truncation for consistent item height
- Add scrollbar-gutter: stable in expanded state, auto in collapsed state
- Add docs registry and stackflow example for SideNavigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat(side-navigation): add scroll divider, focus rings, flatten snippet exports, and expand example

- Add CSS background-attachment scroll divider on content slot (local/scroll trick)
- Add inside focus ring on menu item ::before, outside focus ring on trigger
- Flatten snippet exports to SideNavigation-prefixed named exports (no object export)
- Add more menu groups to stackflow example for scroll testing
- Remove duplicate SideNavigationMenuItemButton (merged into SideNavigationMenuItem)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat(side-navigation): add top scroll divider and bottom scroll fog on content slot

- Top: 1px divider via background-attachment local/scroll trick
- Bottom: 16px mask-image fog that fades into paddingBottom: 16px
- No JS needed — fog is always on, padding ensures no content is obscured at scroll end

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* fix: collapse all collapsibles when sidebar isn't expanded

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* chore: bump icons

* feat: implement selected & disabled

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* docs: block example

# Conflicts:
#	docs/content/react/blocks/meta.json
#	docs/public/__docs__/index.json
#	docs/public/__registry__/block/index.json
#	docs/registry/registry-block.ts

* fix: fix styles

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat: integrate menu with side navigation

# Conflicts:
#	docs/public/__registry__/ui/index.json
#	docs/registry/registry-ui.ts
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* docs

* docs: add missing list item

* refactor

* refactor

* refactor(side-navigation): add current prop to collapsible trigger

ItemCollapsibleTrigger now accepts `current` prop via
useSideNavigationItem, enabling proper current state propagation
to child icons during collapse transitions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(side-navigation): consolidate snippet into data-driven Group

Replace ItemCollapsible + GroupLabel with a single SideNavigationGroup
component that accepts `items` data with discriminated union
(leaf items with onClick vs collapsible items with sub-items).

- Group renders leaf items, collapsible sections, and menu popups
- Collapsible/menu mode switching handled internally via collapsed state
- hasCurrentChild derived from sub-items for trigger highlight
- ItemButton retained for standalone use (e.g. Footer)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add examples

* docs

* fix: fix styles

* docs

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(docs): add Layout blocks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

# Conflicts:
#	docs/public/__registry__/block/index.json

* docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
te6-in and others added 2 commits April 16, 2026 22:41
* feat: basic implementation

# Conflicts:
#	packages/css/all.min.css

# Conflicts:
#	bun.lock
#	packages/css/all.min.css
#	packages/react/package.json

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

# Conflicts:
#	packages/css/all.layered.min.css
#	packages/css/all.min.css

* feat: file with status

* feat: implementation

* refactor: refactor recipe

* chore: scaffold @seed-design/react-middle-truncate package

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(middle-truncate): add splitFileName utility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(middle-truncate): implement MiddleTruncate component with Canvas-based multi-line truncation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: move splitFileName to file-upload package

splitFileName is a file-upload domain concern, not a generic truncation utility.
MiddleTruncate only needs `end` (number of chars to preserve).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(middle-truncate): use Primitive.span with asChild support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add @seed-design/react-middle-truncate dependency to react package

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(file-upload): remove CSS line-clamp from name slot

JS (MiddleTruncate) handles truncation now. CSS keeps overflow:hidden
as a safety net.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(file-upload): integrate MiddleTruncate for extension-preserving filename display

FileUploadItemName now uses MiddleTruncate with splitFileName to preserve
file extensions (e.g. ".pdf") when truncating long filenames. maxLines=2
replaces the previous CSS -webkit-line-clamp approach.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(middle-truncate): replace unit tests with Storybook stories

DOM-mocked unit tests were tautological (mock encoded expected results).
Remove them in favor of Storybook visual tests for truncation accuracy.
Switch measurement from Canvas to DOM-based scrollHeight for correct
multi-line truncation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(middle-truncate): convert to compound component pattern

Split single MiddleTruncate into Root + Content compound components
with hook-first architecture (useMiddleTruncate) and context sharing.
Root now self-measures via rootRef instead of relying on parentElement.
Update FileUpload and Storybook consumers to use new API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor

* refactor

* refactor: simplify snippet api

* feat: focus styles

* refactor: refactor & implement basic dropzone & action button

* refactor: refactor exposed api; add tests

* fix: make form related props follow the text input pattern; add props merging tests

* fix: fix snippet interface

* refactor: refactor snippet API

* refactor

* refactor

* fix: fix styles

* feat: support custom inset

* refactor: provide id to file entry; simplify onFileReject parameter

* refactor

* fix: fix consumers

* feat: add reorderable snippet

* fix: styles

* test: stories

* fix: sync accepted entries with the input

* fix: fix onAcceptedFileEntriesChange being called on file rejection

* fix: fix styles

* fix: add missing snippet item

* docs

* docs

* fix

* test: add dropzone cases

* refactor: rename

* refactor: rename snippet components

* refactor: rename css variable

* refactor: reexport middletruncate from react package

* feat: implement preventDocumentDrop

* feat: filter AutoScroller plugin to prevent default behavior

* feat: add dragging-over style

* feat(attachment-display): add headless package with hook, primitives, and tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(attachment-display): add styled components reusing AttachmentInput CSS recipes

- Root, Container, ItemGroup, Context (attachmentInput recipe)
- Trigger, TriggerIcon, TriggerItemCount (attachmentInputTrigger recipe)
- Item, ItemImage, ItemThumbnail, ItemPreview, ItemActionButton, ItemRemoveButton (attachmentInputItem recipe, type:"image")
- Namespace exports and barrel registration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add AttachmentDisplay documentation, registry snippet, and examples

- Registry snippet with AttachmentDisplayField, AttachmentDisplayInput, AttachmentDisplayItem
- Examples: preview, status, controlled, disabled, bridge integration
- MDX documentation with usage guide and comparison table
- Add headless re-export to @seed-design/react/primitive

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: fix trigger position

* chore: generate

* fix: render retry button only when retry is defined

* fix

* feat: add callback onFileAccept

* fix: fix side effects in render

* fix

* fix: spread stateProps to root

* fix: fix styles

* fix: remove disabled attribute if max files reached

* fix: fix id

* fix: fix className being attached to fragment

* docs

* refactor: rename example components

* refactor

* refactor: remove AttachmentDisplay to separate branch

AttachmentDisplay headless, styled components, docs, registry entries,
and all references in shared files are removed. These will be moved to
a dedicated feat/attachment-display branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: generate

* fix: fix dropzone style when using extend css variable

* fix: fix x axis scroll being disabled; add activity example

* refactor: refactor rootage declaration; add item badge slot

* docs

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants