@microbit/ui 0.1.0-alpha.21 → 0.1.0-alpha.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE.md +5 -5
  2. package/README.md +29 -13
  3. package/lang/ui.ca.json +12 -12
  4. package/lang/ui.cy.json +4 -4
  5. package/lang/ui.de.json +6 -6
  6. package/lang/ui.es-es.json +5 -5
  7. package/lang/ui.fr.json +6 -6
  8. package/lang/ui.ga-ie.json +6 -6
  9. package/lang/ui.it.json +4 -4
  10. package/lang/ui.ja.json +7 -7
  11. package/lang/ui.ko.json +6 -6
  12. package/lang/ui.lo.json +58 -0
  13. package/lang/ui.nl.json +9 -9
  14. package/lang/ui.pl.json +8 -8
  15. package/lang/ui.pt-br.json +7 -7
  16. package/lang/ui.vi.json +58 -0
  17. package/lang/ui.zh-cn.json +6 -6
  18. package/lang/ui.zh-tw.json +7 -7
  19. package/package.json +1 -1
  20. package/src/Avatar.recipe.ts +16 -20
  21. package/src/Avatar.tsx +31 -29
  22. package/src/Breadcrumb.recipe.ts +3 -7
  23. package/src/Breadcrumb.tsx +6 -8
  24. package/src/Button.recipe.ts +22 -33
  25. package/src/Button.tsx +10 -12
  26. package/src/ButtonGroup.tsx +10 -9
  27. package/src/Card.recipe.ts +1 -2
  28. package/src/Card.tsx +2 -1
  29. package/src/Checkbox.recipe.ts +7 -9
  30. package/src/Checkbox.tsx +2 -3
  31. package/src/CheckboxGroup.tsx +5 -7
  32. package/src/CloseButton.tsx +2 -2
  33. package/src/CloseIcon.tsx +6 -4
  34. package/src/Code.tsx +1 -1
  35. package/src/Collapse.tsx +13 -14
  36. package/src/Divider.tsx +3 -3
  37. package/src/Drawer.recipe.ts +4 -5
  38. package/src/Drawer.tsx +3 -4
  39. package/src/Fade.tsx +6 -10
  40. package/src/Field.recipe.ts +9 -12
  41. package/src/Field.tsx +16 -18
  42. package/src/GridList.recipe.ts +1 -2
  43. package/src/Heading.recipe.ts +5 -5
  44. package/src/Heading.tsx +3 -3
  45. package/src/Icon.tsx +7 -11
  46. package/src/IconButton.tsx +1 -1
  47. package/src/Image.tsx +1 -1
  48. package/src/Input.recipe.ts +5 -6
  49. package/src/Input.tsx +4 -4
  50. package/src/InputGroup.tsx +4 -5
  51. package/src/Kbd.tsx +1 -1
  52. package/src/Link.tsx +2 -2
  53. package/src/LinkBox.tsx +2 -3
  54. package/src/LinkButton.tsx +4 -4
  55. package/src/List.tsx +5 -7
  56. package/src/Menu.recipe.ts +15 -16
  57. package/src/Menu.tsx +9 -13
  58. package/src/Modal.recipe.ts +7 -8
  59. package/src/Modal.tsx +19 -24
  60. package/src/NativeSelect.tsx +16 -16
  61. package/src/NumberField.recipe.ts +25 -11
  62. package/src/NumberField.tsx +4 -4
  63. package/src/PopoverArrow.tsx +1 -2
  64. package/src/ProgressBar.tsx +2 -4
  65. package/src/Radio.recipe.ts +8 -9
  66. package/src/Radio.tsx +2 -2
  67. package/src/RadioGroup.tsx +4 -5
  68. package/src/Select.recipe.ts +9 -9
  69. package/src/Select.tsx +8 -9
  70. package/src/Skeleton.tsx +13 -15
  71. package/src/Slide.tsx +2 -2
  72. package/src/Slider.recipe.ts +11 -14
  73. package/src/Slider.tsx +3 -7
  74. package/src/Spinner.tsx +6 -9
  75. package/src/Svg.tsx +2 -3
  76. package/src/Switch.recipe.ts +4 -5
  77. package/src/Switch.tsx +3 -4
  78. package/src/Text.recipe.ts +4 -7
  79. package/src/Text.tsx +2 -2
  80. package/src/TextField.tsx +3 -4
  81. package/src/Toast.recipe.ts +43 -11
  82. package/src/Toast.tsx +69 -40
  83. package/src/Tooltip.recipe.ts +4 -9
  84. package/src/Tooltip.tsx +48 -10
  85. package/src/TooltipButton.tsx +229 -0
  86. package/src/UnmountCallback.tsx +2 -2
  87. package/src/VisuallyHidden.tsx +1 -1
  88. package/src/base-preset.ts +38 -43
  89. package/src/button-icon.ts +2 -3
  90. package/src/dense-preset.ts +6 -7
  91. package/src/hooks/useBreakpointValue.ts +4 -4
  92. package/src/hooks/useClipboard.ts +5 -6
  93. package/src/hooks/useDisclosure.ts +4 -5
  94. package/src/hooks/useMediaQuery.ts +3 -4
  95. package/src/hooks/usePrevious.ts +1 -4
  96. package/src/index.ts +4 -3
  97. package/src/system.ts +2 -2
