From 6a26eab99e16a1ef95888f1c7545e13a46d0299e Mon Sep 17 00:00:00 2001 From: Adam Dierkens Date: Tue, 1 Jul 2025 10:49:58 -0400 Subject: [PATCH 1/3] Add shrink support to Stack.Item --- packages/react/src/Stack/Stack.docs.json | 5 ++ .../src/Stack/Stack.features.stories.tsx | 25 ++++++ packages/react/src/Stack/Stack.module.css | 21 +++++ packages/react/src/Stack/Stack.stories.tsx | 78 ++++++++----------- packages/react/src/Stack/Stack.tsx | 10 ++- 5 files changed, 94 insertions(+), 45 deletions(-) create mode 100644 packages/react/src/Stack/Stack.features.stories.tsx diff --git a/packages/react/src/Stack/Stack.docs.json b/packages/react/src/Stack/Stack.docs.json index 968e1143328..280e2d26fa1 100644 --- a/packages/react/src/Stack/Stack.docs.json +++ b/packages/react/src/Stack/Stack.docs.json @@ -50,6 +50,11 @@ "type": "boolean | ResponsiveValue", "description": "Allow item to keep size or expand to fill the available space." }, + { + "name": "shrink", + "type": "boolean | ResponsiveValue", + "description": "Allow item to keep size or shrink to fit the available space." + }, { "name": "className", "type": "string" diff --git a/packages/react/src/Stack/Stack.features.stories.tsx b/packages/react/src/Stack/Stack.features.stories.tsx new file mode 100644 index 00000000000..1b0ce0aa736 --- /dev/null +++ b/packages/react/src/Stack/Stack.features.stories.tsx @@ -0,0 +1,25 @@ +import type {Meta} from '@storybook/react-vite' +import {Stack} from '../Stack' +import {ShieldLockIcon} from '@primer/octicons-react' + +export default { + title: 'Components/Stack/Features', + component: Stack, +} as Meta + +export const ShrinkingStackItems = () => ( +
+ + + + + This stack has the leading icon set to prevent shrinking + + + + + + This stack item does not have the icon set to prevent shrinking + +
+) diff --git a/packages/react/src/Stack/Stack.module.css b/packages/react/src/Stack/Stack.module.css index d486159f684..cdb652b07b8 100644 --- a/packages/react/src/Stack/Stack.module.css +++ b/packages/react/src/Stack/Stack.module.css @@ -296,6 +296,11 @@ flex: 0 1 auto; min-inline-size: 0; + &[data-shrink='false'], + &[data-shrink-narrow='false'] { + flex-shrink: 0; + } + &[data-grow='true'], &[data-grow-narrow='true'] { flex-grow: 1; @@ -309,6 +314,14 @@ &[data-grow-regular='false'] { flex-grow: 0; } + + &[data-shrink-regular='true'] { + flex-shrink: 1; + } + + &[data-shrink-regular='false'] { + flex-shrink: 0; + } } @media (--viewportRange-wide) { @@ -319,5 +332,13 @@ &[data-grow-wide='false'] { flex-grow: 0; } + + &[data-shrink-wide='true'] { + flex-shrink: 1; + } + + &[data-shrink-wide='false'] { + flex-shrink: 0; + } } } diff --git a/packages/react/src/Stack/Stack.stories.tsx b/packages/react/src/Stack/Stack.stories.tsx index 984fb2cc61d..845a12e5926 100644 --- a/packages/react/src/Stack/Stack.stories.tsx +++ b/packages/react/src/Stack/Stack.stories.tsx @@ -1,6 +1,7 @@ import type {Meta, StoryObj} from '@storybook/react-vite' import {Stack} from '../Stack' import type {ResponsiveValue} from '../hooks/useResponsiveValue' +import type {InputType} from '@storybook/csf' type Story = StoryObj @@ -468,58 +469,42 @@ export const Playground: Story = { }, } +function createArgMetaData(category: string): InputType { + return { + control: { + type: 'boolean', + }, + table: { + category, + defaultValue: { + summary: 'true', + }, + }, + } +} + export const StackItemPlayground: Story = { args: { grow: true, growNarrow: true, growRegular: true, growWide: true, + + shrink: true, + shrinkNarrow: true, + shrinkRegular: true, + shrinkWide: true, }, argTypes: { - grow: { - control: { - type: 'boolean', - }, - table: { - category: 'Properties', - defaultValue: { - summary: 'true', - }, - }, - }, - growNarrow: { - control: { - type: 'boolean', - }, - table: { - category: 'Narrow properties', - defaultValue: { - summary: 'true', - }, - }, - }, - growRegular: { - control: { - type: 'boolean', - }, - table: { - category: 'Regular properties', - defaultValue: { - summary: 'true', - }, - }, - }, - growWide: { - control: { - type: 'boolean', - }, - table: { - category: 'Wide properties', - defaultValue: { - summary: 'true', - }, - }, - }, + grow: createArgMetaData('Properties'), + growNarrow: createArgMetaData('Narrow properties'), + growRegular: createArgMetaData('Regular properties'), + growWide: createArgMetaData('Wide properties'), + + shrink: createArgMetaData('Properties'), + shrinkNarrow: createArgMetaData('Narrow properties'), + shrinkRegular: createArgMetaData('Regular properties'), + shrinkWide: createArgMetaData('Wide properties'), }, render: args => { return ( @@ -530,6 +515,11 @@ export const StackItemPlayground: Story = { regular: args.growRegular, wide: args.growWide, })} + shrink={getControlValues(args.shrink, { + narrow: args.shrinkNarrow, + regular: args.shrinkRegular, + wide: args.shrinkWide, + })} >
= React.PropsWithChildren<{ * @default false */ grow?: boolean | ResponsiveValue + + /** + * Allow item to keep size or expand to fill the available space + * @default true + */ + shrink?: boolean | ResponsiveValue + className?: string }> -const StackItem = forwardRef(({as, children, grow, className, ...rest}, forwardedRef) => { +const StackItem = forwardRef(({as, children, grow, shrink, className, ...rest}, forwardedRef) => { return ( {children} From 97b4f451527a14c3597f8d1d5fe55e5881157460 Mon Sep 17 00:00:00 2001 From: Adam Dierkens Date: Tue, 1 Jul 2025 10:55:49 -0400 Subject: [PATCH 2/3] Add tests for prop behavior --- .../src/Stack/__tests__/StackItem.test.tsx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/react/src/Stack/__tests__/StackItem.test.tsx b/packages/react/src/Stack/__tests__/StackItem.test.tsx index 8d8b1d2415e..b706c6ad76b 100644 --- a/packages/react/src/Stack/__tests__/StackItem.test.tsx +++ b/packages/react/src/Stack/__tests__/StackItem.test.tsx @@ -46,6 +46,28 @@ describe('StackItem', () => { expect(screen.getByTestId('responsive-grow')).toHaveAttribute('data-grow-wide', 'true') }) + it('should support the `shrink` prop', () => { + render( + + + + , + ) + expect(screen.getByTestId('shrink-true')).toHaveAttribute('data-shrink', 'true') + expect(screen.getByTestId('shrink-false')).not.toHaveAttribute('data-shrink', 'false') + }) + + it('should support responsive `shrink` values', () => { + render( + + + , + ) + expect(screen.getByTestId('responsive-shrink')).toHaveAttribute('data-shrink-narrow', 'true') + expect(screen.getByTestId('responsive-shrink')).toHaveAttribute('data-shrink-regular', 'false') + expect(screen.getByTestId('responsive-shrink')).toHaveAttribute('data-shrink-wide', 'true') + }) + it('should render a custom component with the `as` prop', () => { const CustomComponent = vi.fn(({children}: React.PropsWithChildren) => { return
{children}
From bb826033d446ea137cb64b38d0acf810417423cb Mon Sep 17 00:00:00 2001 From: Adam Dierkens Date: Tue, 1 Jul 2025 11:02:37 -0400 Subject: [PATCH 3/3] Add changeset --- .changeset/good-bars-see.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/good-bars-see.md diff --git a/.changeset/good-bars-see.md b/.changeset/good-bars-see.md new file mode 100644 index 00000000000..76453f92790 --- /dev/null +++ b/.changeset/good-bars-see.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Stack.Item: add support for `shrink` prop