Skip to content

feat(flex): support responsive prop values#284

Open
KYBee wants to merge 5 commits into
devfrom
feature/flex-responsive-contract-kybee-dev
Open

feat(flex): support responsive prop values#284
KYBee wants to merge 5 commits into
devfrom
feature/flex-responsive-contract-kybee-dev

Conversation

@KYBee

@KYBee KYBee commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Flex의 기존 단일 값 prop 계약을 유지하면서 { sm, md, lg } responsive 값을 추가로 받을 수 있도록 확장했습니다.
  • direction, align, justify, wrap, gap에서 단일 값과 breakpoint 객체 값을 모두 지원합니다.
  • responsive class와 media query는 현재 Flex 패키지 내부 계약으로 처리합니다.
  • 추후 @sipe-team/tokens에 정식 breakpoint token이 정의되면, 외부 사용 방식은 유지하고 내부 구현만 token 기반으로 교체할 수 있습니다.
  • @sipe-team/flex minor / @sipe-team/side patch changeset을 추가했습니다.

Visuals

  • Storybook Flex/Responsive 예시를 추가했습니다.

Checklist

  • Have you written the functional specifications?
  • Have you written the test code?

Additional Discussion Points

  • 기존 사용 방식은 계속 호환됩니다.
  • sipe.team 마이그레이션은 이 PR 배포 이후 별도 PR에서 진행할 수 있습니다.

Validation

  • mise exec -- pnpm --filter @sipe-team/flex test -- run src/Flex.test.tsx
  • mise exec -- pnpm --filter @sipe-team/flex typecheck
  • mise exec -- pnpm --filter @sipe-team/flex lint
  • mise exec -- pnpm --filter @sipe-team/flex build
  • mise exec -- pnpm --filter @sipe-team/side typecheck
  • mise exec -- pnpm --filter @sipe-team/side build
  • git diff --check origin/dev..HEAD

@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e9034fd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@sipe-team/flex Minor
@sipe-team/side Patch

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

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • main
  • release/v1

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: ASSERTIVE

Plan: Pro

Run ID: 9d4a488d-c23e-497f-b244-e363dcbb4de9

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/flex-responsive-contract-kybee-dev

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.

@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
packages/flex/src/Flex.css.ts 100.00% <ø> (ø)
packages/flex/src/Flex.test.tsx 100.00% <100.00%> (ø)
packages/flex/src/Flex.tsx 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@KYBee
KYBee marked this pull request as ready for review June 30, 2026 06:30
@KYBee
KYBee marked this pull request as draft June 30, 2026 06:31
@KYBee
KYBee force-pushed the feature/flex-responsive-contract-kybee-dev branch from fa78aeb to 594a33d Compare June 30, 2026 06:44
@KYBee
KYBee marked this pull request as ready for review June 30, 2026 07:00
Comment thread packages/flex/src/Flex.tsx Outdated
Comment on lines +10 to +12
type FlexBreakpoint = 'sm' | 'md' | 'lg';
type ResponsiveValue<T> = T | Partial<Record<FlexBreakpoint, T>>;
type ResponsiveStyleVariants<T extends string> = Record<FlexBreakpoint, Record<T, string>>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

export 하지 않으면 사용부에서 한번 더 정의해야해서 export를 해야할꺼 같습니다~

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

오 감사합니다. 반영하겠습니다!

Comment on lines +10 to +11
md: 'screen and (min-width: 780px)',
lg: 'screen and (min-width: 1060px)',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

780, 1060으로 잡은 이유는 몬가요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

780/1060은 기존 @sipe-team/tokens layout breakpoint(md/lg) 값과 맞춘 값입니다. 해당 token export가 deprecated 상태라 Flex 내부에 로컬 상수로 두고, 그 맥락을 코드 주석에 추가했습니다.

@osohyun0224 osohyun0224 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

고생많으셨습니다 bb

getResponsiveClassNames(direction, 'row', styles.direction),
getResponsiveClassNames(align, 'normal', styles.align),
getResponsiveClassNames(justify, 'normal', styles.justify),
getResponsiveClassNames(wrap, 'nowrap', styles.wrap),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

이거 gap 은 없는데 혹시 의도하신 걸까요...?