@@ -63,7 +63,7 @@ import { toast } from "./Toast.recipe";
63
63
  // Override values, never names: raw var(--colors-gray-*) references and
64
64
  // paired private presets depend on the names, so a rename is a breaking
65
65
  // change to both and needs every app and paired preset moved in lockstep
66
- // (as was done when Chakra's misnamed darker-than-50 stop `25` became
66
+ // (as was done when the misnamed darker-than-50 stop `25` became
67
67
  // `75`). And never override partially in a way that lets a stop fall
68
68
  // through to a different grey system.
69
69
  const gray = {
@@ -88,17 +88,17 @@ const gray = {
88
88
  * (pill `radii.button`, `outline*` focus shadows, Helvetica fonts, the
89
89
  * `language`/`toolbar` button variants in Button.recipe.ts, the
90
90
  * `languageText`/`toast*Bg`/`statusBarBg` semantic tokens), the shared-ui
91
- * component recipes, the react-aria condition widening, the Chakra-reset
92
- * parity `globalCss`, and the `staticCss` that keeps runtime-prop recipe
91
+ * component recipes, the react-aria condition widening, the `globalCss`
92
+ * defaults, and the `staticCss` that keeps runtime-prop recipe
93
93
  * variants generated. Used alone it renders in the OSS default look.
94
94
  *
95
95
  * ── Brand contract ──────────────────────────────────────────────────────
96
96
  * A private brand preset (a sibling repo, e.g. CreateAI) is merged AFTER this
97
97
  * one to restyle everything by overriding just these token *values* (never
98
98
  * their names — see the CSS-var contract in the README):
99
- * - colours: the `brand` and `brand2` ramps (OSS defaults: Chakra
100
- * blue / Chakra's unmodified gray). Other ramps a brand tweaks
101
- * (teal/purple/pink/…) already exist in the Chakra scales below.
99
+ * - colours: the `brand` and `brand2` ramps (OSS defaults: the blue
100
+ * ramp / a legacy slate gray). Other ramps a brand tweaks
101
+ * (teal/purple/pink/…) already exist in the base scales below.
102
102
  * - font: `display` (OSS default: Helvetica; e.g. GT Walsheim privately).
103
103
  * The recipes and semantic tokens here reference those, so a brand swap needs
104
104
  * no recipe changes. With no private preset, these OSS defaults stand.
@@ -126,8 +126,8 @@ export const basePreset = definePreset({
126
126
  },
127
127
  },
128
128
  // Toast enter/exit, played on the view-transition snapshots (see the
129
- // ::view-transition rules in globalCss). Chakra-ballpark timings: fade
130
- // + short slide in, quicker fade + shrink out.
129
+ // ::view-transition rules in globalCss): fade + short slide in,
130
+ // quicker fade + shrink out.
131
131
  toastSlideIn: {
132
132
  from: { opacity: 0, transform: "translateY(-24px)" },
133
133
  },
@@ -140,9 +140,10 @@ export const basePreset = definePreset({
140
140
  ...colors,
141
141
  gray,
142
142
  // OSS default brand ramps (see the brand contract above). `brand`
143
- // aliases Chakra blue; `brand2` stays Chakra's slate gray a frozen
144
- // legacy alias, deliberately decoupled from the neutral `gray` above
145
- // so ml-trainer's OSS look and `statusBarBg`'s default don't move.
143
+ // aliases the blue ramp; `brand2` is a frozen legacy alias of the
144
+ // slate gray in base-tokens, deliberately decoupled from the neutral
145
+ // `gray` above so ml-trainer's OSS look and `statusBarBg`'s default
146
+ // don't move.
146
147
  // Removing the slot is a follow-up needing an ml-trainer lockstep.
147
148
  brand: colors.blue,
148
149
  brand2: colors.gray,
@@ -165,7 +166,7 @@ export const basePreset = definePreset({
165
166
  },
166
167
  shadows: {
167
168
  ...shadows,
168
- // Chakra's outline shadow widened to 4px, plus dark/light-surface
169
+ // The 4px focus outline shadow, plus dark/light-surface
169
170
  // companions. Consumed via the `focusShadow` utility.
170
171
  outline: { value: "0 0 0 4px rgba(66, 153, 225, 0.6)" },
171
172
  outlineDark: { value: "0 0 0 4px rgba(0, 0, 0, 0.5)" },
@@ -174,7 +175,7 @@ export const basePreset = definePreset({
174
175
  fonts: {
175
176
  // Helvetica heading/body (4/4 apps); a brand preset leaves these and
176
177
  // overrides only `display` (the marketing font — see the brand
177
- // contract above). `mono` is Chakra's default stack.
178
+ // contract above).
178
179
  heading: { value: "Helvetica, Arial, sans-serif" },
179
180
  body: { value: "Helvetica, Arial, sans-serif" },
180
181
  mono: {
@@ -195,7 +196,7 @@ export const basePreset = definePreset({
195
196
  controlCheckedBg: { value: "{colors.brand.500}" },
196
197
  controlCheckedHoverBg: { value: "{colors.brand.600}" },
197
198
  focusBorder: { value: "{colors.brand.500}" },
198
- // Error/destructive ramp (Chakra red). Destructive button variants,
199
+ // Error/destructive ramp. Destructive button variants,
199
200
  // field error states and the error toast; the record* button
200
201
  // variants deliberately stay on red.* (recording vocabulary, not
201
202
  // danger).
@@ -211,9 +212,6 @@ export const basePreset = definePreset({
211
212
  // (CreateAI privately to brand.600 with no hover change,
212
213
  // python-editor to brand.500/600 — the default). Semantic tokens so
213
214
  // the recipe stays shared and a brand preset overrides only values.
214
- // (Was brand2.* — the grey ml-trainer OSS Chakra look — but both
215
- // apps' final values sit on their primary brand, so the default
216
- // follows; OSS language buttons are brand blue.)
217
215
  languageText: { value: "{colors.brand.500}" },
218
216
  languageTextHover: { value: "{colors.brand.600}" },
219
217
  // The `label`/`subtitle` heading variants' colour (page-title chrome).
@@ -243,8 +241,8 @@ export const basePreset = definePreset({
243
241
  secondaryActiveBorder: { value: "{colors.brand.700}" },
244
242
  secondaryActiveBg: { value: "{colors.brand.50}" },
245
243
  },
246
- // Toast status colours: the Chakra-era toast Alert restyle (teal for
247
- // every status except error) shared across the app family.
244
+ // Toast status colours (teal for every status except error), shared
245
+ // across the app family.
248
246
  toastInfoBg: { value: "{colors.teal.800}" },
249
247
  toastSuccessBg: { value: "{colors.teal.800}" },
250
248
  toastWarningBg: { value: "{colors.teal.800}" },
@@ -280,13 +278,10 @@ export const basePreset = definePreset({
280
278
  toast,
281
279
  },
282
280
  },
283
- // What ChakraProvider used to inject and Panda's preflight doesn't cover:
284
- // the theme's styles.global (body text/background defaults, global
285
- // border/placeholder colours) plus the parts of Chakra's CSS reset that
286
- // Panda's has no equivalent for kerning/text-rendering (their absence
287
- // shifts glyphs page-wide), word-wrap and touch-action. Token references
288
- // resolve against the merged preset stack, so the values track any brand
289
- // overrides exactly as they did under Chakra's runtime theme.
281
+ // Global defaults Panda's preflight doesn't cover: body text/background,
282
+ // placeholder colour, kerning/text-rendering (their absence shifts
283
+ // glyphs page-wide) and touch-action. Token references resolve against
284
+ // the merged preset stack, so the values track any brand overrides.
290
285
  globalCss: {
291
286
  html: {
292
287
  textRendering: "optimizeLegibility",
@@ -306,20 +301,20 @@ export const basePreset = definePreset({
306
301
  "*::placeholder": {
307
302
  color: "gray.500",
308
303
  },
309
- // The `* { border-color; word-wrap }` Chakra-reset parity lives in
310
- // ../reset.css, imported into the `reset` layer by consumers'
311
- // layers.css — NOT here: globalCss emits into the `base` layer, which
312
- // the legacy-Safari cascade-layer flattening specificity-boosts above
313
- // runtime-injected CSS (CodeMirror themes) and other app CSS files.
314
- // Resets must stay at the bottom (playbook gotcha #28).
315
- // Panda's preflight, unlike Chakra's reset, doesn't set the pointer
316
- // cursor on buttons. Recipes' disabled states (cursor: not-allowed)
317
- // override this from the higher recipes layer.
304
+ // The `* { border-color; word-wrap }` defaults live in ../reset.css,
305
+ // imported into the `reset` layer by consumers' layers.css — NOT here:
306
+ // globalCss emits into the `base` layer, which the legacy-Safari
307
+ // cascade-layer flattening specificity-boosts above runtime-injected
308
+ // CSS (CodeMirror themes) and other app CSS files. Resets must stay in
309
+ // the bottom layer.
310
+ // Panda's preflight doesn't set the pointer cursor on buttons.
311
+ // Recipes' disabled states (cursor: not-allowed) override this from
312
+ // the higher recipes layer.
318
313
  "button, [role='button']": {
319
314
  cursor: "pointer",
320
315
  },
321
- // Panda's preflight balance-wraps headings; Chakra didn't, and balanced
322
- // multi-line headings break at different points (mobile/translations).
316
+ // Panda's preflight balance-wraps headings; balanced multi-line
317
+ // headings break at different points (mobile/translations), so undo it.
323
318
  "h1, h2, h3, h4, h5, h6": {
324
319
  textWrap: "wrap",
325
320
  },
@@ -336,8 +331,8 @@ export const basePreset = definePreset({
336
331
  },
337
332
  // Toast enter/exit (the ToastQueue wraps updates in
338
333
  // document.startViewTransition — see Toast.tsx, which also stamps the
339
- // scoping class on <html> while its transitions run). Timings sit in
340
- // Chakra's ballpark: 0.4s fade+slide in, 0.2s fade+shrink out; the
334
+ // scoping class on <html> while its transitions run). Timings: 0.4s
335
+ // fade+slide in, 0.2s fade+shrink out; the
341
336
  // stack reflow comes from the default group animation. `(*)` +
342
337
  // `:only-child` matches exactly the entering/exiting toast groups: the
343
338
  // root snapshot always has both old and new children, and toasts are
@@ -365,8 +360,8 @@ export const basePreset = definePreset({
365
360
  // can silently lose runtime-prop variants.
366
361
  staticCss: {
367
362
  recipes: {
368
- // Size is passed responsively at call sites ported from Chakra's
369
- // `size={["md", "lg"]}`, so generate the breakpoint-prefixed variants
363
+ // Size is passed responsively at call sites
364
+ // (`size={["md", "lg"]}`), so generate the breakpoint-prefixed variants
370
365
  // too — otherwise the class lands on the element with no rule behind it
371
366
  // and the button silently falls back to the base size.
372
367
  avatar: ["*"],
@@ -410,8 +405,8 @@ export const basePreset = definePreset({
410
405
  },
411
406
  },
412
407
  },
413
- // Widen the interaction conditions so the Chakra-shaped recipe/style objects
414
- // (`_hover`/`_active`/`_focusVisible`/`_disabled`) also respond to
408
+ // Widen the interaction conditions so recipe/style objects written with
409
+ // `_hover`/`_active`/`_focusVisible`/`_disabled` also respond to
415
410
  // react-aria-components' data attributes, not just native pseudo-classes.
416
411
  conditions: {
417
412
  extend: {
@@ -5,9 +5,8 @@
5
5
  */
6
6
  import { cva } from "styled-system/css";
7
7
 
8
- // Chakra's ButtonIcon: keeps the glyph centred and spaced from the label
9
- // (iconSpacing 0.5rem). Shared by Button and LinkButton; deliberately not
10
- // exported from the package index.
8
+ // Keeps the glyph centred and spaced 0.5rem from the label. Shared by Button
9
+ // and LinkButton; deliberately not exported from the package index.
11
10
  export const buttonIcon = cva({
12
11
  base: {
13
12
  display: "inline-flex",
@@ -11,11 +11,10 @@ const toTokens = (values: Record<string, string>) =>
11
11
  ) as Record<string, { value: string }>;
12
12
 
13
13
  /**
14
- * The numeric spacing/size grid, Chakra's 0.25rem step × 0.88.
14
+ * The numeric spacing/size grid, the base 0.25rem step × 0.88.
15
15
  *
16
16
  * Only the numeric scale is touched: the named `sizes` (`xs`…`8xl`, `max`,
17
- * `full`, `container.*`) stay at their base-preset values, as they did in
18
- * both apps' Chakra themes.
17
+ * `full`, `container.*`) stay at their base-preset values.
19
18
  */
20
19
  const scale = toTokens({
21
20
  px: "1px",
@@ -81,11 +80,11 @@ const denseFontSizes = toTokens({
81
80
  * ```
82
81
  *
83
82
  * Both python-editor and classroom shipped the same "make everything
84
- * smaller" Chakra theme change (2022): the numeric spacing/sizes grid at
85
- * × 0.88 and `fontSizes` from `md` up at × 0.9. The two themes' values were
83
+ * smaller" theme change (2022): the numeric spacing/sizes grid at
84
+ * × 0.88 and `fontSizes` from `md` up at × 0.9. The two apps' values were
86
85
  * byte-identical, so the scale lives here rather than being replicated in
87
- * each app preset (migration-playbook gotcha #25 — a global scale override
88
- * hides from every safeguard, so it needs to be explicit and shared).
86
+ * each app preset — a global scale override hides from every safeguard,
87
+ * so it needs to be explicit and shared.
89
88
  *
90
89
  * Whether this density stays or the family aligns on one scale is an open
91
90
  * design question; when it is answered, this preset is the single place the
@@ -31,10 +31,10 @@ const activeBreakpoint = (): Breakpoint => {
31
31
  };
32
32
 
33
33
  /**
34
- * JS-side responsive value resolver, replacing Chakra's `useBreakpointValue`.
35
- * Panda handles responsive *styles* in CSS; this is for responsive *logic*
36
- * (choosing a prop value, branching behaviour). Resolves to the value at the
37
- * active breakpoint, falling back to the nearest smaller one that is defined.
34
+ * JS-side responsive value resolver. Panda handles responsive *styles* in
35
+ * CSS; this is for responsive *logic* (choosing a prop value, branching
36
+ * behaviour). Resolves to the value at the active breakpoint, falling back to
37
+ * the nearest smaller one that is defined.
38
38
  */
39
39
  export function useBreakpointValue<T>(
40
40
  values: Partial<Record<Breakpoint, T>>,
@@ -7,7 +7,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
7
7
 
8
8
  /**
9
9
  * Copy a value to the clipboard with a transient `hasCopied` flag for
10
- * "Copied!" feedback. Replaces Chakra's `useClipboard`.
10
+ * "Copied!" feedback.
11
11
  */
12
12
  export function useClipboard(
13
13
  value: string,
@@ -34,11 +34,10 @@ export function useClipboard(
34
34
  }
35
35
 
36
36
  /**
37
- * Chakra's useClipboard wrapped the execCommand-based copy-to-clipboard
38
- * package, which works on a user gesture in contexts the async API refuses:
39
- * insecure (non-localhost http) origins, where `navigator.clipboard` is
40
- * undefined, and frames without a clipboard-write permissions policy, where
41
- * `writeText` rejects.
37
+ * execCommand-based fallback copy. Works on a user gesture in contexts the
38
+ * async API refuses: insecure (non-localhost http) origins, where
39
+ * `navigator.clipboard` is undefined, and frames without a clipboard-write
40
+ * permissions policy, where `writeText` rejects.
42
41
  */
43
42
  function execCommandCopy(value: string): boolean {
44
43
  const active = document.activeElement;
@@ -13,12 +13,11 @@ export interface Disclosure {
13
13
  }
14
14
 
15
15
  /**
16
- * useDisclosure — Chakra's hook of the same name: the open/closed state of a
17
- * dialog, menu or drawer, and the three functions that change it.
16
+ * useDisclosure — the open/closed state of a dialog, menu or drawer, and the
17
+ * three functions that change it.
18
18
  *
19
- * A thin `useState` wrapper, kept because it is the shape a Chakra app's
20
- * dialog call sites are written in, and because a stable object means a
21
- * disclosure can be passed to a memoised child without re-rendering it.
19
+ * A thin `useState` wrapper; the stable object means a disclosure can be
20
+ * passed to a memoised child without re-rendering it.
22
21
  */
23
22
  export const useDisclosure = (defaultIsOpen = false): Disclosure => {
24
23
  const [isOpen, setIsOpen] = useState(defaultIsOpen);
@@ -6,10 +6,9 @@
6
6
  import { useCallback, useSyncExternalStore } from "react";
7
7
 
8
8
  /**
9
- * Tracks a raw CSS media query, replacing Chakra's `useMediaQuery` for
10
- * queries that aren't breakpoint-based (custom widths, height-based
11
- * queries). For the preset's breakpoint scale prefer `useBreakpointValue`.
12
- * Returns false during SSR.
9
+ * Tracks a raw CSS media query, for queries that aren't breakpoint-based
10
+ * (custom widths, height-based queries). For the preset's breakpoint scale
11
+ * prefer `useBreakpointValue`. Returns false during SSR.
13
12
  */
14
13
  export function useMediaQuery(query: string): boolean {
15
14
  const subscribe = useCallback(
@@ -5,10 +5,7 @@
5
5
  */
6
6
  import { useEffect, useRef } from "react";
7
7
 
8
- /**
9
- * The value from the previous render (undefined on the first render).
10
- * Replaces Chakra's `usePrevious`.
11
- */
8
+ /** The value from the previous render (undefined on the first render). */
12
9
  export function usePrevious<T>(value: T): T | undefined {
13
10
  const ref = useRef<T>();
14
11
  useEffect(() => {
package/src/index.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
6
  /**
7
- * shared-ui — react-aria-components + Panda CSS primitives replacing Chakra,
8
- * designed to be extracted into a library shared across sibling apps. Visuals
9
- * match the Chakra theme; behaviour follows react-aria patterns.
7
+ * shared-ui — react-aria-components + Panda CSS primitives shared across the
8
+ * micro:bit app family. Behaviour follows react-aria patterns; styling comes
9
+ * from the recipe/token system in the base preset.
10
10
  */
11
11
  export * from "./system";
12
12
  export * from "./Avatar";
@@ -58,6 +58,7 @@ export * from "./Modal";
58
58
  export * from "./PopoverArrow";
59
59
  export * from "./SharedUIProvider";
60
60
  export * from "./Tooltip";
61
+ export * from "./TooltipButton";
61
62
  export * from "./Toast";
62
63
  export * from "./VisuallyHidden";
63
64
  export { useBreakpointValue } from "./hooks/useBreakpointValue";
package/src/system.ts CHANGED
@@ -22,13 +22,13 @@ export type {
22
22
  GridProps,
23
23
  } from "styled-system/jsx";
24
24
 
25
- // Layout patterns — the Panda-native equivalents of Chakra's Box/Flex/Stack/etc.
25
+ // Layout patterns — Box/Flex/Stack/etc.
26
26
  //
27
27
  // `styled` is re-exported for the `styled(Component)` form, which works from
28
28
  // anywhere. The `styled.tag` JSX form does NOT: Panda recognises the factory by
29
29
  // the module it was imported from, so `<styled.table css={…}>` on a `styled`
30
30
  // imported from here silently produces no CSS. Import it from
31
- // "styled-system/jsx" for that (playbook gotcha #41).
31
+ // "styled-system/jsx" for that.
32
32
  export {
33
33
  AspectRatio,
34
34
  Box,