Skip to content

core: add Stack and Separator component #97052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 7, 2025
Merged

core: add Stack and Separator component #97052

merged 8 commits into from
Aug 7, 2025

Conversation

JonasBa
Copy link
Member

@JonasBa JonasBa commented Aug 2, 2025

Adds a Stack and Separator component.

The Stack.Separator is essentially just a wrapper around the Separator that omits the orientation prop. We want to do this to avoid possible user error where they would end up displaying a horizontal separator in a horizontal row.

The orientation management is handled via OrientationContext from inside the Stack Component. An alternative could have been to use cloneElement with a bit of detection for the Separator element and provide the prop, but I think context is fine given that the context consumer is scoped to the Stack.Separator component.

core: add separator component

core: add core separator

core: add separator
@JonasBa JonasBa requested a review from a team as a code owner August 2, 2025 14:46
@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Aug 2, 2025
Comment on lines +176 to +177
query: window.matchMedia(`(min-width: ${theme.breakpoints[bp]})`),
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Potential bug: The `useResponsivePropValue` hook accesses `window.matchMedia` without a safety check, which will cause a crash during server-side rendering (SSR).
  • Description: The useResponsivePropValue hook directly calls window.matchMedia during component initialization. In a server-side rendering (SSR) environment, where the window object is not available, this will throw a ReferenceError: window is not defined. This error will cause the server rendering process to crash whenever a component using this hook, such as Stack, is rendered. Other parts of the codebase already use safe access patterns like typeof window !== 'undefined' or optional chaining (window.matchMedia?.()), which this new code fails to implement.
  • Suggested fix: Add a check to ensure window is defined before calling window.matchMedia. Use optional chaining (window.matchMedia?.()) or a condition like typeof window !== 'undefined'. The hook should return a default or undefined value during server-side rendering to prevent the crash.
    severity: 0.9, confidence: 0.95

Did we get this right? 👍 / 👎 to inform future reviews.

cursor[bot]

This comment was marked as outdated.

Copy link

codecov bot commented Aug 2, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #97052   +/-   ##
=======================================
  Coverage   80.67%   80.67%           
=======================================
  Files        8549     8549           
  Lines      376208   376208           
  Branches    24443    24443           
=======================================
  Hits       303503   303503           
  Misses      72333    72333           
  Partials      372      372           

cursor[bot]

This comment was marked as outdated.

Copy link
Contributor

@TkDodo TkDodo left a comment

Choose a reason for hiding this comment

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

looks great 🔥

Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Responsive Prop Handling Mismatch

The getOrientationFromDirection function has a type mismatch: it expects the raw StackLayoutProps['direction'] (which can include responsive objects), but it's called with the resolved string value from useResponsivePropValue. Additionally, useResponsivePropValue can return undefined if all responsive breakpoints are undefined (e.g., direction={{sm: undefined}}). Passing this undefined value to getOrientationFromDirection results in a TypeError with the message "No Stack Direction was provided".

static/app/components/core/layout/stack.tsx#L153-L196

https://github.com/getsentry/sentry/blob/2f513286d4c3d212e97806eacccb70e749fa5b04/static/app/components/core/layout/stack.tsx#L153-L196

static/app/components/core/layout/stack.tsx#L40-L42

function getOrientationFromDirection(
direction: NonNullable<StackLayoutProps['direction']>

Fix in Cursor Fix in Web

Copy link
Contributor

@TkDodo TkDodo left a comment

Choose a reason for hiding this comment

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

nice 🙌

@JonasBa JonasBa merged commit b030355 into master Aug 7, 2025
46 checks passed
@JonasBa JonasBa deleted the jb/core/divider branch August 7, 2025 13:25
andrewshie-sentry pushed a commit that referenced this pull request Aug 7, 2025
Adds a Stack and Separator component.

The Stack.Separator is essentially just a wrapper around the Separator
that omits the orientation prop. We want to do this to avoid possible
user error where they would end up displaying a horizontal separator in
a horizontal row.

The orientation management is handled via OrientationContext from inside
the Stack Component. An alternative could have been to use cloneElement
with a bit of detection for the Separator element and provide the prop,
but I think context is fine given that the context consumer is scoped to
the Stack.Separator component.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Scope: Frontend Automatically applied to PRs that change frontend components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants