Skip to content
5 changes: 5 additions & 0 deletions .changeset/poor-kiwis-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/polaris': minor
---

Added `AlphaStack` component
51 changes: 51 additions & 0 deletions polaris-react/src/components/AlphaStack/AlphaStack.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import type {ComponentMeta} from '@storybook/react';
import {Badge, AlphaStack} from '@shopify/polaris';

export default {
component: AlphaStack,
} as ComponentMeta<typeof AlphaStack>;

export function Default() {
return (
<AlphaStack>
<Badge>Paid</Badge>
<Badge>Processing</Badge>
<Badge>Fulfilled</Badge>
<Badge>Completed</Badge>
</AlphaStack>
);
}

export function Spacing() {
return (
<AlphaStack spacing="8">
<Badge>Paid</Badge>
<Badge>Processing</Badge>
<Badge>Fulfilled</Badge>
<Badge>Completed</Badge>
</AlphaStack>
);
}

export function AlignCenter() {
return (
<AlphaStack align="center">
<Badge>Paid</Badge>
<Badge>Processing</Badge>
<Badge>Fulfilled</Badge>
<Badge>Completed</Badge>
</AlphaStack>
);
}

export function AlignEnd() {
return (
<AlphaStack align="end">
<Badge>Paid</Badge>
<Badge>Processing</Badge>
<Badge>Fulfilled</Badge>
<Badge>Completed</Badge>
</AlphaStack>
);
}
42 changes: 42 additions & 0 deletions polaris-react/src/components/AlphaStack/AlphaStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import type {spacing} from '@shopify/polaris-tokens';

import {classNames} from '../../utilities/css';

import styles from './Stack.scss';

type SpacingTokenGroup = typeof spacing;
type SpacingTokenName = keyof SpacingTokenGroup;

// TODO: Bring this logic into tokens
type Spacing = SpacingTokenName extends `space-${infer Scale}` ? Scale : never;

type Align = 'start' | 'end' | 'center';

export interface AlphaStackProps {
/** Elements to display inside stack */
children?: React.ReactNode;
/** Adjust spacing between elements */
spacing?: Spacing;
/** Adjust vertical alignment of elements */
align?: Align;
}

export const AlphaStack = ({
children,
spacing = '4',
align = 'start',
}: AlphaStackProps) => {
const className = classNames(styles.Stack);

const style = {
'--pc-stack-align': align,
...(spacing ? {'--pc-stack-spacing': `var(--p-space-${spacing})`} : {}),
} as React.CSSProperties;

return (
<div className={className} style={style}>
{children}
</div>
);
};
6 changes: 6 additions & 0 deletions polaris-react/src/components/AlphaStack/Stack.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.Stack {
display: flex;
flex-direction: column;
align-items: var(--pc-stack-align);
gap: var(--pc-stack-spacing);
}
1 change: 1 addition & 0 deletions polaris-react/src/components/AlphaStack/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './AlphaStack';
14 changes: 14 additions & 0 deletions polaris-react/src/components/AlphaStack/tests/AlphaStack.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import {mountWithApp} from 'tests/utilities';

import {AlphaStack} from '../AlphaStack';

describe('<AlphaStack />', () => {
const renderChildren = () => [0, 1].map((i) => <div key={i}>Child {i}</div>);

it('renders its children', () => {
const stack = mountWithApp(<AlphaStack>{renderChildren()}</AlphaStack>);

expect(stack).toContainReactComponentTimes('div', 3);
});
});
3 changes: 3 additions & 0 deletions polaris-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export type {
export {ActionMenu} from './components/ActionMenu';
export type {ActionMenuProps} from './components/ActionMenu';

export {AlphaStack} from './components/AlphaStack';
export type {AlphaStackProps} from './components/AlphaStack';

export {Autocomplete} from './components/Autocomplete';
export type {AutocompleteProps} from './components/Autocomplete';

Expand Down