gap={{ md: '16px', lg: '24px' }}처럼 sm을 생략하면
780px 미만 화면에서 --side-flex-gap-sm이 설정 안 되서
폴백 없이 무효화되고 gap이 0이 되는 것 같은데.

이게 다른 prop들과 동작이 다른데, 의도하신 걸까요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

문의 주신 부분을 확인해보았습니다. sm을 생략한 구간에서는 Flex의 기본 gap인 normal(flex 레이아웃에서는 0)을 사용하는 동작을 의도했습니다. 다른 responsive prop도 값이 없는 기본 구간에서는 각 prop의 기본값을 사용하고 있어 같은 기준으로 보았습니다. 이번 수정에서는 이 계약이 명확하게 드러나도록 sm 기본값을 명시하고 관련 테스트를 추가했습니다. (e9034fd)

[mediaQuery.lg]: style,
},
})),
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

responsiveGap 처럼 하나의 style() 호출 안에서
@media 우선순위를 명시하는 방식으로 바꾸는 게 더 안전할 것 같습니다.

나중에 이 함수 근처에 다른 mediaQuery.lg 참조가 먼저 추가되거나
객체 프로퍼티 순서가 바뀌면,
lg 값이 적용돼야 할 1060px 이상 화면에서 md 값이 대신 적용되는 일이 생길 수도 있을 것 같습니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

말씀해주신 것처럼 1060px 이상에서는 mdlg 조건이 함께 적용되므로 최종 CSS 선언 순서가 중요하다고 보았습니다. 실제 빌드 결과를 확인한 결과, 현재 responsiveGap의 단일 style()에 선언된 md → lg 순서가 같은 파일의 미디어 규칙 정렬에 반영되어 md 블록 다음에 lg 블록이 생성되고 있었습니다. 이번 변경 후에도 해당 순서가 유지되는 것을 다시 확인했으며, 현재 구조에서는 lg 값이 정상적으로 우선 적용되고 있어 이 부분은 기존 구현을 유지했습니다.

@G-hoon

G-hoon commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

@KYBee 질문이 있습니다.

<Flex gap={{ sm: '8px' }}>
  <div>부모 아이템 1</div>
  <div>부모 아이템 2</div>

  <Flex gap={{ lg: '2px' }}>   {/* sm 생략 */}
    <div>자식 아이템 1</div>
    <div>자식 아이템 2</div>
  </Flex>
</Flex>

의 케이스에 대해서,
자식 엘리먼트에 sm 이 없을 경우 부모로 올라가서, sm 값을 찾아서 사용하는데.
이 경우엔 자식 요소가 sm: 8px 을 상속받아서 사용하는데 의도된 동작이 맞을까요?

코드를 작성하는 입장에서는, 자식 요소의 Flex gap 속성 값이
sm: 0px 로 생각하고 이렇게 작성할 수도 있을 것 같은데.
의도치 않게 부모에 있는 Flex의 요소를 상속 받아서 쓰게 되지 않나 생각이 들어서요.

나중에 Flex 를 매우 복잡하게 사용해야 할 때는, 의도치 못한 이슈가 발생할 수도 있을 것 같은데.
다른 디자인 컴포넌트나 라이브러리 참고한 게 있으면 같이 공유해주시면 좋을 것 같습니다.

@KYBee

KYBee commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

@G-hoon 문의 주신 중첩 케이스를 확인해보았습니다. 이번 responsive API는 별도로 참고한 특정 컴포넌트나 라이브러리 구현은 없으며, 기존 sipe.teamsm, md, lg breakpoint와 현재 Flex prop 계약을 기준으로 설계했습니다.

확인 과정에서 CSS custom property가 상속되면서 자식 Flex가 생략한 breakpoint에서 부모의 gap 값을 가져오는 문제가 있었습니다. 의도한 동작은 아니어서, 자식 Flex가 각 breakpoint 값을 자체 기본값과 직전 breakpoint 값으로 해석하도록 수정했습니다. 예시의 자식 gap={{ lg: "2px" }}은 이제 sm/md에서 기본값 normal(flex 레이아웃에서는 0), lg에서 2px을 사용합니다. 중첩 시 부모 값을 상속하지 않는 테스트도 함께 추가했습니다. (e9034fd)

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.

4 participants