Skip to content

Commit 3840f49

Browse files
gwyneplaineraquelbreternitzRaquel Breternitzjesstelford
authored
Reboot Polaris patterns (#7843)
## Reboot Pattern Guidance See [Reboot Polaris patterns vault project](https://vault.shopify.io/gsd/projects/30559) - New layout primitives `Stack`, `Box`, `Grid`, `Row`. - Playroom patched to support larger code snippets. - New designs and content for the [patterns](https://polaris.shopify.com/patterns) pages. - Deprecated old patterns: ||Old|New| |--|--|--| |**design-patterns** | `/patterns/design-patterns` | `404`| |**page-layouts** | `/patterns/page-layouts` | `404`| |**error-messages** | `/patterns/error-messages` | `/content/error-messages`| |**help-content** | `/patterns/help-content` | `/content/help-content`| |**loading** | `/patterns/loading` | `/patterns-legacy/loading`| |**new-badge** | `/patterns/new-badge` | `/patterns-legacy/new-badge`| |**pickers** | `/patterns/pickers` | `/patterns-legacy/pickers`| |**text-fields** | `/patterns/text-fields` | `/patterns-legacy/text-fields`| - Page padding and max-width adjusted such that live previews for components and patterns always display the desktop breakpoint. ### How to 🎩 🖥 [Local development instructions](https://github.com/Shopify/polaris/blob/main/README.md#local-development) 🗒 [General tophatting guidelines](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md) 📄 [Changelog guidelines](https://github.com/Shopify/polaris/blob/main/.github/CONTRIBUTING.md#changelog) <!-- Give as much information as needed to experiment with the component in the playground. --> <details> <summary>Copy-paste this code in <code>playground/Playground.tsx</code>:</summary> ```jsx import React from 'react'; import {Page} from '../src'; export function Playground() { return ( <Page title="Playground"> {/* Add the code you want to test in here */} </Page> ); } ``` </details> ### 🎩 checklist - [ ] Tested on [mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [ ] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) - [ ] Tested for [accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - [ ] Updated the component's `README.md` with documentation changes - [ ] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide --------- Co-authored-by: Raquel Breternitz <raquelbreternitz@gmail.com> Co-authored-by: Raquel Breternitz <raquel.breternitz@shopify.com> Co-authored-by: Jess Telford <jess+github@jes.st> Co-authored-by: Jess Telford <jess.telford@shopify.com>
1 parent c606175 commit 3840f49

File tree

129 files changed

+4168
-535
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+4168
-535
lines changed

.changeset/tame-adults-wash.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'polaris.shopify.com': minor
3+
---
4+
5+
## Reboot Pattern Guidance
6+
7+
- New layout primitives `Stack`, `Box`, `Grid`, `Row`.
8+
- Playroom patched to support larger code snippets.
9+
- New designs and content for the [patterns](https://polaris.shopify.com/patterns) pages.
10+
- Deprecated old patterns:
11+
||Old|New|
12+
|--|--|--|
13+
|**design-patterns** | `/patterns/design-patterns` | `404`|
14+
|**page-layouts** | `/patterns/page-layouts` | `404`|
15+
|**error-messages** | `/patterns/error-messages` | `/content/error-messages`|
16+
|**help-content** | `/patterns/help-content` | `/content/help-content`|
17+
|**loading** | `/patterns/loading` | `/patterns-legacy/loading`|
18+
|**new-badge** | `/patterns/new-badge` | `/patterns-legacy/new-badge`|
19+
|**pickers** | `/patterns/pickers` | `/patterns-legacy/pickers`|
20+
|**text-fields** | `/patterns/text-fields` | `/patterns-legacy/text-fields`|
21+
- Page padding and max-width adjusted such that live previews for components and patterns always display the desktop breakpoint.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
.turbo
99
dist
1010
node_modules
11+
Session.vim
1112
/polaris-react/build
1213
/polaris-react/build-internal
1314
/polaris-react/src/styles/_media-queries.scss

patches/playroom+0.28.0.patch

Lines changed: 173 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ index 6c82bbe..f05b80b 100644
55
@@ -160,6 +160,12 @@ export { themeB } from './themeB';
66
// etc...
77
```
8-
8+
99
+## Additional Code Transformations
1010
+
1111
+A hook into the internal processing of code is available via the `processCode` option, which is a path to a file that exports a function that receives the code as entered into the editor, and returns the new code to be rendered.
1212
+
1313
+One example is [wrapping code in an IIFE for state support](https://github.com/seek-oss/playroom/issues/66).
1414
+
1515
## TypeScript Support
16-
16+
1717
If a `tsconfig.json` file is present in your project, static prop types are parsed using [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript) to provide better autocompletion in the Playroom editor.
1818
diff --git a/node_modules/playroom/lib/defaultModules/processCode.js b/node_modules/playroom/lib/defaultModules/processCode.js
1919
new file mode 100644
@@ -36,6 +36,173 @@ index 56defa7..1e7cf3b 100644
3636
},
3737
},
3838
module: {
39+
diff --git a/node_modules/playroom/src/Playroom/Frame.tsx b/node_modules/playroom/src/Playroom/Frame.tsx
40+
index b175d74..ce3e7ef 100644
41+
--- a/node_modules/playroom/src/Playroom/Frame.tsx
42+
+++ b/node_modules/playroom/src/Playroom/Frame.tsx
43+
@@ -1,9 +1,9 @@
44+
-import React from 'react';
45+
-import { useParams } from '../utils/params';
46+
+import React, { useEffect, useState } from 'react';
47+
// @ts-ignore
48+
import CatchErrors from './CatchErrors/CatchErrors';
49+
// @ts-ignore
50+
import RenderCode from './RenderCode/RenderCode';
51+
+import { INCOMING_CODE, READY_TO_RECEIVE } from './constants';
52+
53+
interface FrameProps {
54+
themes: Record<string, any>;
55+
@@ -18,11 +18,21 @@ export default function Frame({
56+
components,
57+
FrameComponent,
58+
}: FrameProps) {
59+
- const { themeName, code } = useParams((rawParams) => ({
60+
- themeName:
61+
- typeof rawParams.themeName === 'string' ? rawParams.themeName : '',
62+
- code: typeof rawParams.code === 'string' ? rawParams.code : '',
63+
- }));
64+
+ const [code, setCode] = useState(`/*#__PURE__*/
65+
+ React.createElement(React.Fragment, null);`);
66+
+ const [themeName, setThemeName] = useState('');
67+
+ useEffect(() => {
68+
+ const listener = (e: any) => {
69+
+ if (e.data && e.data.type === INCOMING_CODE ) {
70+
+ setCode(e.data.code);
71+
+ setThemeName(e.data.themeName);
72+
+ };
73+
+
74+
+ }
75+
+ window.addEventListener('message', listener);
76+
+ window.parent.postMessage({ type: READY_TO_RECEIVE, ready: true }, window.origin);
77+
+ return () => window.removeEventListener('message', listener);
78+
+ }, []);
79+
80+
const resolvedThemeName =
81+
themeName === '__PLAYROOM__NO_THEME__' ? null : themeName;
82+
diff --git a/node_modules/playroom/src/Playroom/Frames/Frames.tsx b/node_modules/playroom/src/Playroom/Frames/Frames.tsx
83+
index 5b4af43..3bb2615 100644
84+
--- a/node_modules/playroom/src/Playroom/Frames/Frames.tsx
85+
+++ b/node_modules/playroom/src/Playroom/Frames/Frames.tsx
86+
@@ -6,7 +6,6 @@ import { PlayroomProps } from '../Playroom';
87+
import { Strong } from '../Strong/Strong';
88+
import { Text } from '../Text/Text';
89+
import playroomConfig from '../../config';
90+
-import frameSrc from './frameSrc';
91+
92+
import * as styles from './Frames.css';
93+
94+
@@ -44,10 +43,9 @@ export default function Frames({ code, themes, widths }: FramesProps) {
95+
<div className={styles.frameBorder} />
96+
<Iframe
97+
intersectionRootRef={scrollingPanelRef}
98+
- src={frameSrc(
99+
- { themeName: frame.theme, code: renderCode },
100+
- playroomConfig
101+
- )}
102+
+ code={renderCode}
103+
+ themeName={frame.theme}
104+
+ src={`${playroomConfig.baseUrl}frame.html`}
105+
className={styles.frame}
106+
style={{ width: frame.width }}
107+
data-testid="previewFrame"
108+
diff --git a/node_modules/playroom/src/Playroom/Frames/Iframe.tsx b/node_modules/playroom/src/Playroom/Frames/Iframe.tsx
109+
index 9285b94..cd57b41 100644
110+
--- a/node_modules/playroom/src/Playroom/Frames/Iframe.tsx
111+
+++ b/node_modules/playroom/src/Playroom/Frames/Iframe.tsx
112+
@@ -6,22 +6,29 @@ import React, {
113+
MutableRefObject,
114+
} from 'react';
115+
import { useIntersection } from 'react-use';
116+
+import { READY_TO_RECEIVE, INCOMING_CODE } from '../constants';
117+
118+
import playroomConfig from '../../config';
119+
120+
interface IframeProps extends AllHTMLAttributes<HTMLIFrameElement> {
121+
src: string;
122+
+ code: string;
123+
+ themeName: string;
124+
intersectionRootRef: MutableRefObject<Element | null>;
125+
}
126+
127+
+
128+
export default function Iframe({
129+
intersectionRootRef,
130+
+ code,
131+
+ themeName,
132+
style,
133+
src,
134+
...restProps
135+
}: IframeProps) {
136+
const [loaded, setLoaded] = useState(false);
137+
- const [renderedSrc, setRenderedSrc] = useState<string | null>(null);
138+
+ const [renderedSrc, setRenderedSrc] = useState<string | undefined>(undefined);
139+
+ const [readyToPost, setReadyToPost] = useState(false);
140+
const iframeRef = useRef<HTMLIFrameElement | null>(null);
141+
const intersection = useIntersection(iframeRef, {
142+
root: intersectionRootRef.current,
143+
@@ -32,35 +39,41 @@ export default function Iframe({
144+
const intersectionRatio = intersection?.intersectionRatio ?? null;
145+
146+
useEffect(() => {
147+
- if (intersectionRatio === null) {
148+
- return;
149+
+ if (intersectionRatio === null) return;
150+
+ const listener = (e: any) => {
151+
+ if (e.data.type === READY_TO_RECEIVE && e.source === iframeRef.current?.contentWindow) {
152+
+ setReadyToPost(true);
153+
+ const contentWindow = iframeRef.current?.contentWindow;
154+
+ if (contentWindow) {
155+
+ contentWindow.postMessage({ type: INCOMING_CODE, themeName, code }, window.origin);
156+
+ }
157+
+ }
158+
}
159+
+ window.addEventListener('message', listener);
160+
161+
if (intersectionRatio > 0 && src !== renderedSrc) {
162+
setRenderedSrc(src);
163+
}
164+
+ return () => window.removeEventListener('message', listener);
165+
}, [intersectionRatio, src, renderedSrc]);
166+
167+
useEffect(() => {
168+
- if (renderedSrc !== null) {
169+
- const location = iframeRef.current?.contentWindow?.location;
170+
-
171+
- if (location) {
172+
- location.replace(renderedSrc);
173+
+ if (readyToPost) {
174+
+ const contentWindow = iframeRef.current?.contentWindow;
175+
+ if (contentWindow) {
176+
+ contentWindow.postMessage({ type: INCOMING_CODE, themeName, code }, window.origin);
177+
}
178+
}
179+
- }, [renderedSrc]);
180+
+ }, [readyToPost, code])
181+
+
182+
+
183+
184+
return (
185+
<iframe
186+
ref={iframeRef}
187+
sandbox={playroomConfig.iframeSandbox}
188+
onLoad={() => setLoaded(true)}
189+
- onMouseEnter={() => {
190+
- if (src !== renderedSrc) {
191+
- setRenderedSrc(src);
192+
- }
193+
- }}
194+
+ src={renderedSrc}
195+
style={{
196+
...style,
197+
transition: 'opacity .3s ease',
198+
diff --git a/node_modules/playroom/src/Playroom/constants.ts b/node_modules/playroom/src/Playroom/constants.ts
199+
new file mode 100644
200+
index 0000000..90c35d0
201+
--- /dev/null
202+
+++ b/node_modules/playroom/src/Playroom/constants.ts
203+
@@ -0,0 +1,2 @@
204+
+export const READY_TO_RECEIVE = "PLAYROOM_READY_TO_RECEIVE";
205+
+export const INCOMING_CODE = "PLAYROOM_INCOMING_CODE";
39206
diff --git a/node_modules/playroom/src/utils/compileJsx.ts b/node_modules/playroom/src/utils/compileJsx.ts
40207
index dadea77..82d080c 100644
41208
--- a/node_modules/playroom/src/utils/compileJsx.ts
@@ -44,7 +211,7 @@ index dadea77..82d080c 100644
44211
import { transform } from '@babel/standalone';
45212
+/* eslint-disable-next-line import/no-unresolved */
46213
+import processCode from '__PLAYROOM_ALIAS__PROCESS_CODE__';
47-
214+
48215
-export const compileJsx = (code: string) =>
49216
- transform(`<React.Fragment>${code.trim() || ''}</React.Fragment>`, {
50217
+export const compileJsx = (code: string) => {
@@ -58,7 +225,7 @@ index dadea77..82d080c 100644
58225
presets: ['react'],
59226
}).code;
60227
+}
61-
228+
62229
export const validateCode = (code: string) => {
63230
try {
64231
diff --git a/node_modules/playroom/src/utils/formatting.ts b/node_modules/playroom/src/utils/formatting.ts
@@ -68,13 +235,13 @@ index a1819bf..70ac15c 100644
68235
@@ -133,10 +133,10 @@ export const formatAndInsert = ({
69236
snippet,
70237
});
71-
238+
72239
- return formatCode({
73240
+ return {
74241
code: newCode,
75242
cursor: updatedCursor,
76243
- });
77244
+ };
78245
};
79-
246+
80247
export const formatForInsertion = ({

polaris.shopify.com/content/components/layout-and-structure/page.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ keywords:
1919
- outer wrapper
2020
- page actions
2121
- page layouts
22+
updateBannerMessage: We are [adding patterns](/patterns) to our documentation. Check out related patterns, expect changes to happen, and [join the discussion](https://github.com/Shopify/polaris/discussions/categories/pattern-documentation) to make it better!
2223
examples:
2324
- fileName: page-default.tsx
2425
title: Default
@@ -158,3 +159,8 @@ Add a menu item
158159
- To lay out the content within a page, use the [layout component](https://polaris.shopify.com/components/layout-and-structure/layout)
159160
- To add pagination within the context of a list or other page content, use the [pagination component](https://polaris.shopify.com/components/navigation/pagination)
160161
- To add primary and secondary calls to action at the bottom of a page, see the [page actions component](https://polaris.shopify.com/components/actions/page-actions)
162+
163+
## Related patterns
164+
165+
- [App settings layout](/patterns/app-settings-layout)
166+
- [Resource details layout](/patterns/resource-details-layout)

polaris.shopify.com/content/components/navigation/navigation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ The navigation component should:
6868
- Use a major icon for item actions.
6969
- Use a minor icon for secondary actions.
7070
- Use the provided navigation section component to group navigation items.
71-
- Not add additional components, like [badge](/components/feedback-indicators/badge), in navigation items. Example: Don‘t add the [New badge](/patterns/new-badge).
71+
- Not add additional components, like [badge](/components/feedback-indicators/badge), in navigation items. Example: Don‘t add the [New badge](/patterns-legacy/new-badge).
7272

7373
---
7474

polaris.shopify.com/content/components/selection-and-input/date-picker.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ keywords:
1616
- date selector
1717
- date range picker
1818
- date range selector
19+
updateBannerMessage: We are [adding patterns](/patterns) to our documentation. Check out related patterns, expect changes to happen, and [join the discussion](https://github.com/Shopify/polaris/discussions/categories/pattern-documentation) to make it better!
1920
examples:
2021
- fileName: date-picker-default.tsx
2122
title: Default
@@ -57,3 +58,7 @@ If you use the date picker within a [popover component](/components/overlays/pop
5758
- Press the <kbd>tab</kbd> key to move forward and <kbd>shift</kbd> + <kbd>tab</kbd> to move backward through the previous button, next button, and the calendar
5859
- When focus is in the calendar, move keyboard focus between the dates using the arrow keys
5960
- To select a date that has focus, press the <kbd>enter</kbd>/<kbd>return</kbd> key
61+
62+
## Related patterns
63+
64+
- [Date picking](/patterns/date-picking)
File renamed without changes.
File renamed without changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: Patterns (legacy)
3+
description: Design patterns help ensure consistent behavior across the Shopify admin.
4+
status:
5+
value: Deprecated
6+
message: These patterns are deprecated, please use with caution.
7+
noIndex: true
8+
hideFromNav: true
9+
---

polaris.shopify.com/content/patterns/loading.md renamed to polaris.shopify.com/content/patterns-legacy/loading.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
title: Loading
33
description: Navigating the Shopify admin should be fast, meaningful, and focused. Intentional loading states deliver a continuous flow for merchants.
44
icon: RefreshMajor
5+
noIndex: true
6+
status:
7+
value: Deprecated
8+
message: This pattern is no longer supported.
59
keywords:
610
- page loading
711
- loading

0 commit comments

Comments
 (0)