Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/calm-hats-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@shopify/polaris': minor
'polaris.shopify.com': minor
---

Added `LegacyStack` component
136 changes: 136 additions & 0 deletions polaris-react/src/components/LegacyStack/LegacyStack.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
.LegacyStack {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-4);
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
display: flex;
flex-wrap: wrap;
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
align-items: stretch;
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
margin-top: calc(-1 * var(--pc-stack-spacing));
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
margin-left: calc(-1 * var(--pc-stack-spacing));

> .Item {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
margin-top: var(--pc-stack-spacing);
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
margin-left: var(--pc-stack-spacing);
max-width: 100%;
}
}

.noWrap {
flex-wrap: nowrap;
}

.spacingNone {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-0);
}

.spacingExtraTight {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-1);
}

.spacingTight {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-2);
}

.spacingBaseTight {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-3);
}

.spacingLoose {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-5);
}

.spacingExtraLoose {
// stylelint-disable-next-line -- Polaris component custom properties
--pc-stack-spacing: var(--p-space-8);
}

.distributionLeading {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
justify-content: flex-start;
}

.distributionTrailing {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
justify-content: flex-end;
}

.distributionCenter {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
justify-content: center;
}

.distributionEqualSpacing {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
justify-content: space-between;
}

.distributionFill > .Item {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
flex: 1 1 auto;
}

.distributionFillEvenly > .Item {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
flex: 1 1 auto;

@supports (min-width: fit-content) {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
flex: 1 0 0%;
min-width: fit-content;
}
}

.alignmentLeading {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
align-items: flex-start;
}

.alignmentTrailing {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
align-items: flex-end;
}

.alignmentCenter {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
align-items: center;
}

.alignmentFill {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
align-items: stretch;
}

.alignmentBaseline {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
align-items: baseline;
}

.vertical {
flex-direction: column;
margin-left: var(--p-space-0);

> .Item {
margin-left: var(--p-space-0);
}
}

.Item {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
flex: 0 0 auto;
min-width: 0;
}

.Item-fill {
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
flex: 1 1 auto;
}
96 changes: 96 additions & 0 deletions polaris-react/src/components/LegacyStack/LegacyStack.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from 'react';
import type {ComponentMeta} from '@storybook/react';
import {Badge, Text, LegacyStack} from '@shopify/polaris';

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

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

export function NonWrapping() {
return (
<LegacyStack wrap={false}>
<Badge>Paid</Badge>
<Badge>Processing</Badge>
<Badge>Fulfilled</Badge>
<Badge>Completed</Badge>
</LegacyStack>
);
}

export function Spacing() {
return (
<LegacyStack spacing="loose">
<Badge>Paid</Badge>
<Badge>Fulfilled</Badge>
</LegacyStack>
);
}

export function VerticalCentering() {
return (
<LegacyStack alignment="center">
<Text variant="headingMd" as="h2">
Order
<br />
#1136
<br />
was paid
</Text>
<Badge>Paid</Badge>
<Badge>Fulfilled</Badge>
</LegacyStack>
);
}

export function FillAvailableSpaceProportionally() {
return (
<LegacyStack distribution="fill">
<Text variant="headingMd" as="h2">
Order #1136
</Text>
<Badge>Paid</Badge>
<Badge>Fulfilled</Badge>
</LegacyStack>
);
}

export function WhereItemsFillSpaceEvenly() {
return (
<LegacyStack distribution="fillEvenly">
<Text variant="headingMd" as="h2">
Order #1136
</Text>
<Badge>Paid</Badge>
<Badge>Fulfilled</Badge>
</LegacyStack>
);
}

export function WhereASingleItemFillsTheRemainingSpace() {
return (
<LegacyStack>
<LegacyStack.Item fill>
<Text variant="headingMd" as="h2">
Order #1136
</Text>
</LegacyStack.Item>
<LegacyStack.Item>
<Badge>Paid</Badge>
</LegacyStack.Item>
<LegacyStack.Item>
<Badge>Fulfilled</Badge>
</LegacyStack.Item>
</LegacyStack>
);
}
69 changes: 69 additions & 0 deletions polaris-react/src/components/LegacyStack/LegacyStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, {memo, NamedExoticComponent} from 'react';

import {classNames, variationName} from '../../utilities/css';
import {elementChildren, wrapWithComponent} from '../../utilities/components';

import {Item} from './components';
import styles from './LegacyStack.scss';

type Spacing =
| 'extraTight'
| 'tight'
| 'baseTight'
| 'loose'
| 'extraLoose'
| 'none';

type Alignment = 'leading' | 'trailing' | 'center' | 'fill' | 'baseline';

type Distribution =
| 'equalSpacing'
| 'leading'
| 'trailing'
| 'center'
| 'fill'
| 'fillEvenly';

export interface LegacyStackProps {
/** Elements to display inside stack */
children?: React.ReactNode;
/** Wrap stack elements to additional rows as needed on small screens (Defaults to true) */
wrap?: boolean;
/** Stack the elements vertically */
vertical?: boolean;
/** Adjust spacing between elements */
spacing?: Spacing;
/** Adjust vertical alignment of elements */
alignment?: Alignment;
/** Adjust horizontal alignment of elements */
distribution?: Distribution;
}

export const LegacyStack = memo(function Stack({
children,
vertical,
spacing,
distribution,
alignment,
wrap,
}: LegacyStackProps) {
const className = classNames(
styles.LegacyStack,
vertical && styles.vertical,
spacing && styles[variationName('spacing', spacing)],
distribution && styles[variationName('distribution', distribution)],
alignment && styles[variationName('alignment', alignment)],
wrap === false && styles.noWrap,
);

const itemMarkup = elementChildren(children).map((child, index) => {
const props = {key: index};
return wrapWithComponent(child, Item, props);
});

return <div className={className}>{itemMarkup}</div>;
}) as NamedExoticComponent<LegacyStackProps> & {
Item: typeof Item;
};

LegacyStack.Item = Item;
20 changes: 20 additions & 0 deletions polaris-react/src/components/LegacyStack/components/Item/Item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

import {classNames} from '../../../../utilities/css';
import styles from '../../LegacyStack.scss';

export interface LegacyItemProps {
/** Elements to display inside item */
children?: React.ReactNode;
/** Fill the remaining horizontal space in the stack with the item */
fill?: boolean;
/**
* @default false
*/
}

export function Item({children, fill}: LegacyItemProps) {
const className = classNames(styles.Item, fill && styles['Item-fill']);

return <div className={className}>{children}</div>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Item';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Item';
1 change: 1 addition & 0 deletions polaris-react/src/components/LegacyStack/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './LegacyStack';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import {mountWithApp} from 'tests/utilities';

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

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

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

expect(legacyStack).toContainReactComponentTimes(LegacyStack.Item, 2);
});
});
3 changes: 3 additions & 0 deletions polaris-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ export type {
LegacyCardSubsectionProps,
} from './components/LegacyCard';

export {LegacyStack} from './components/LegacyStack';
export type {LegacyStackProps} from './components/LegacyStack';

export {Link} from './components/Link';
export type {LinkProps} from './components/Link';

Expand Down
Loading