@microbit/ui 0.1.0-alpha.22 → 0.1.0-alpha.24
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.
- package/LICENSE.md +5 -5
- package/README.md +40 -13
- package/lang/ui.ca.json +12 -12
- package/lang/ui.cy.json +4 -4
- package/lang/ui.de.json +6 -6
- package/lang/ui.es-es.json +5 -5
- package/lang/ui.fr.json +6 -6
- package/lang/ui.ga-ie.json +6 -6
- package/lang/ui.it.json +4 -4
- package/lang/ui.ja.json +7 -7
- package/lang/ui.ko.json +6 -6
- package/lang/ui.lo.json +58 -0
- package/lang/ui.nl.json +9 -9
- package/lang/ui.pl.json +8 -8
- package/lang/ui.pt-br.json +7 -7
- package/lang/ui.vi.json +58 -0
- package/lang/ui.zh-cn.json +6 -6
- package/lang/ui.zh-tw.json +7 -7
- package/package.json +1 -1
- package/src/Avatar.recipe.ts +16 -20
- package/src/Avatar.tsx +31 -29
- package/src/Breadcrumb.recipe.ts +3 -7
- package/src/Breadcrumb.tsx +6 -8
- package/src/Button.recipe.ts +22 -33
- package/src/Button.tsx +10 -12
- package/src/ButtonGroup.tsx +10 -9
- package/src/Card.recipe.ts +1 -2
- package/src/Card.tsx +2 -1
- package/src/Checkbox.recipe.ts +7 -9
- package/src/Checkbox.tsx +2 -3
- package/src/CheckboxGroup.tsx +5 -7
- package/src/CloseButton.tsx +2 -2
- package/src/CloseIcon.tsx +6 -4
- package/src/Code.tsx +1 -1
- package/src/Collapse.tsx +13 -14
- package/src/Divider.tsx +3 -3
- package/src/Drawer.recipe.ts +4 -5
- package/src/Drawer.tsx +3 -4
- package/src/Fade.tsx +6 -10
- package/src/Field.recipe.ts +9 -12
- package/src/Field.tsx +16 -18
- package/src/GridList.recipe.ts +1 -2
- package/src/Heading.recipe.ts +5 -5
- package/src/Heading.tsx +3 -3
- package/src/Icon.tsx +7 -11
- package/src/IconButton.tsx +1 -1
- package/src/Image.tsx +1 -1
- package/src/Input.recipe.ts +5 -6
- package/src/Input.tsx +4 -4
- package/src/InputGroup.tsx +4 -5
- package/src/Kbd.tsx +1 -1
- package/src/Link.tsx +2 -2
- package/src/LinkBox.tsx +2 -3
- package/src/LinkButton.tsx +4 -4
- package/src/List.tsx +5 -7
- package/src/Menu.recipe.ts +15 -16
- package/src/Menu.tsx +9 -13
- package/src/Modal.recipe.ts +7 -8
- package/src/Modal.tsx +19 -24
- package/src/NativeSelect.tsx +16 -16
- package/src/NumberField.recipe.ts +8 -10
- package/src/NumberField.tsx +4 -4
- package/src/PopoverArrow.tsx +1 -2
- package/src/ProgressBar.tsx +2 -3
- package/src/Radio.recipe.ts +8 -9
- package/src/Radio.tsx +2 -2
- package/src/RadioGroup.tsx +4 -5
- package/src/Select.recipe.ts +9 -9
- package/src/Select.tsx +8 -9
- package/src/Skeleton.tsx +13 -15
- package/src/Slide.tsx +2 -2
- package/src/Slider.recipe.ts +11 -14
- package/src/Slider.tsx +3 -7
- package/src/Spinner.tsx +6 -9
- package/src/Svg.tsx +2 -3
- package/src/Switch.recipe.ts +4 -5
- package/src/Switch.tsx +3 -4
- package/src/Text.recipe.ts +4 -7
- package/src/Text.tsx +2 -2
- package/src/TextField.tsx +3 -4
- package/src/Toast.recipe.ts +43 -11
- package/src/Toast.tsx +29 -28
- package/src/Tooltip.recipe.ts +4 -9
- package/src/Tooltip.tsx +9 -11
- package/src/TooltipButton.tsx +1 -2
- package/src/UnmountCallback.tsx +2 -2
- package/src/VisuallyHidden.tsx +1 -1
- package/src/base-preset.ts +40 -44
- package/src/button-icon.ts +2 -3
- package/src/dense-preset.ts +6 -7
- package/src/hooks/useBreakpointValue.ts +4 -4
- package/src/hooks/useClipboard.ts +5 -6
- package/src/hooks/useDisclosure.ts +4 -5
- package/src/hooks/useMediaQuery.ts +3 -4
- package/src/hooks/usePrevious.ts +1 -4
- package/src/index.ts +3 -3
- package/src/system.ts +2 -2
package/src/Toast.tsx
CHANGED
|
@@ -23,7 +23,6 @@ import { toast as toastRecipe } from "styled-system/recipes";
|
|
|
23
23
|
import { CloseIcon } from "./CloseIcon";
|
|
24
24
|
import { Icon } from "./Icon";
|
|
25
25
|
import { uiMessage } from "./messages";
|
|
26
|
-
import { VisuallyHidden } from "./VisuallyHidden";
|
|
27
26
|
|
|
28
27
|
export type ToastStatus = "info" | "success" | "warning" | "error";
|
|
29
28
|
|
|
@@ -84,11 +83,11 @@ export const toastQueue = new RACToastQueue<ToastContent>({
|
|
|
84
83
|
// call onClose, so closeAll empties both.
|
|
85
84
|
const keysById = new Map<string, string>();
|
|
86
85
|
|
|
87
|
-
// Status icon
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
86
|
+
// Status icon (filled glyphs, coloured by the toast foreground = white
|
|
87
|
+
// here). Warning is a triangle, error a circle — the glyph must distinguish
|
|
88
|
+
// them because the colours alone don't reliably. The glyph is also what
|
|
89
|
+
// carries the status for assistive tech, via its accessible name (see
|
|
90
|
+
// ToastProvider).
|
|
92
91
|
const statusIcon: Record<ToastStatus, IconType> = {
|
|
93
92
|
info: RiInformationFill,
|
|
94
93
|
success: RiCheckboxCircleFill,
|
|
@@ -131,21 +130,24 @@ export const ToastProvider = () => {
|
|
|
131
130
|
// group and lets old/new pair up across the transition.
|
|
132
131
|
style={{ viewTransitionName: toast.key }}
|
|
133
132
|
>
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
<RACToastContent className={slots.content}>
|
|
134
|
+
<Icon
|
|
135
|
+
as={statusIcon[status]}
|
|
136
|
+
className={slots.icon}
|
|
137
|
+
aria-label={intl.formatMessage(
|
|
138
|
+
uiMessage(`ui.toast-status-${status}`),
|
|
139
|
+
)}
|
|
140
|
+
/>
|
|
141
|
+
<div className={slots.body}>
|
|
142
|
+
{toast.content.title && (
|
|
143
|
+
<p className={slots.title}>{toast.content.title}</p>
|
|
144
|
+
)}
|
|
145
|
+
{toast.content.description && (
|
|
146
|
+
<div className={slots.description}>
|
|
147
|
+
{toast.content.description}
|
|
148
|
+
</div>
|
|
149
|
+
)}
|
|
150
|
+
</div>
|
|
149
151
|
</RACToastContent>
|
|
150
152
|
{toast.content.isClosable && (
|
|
151
153
|
<RACButton
|
|
@@ -181,19 +183,18 @@ export interface ToastFn {
|
|
|
181
183
|
*/
|
|
182
184
|
isActive(id: string): boolean;
|
|
183
185
|
/**
|
|
184
|
-
* Replace a queued toast's content
|
|
185
|
-
*
|
|
186
|
-
* takes its place at the front of the queue.
|
|
186
|
+
* Replace a queued toast's content. The toast is re-added: it re-animates,
|
|
187
|
+
* restarts any timeout, and takes its place at the front of the queue.
|
|
187
188
|
*/
|
|
188
189
|
update(id: string, options: ToastOptions): void;
|
|
189
|
-
/** Dismiss every toast, queued as well as displayed
|
|
190
|
+
/** Dismiss every toast, queued as well as displayed. */
|
|
190
191
|
closeAll(): void;
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
/**
|
|
194
|
-
* useToast — imperative toast trigger
|
|
195
|
-
*
|
|
196
|
-
*
|
|
195
|
+
* useToast — imperative toast trigger:
|
|
196
|
+
* `toast({ title, description, status, duration })`. There is no
|
|
197
|
+
* `duration: null`; use `persistent: true` instead.
|
|
197
198
|
*/
|
|
198
199
|
export const useToast = (): ToastFn =>
|
|
199
200
|
useMemo(() => {
|
package/src/Tooltip.recipe.ts
CHANGED
|
@@ -6,17 +6,12 @@
|
|
|
6
6
|
import { defineRecipe } from "@pandacss/dev";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Tooltip recipe —
|
|
9
|
+
* Tooltip recipe — the dark tooltip.
|
|
10
10
|
*
|
|
11
11
|
* A recipe rather than styles inside the component because tooltip typography
|
|
12
|
-
* is the kind of thing an app sets once for all of them
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* The colour, vertical padding and radius are Chakra's exactly. They had
|
|
17
|
-
* drifted (white, `py: 1`, `borderRadius: md`) while this lived inside the
|
|
18
|
-
* component, which classroom's port measured: a 6px radius where Chakra drew
|
|
19
|
-
* 2px. ml-trainer and python-editor pick the correction up too.
|
|
12
|
+
* is the kind of thing an app sets once for all of them (classroom does,
|
|
13
|
+
* `fontSize: md`), and a `css` override at today's call sites would quietly
|
|
14
|
+
* not apply to tomorrow's.
|
|
20
15
|
*
|
|
21
16
|
* Registered in the base preset (base-preset.ts).
|
|
22
17
|
*/
|
package/src/Tooltip.tsx
CHANGED
|
@@ -12,9 +12,9 @@ import { PopoverArrow } from "./PopoverArrow";
|
|
|
12
12
|
|
|
13
13
|
export interface TooltipProps {
|
|
14
14
|
/**
|
|
15
|
-
* Tooltip body
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Tooltip body. Not named `content`: Panda extracts utility-named props
|
|
16
|
+
* with literal values from any JSX component, so a `content` prop taking a
|
|
17
|
+
* string would emit a broken CSS `content` rule.
|
|
18
18
|
*/
|
|
19
19
|
label: ReactNode;
|
|
20
20
|
/** A single focusable trigger element (e.g. a Button). */
|
|
@@ -60,10 +60,8 @@ export interface TooltipProps {
|
|
|
60
60
|
*
|
|
61
61
|
* This is what makes a tooltip hoverable, as WCAG 1.4.13 asks: react-aria
|
|
62
62
|
* puts hover handlers on the tooltip that re-open it, but with an immediate
|
|
63
|
-
* close it has unmounted before the pointer can cross the gap.
|
|
64
|
-
*
|
|
65
|
-
* reach for it is not worth the parity. Pass 0 where the delay is wrong for a
|
|
66
|
-
* particular control.
|
|
63
|
+
* close it has unmounted before the pointer can cross the gap. Pass 0 where
|
|
64
|
+
* the delay is wrong for a particular control.
|
|
67
65
|
*/
|
|
68
66
|
closeDelay?: number;
|
|
69
67
|
/**
|
|
@@ -79,10 +77,10 @@ export interface TooltipProps {
|
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
/**
|
|
82
|
-
* Tooltip — react-aria-components TooltipTrigger + Tooltip
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
80
|
+
* Tooltip — react-aria-components TooltipTrigger + Tooltip in the dark
|
|
81
|
+
* tooltip style. The child must be a focusable element so the tooltip is
|
|
82
|
+
* reachable by keyboard (RAC requirement), unless `triggerRef` provides the
|
|
83
|
+
* anchor and the caller manages open state and keyboard access itself.
|
|
86
84
|
*/
|
|
87
85
|
export const Tooltip = ({
|
|
88
86
|
label,
|
package/src/TooltipButton.tsx
CHANGED
|
@@ -94,8 +94,7 @@ export interface TooltipButtonProps {
|
|
|
94
94
|
* (`ContextualHelp`), not a tooltip, which would remove the hidden copy of the
|
|
95
95
|
* body and the pointer-geometry keep-alive below rather than work around them.
|
|
96
96
|
* Tracked as microbit-foundation/ui#63, which would deprecate this component;
|
|
97
|
-
*
|
|
98
|
-
* before extending it.
|
|
97
|
+
* prefer that direction over extending it.
|
|
99
98
|
*/
|
|
100
99
|
export const TooltipButton = ({
|
|
101
100
|
label,
|
package/src/UnmountCallback.tsx
CHANGED
|
@@ -7,8 +7,8 @@ import { useEffect, useRef } from "react";
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Runs its callback when unmounted. RAC keeps an overlay tree mounted until
|
|
10
|
-
* the exit transition finishes, so mounting this inside
|
|
11
|
-
*
|
|
10
|
+
* the exit transition finishes, so mounting this inside the overlay
|
|
11
|
+
* implements Modal/Drawer's `onCloseComplete`. Internal to shared-ui.
|
|
12
12
|
*/
|
|
13
13
|
export const UnmountCallback = ({ callback }: { callback?: () => void }) => {
|
|
14
14
|
const ref = useRef(callback);
|
package/src/VisuallyHidden.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import { styled } from "styled-system/jsx";
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* VisuallyHidden — screen-reader-only content (Panda's `srOnly` utility).
|
|
10
|
-
* Renders a span
|
|
10
|
+
* Renders a span; use `as="div"` for block children.
|
|
11
11
|
*/
|
|
12
12
|
export const VisuallyHidden = styled("span", {
|
|
13
13
|
base: { srOnly: true },
|
package/src/base-preset.ts
CHANGED
|
@@ -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
|
|
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
|
|
92
|
-
*
|
|
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:
|
|
100
|
-
*
|
|
101
|
-
* (teal/purple/pink/…) already exist in the
|
|
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)
|
|
130
|
-
//
|
|
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
|
|
144
|
-
//
|
|
145
|
-
// so ml-trainer's OSS look and `statusBarBg`'s default
|
|
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
|
-
//
|
|
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).
|
|
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
|
|
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
|
|
247
|
-
//
|
|
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,20 +278,18 @@ export const basePreset = definePreset({
|
|
|
280
278
|
toast,
|
|
281
279
|
},
|
|
282
280
|
},
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
//
|
|
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",
|
|
293
288
|
touchAction: "manipulation",
|
|
294
289
|
},
|
|
295
290
|
body: {
|
|
296
|
-
position:
|
|
291
|
+
// No `position: relative` (Chakra had it): it breaks react-aria's
|
|
292
|
+
// overlay positioning — see Tooltip's "In a scrolling page" story.
|
|
297
293
|
minHeight: "100%",
|
|
298
294
|
fontFeatureSettings: '"kern"',
|
|
299
295
|
fontFamily: "body",
|
|
@@ -306,20 +302,20 @@ export const basePreset = definePreset({
|
|
|
306
302
|
"*::placeholder": {
|
|
307
303
|
color: "gray.500",
|
|
308
304
|
},
|
|
309
|
-
// The `* { border-color; word-wrap }`
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
// Panda's preflight
|
|
316
|
-
//
|
|
317
|
-
//
|
|
305
|
+
// The `* { border-color; word-wrap }` defaults live in ../reset.css,
|
|
306
|
+
// imported into the `reset` layer by consumers' layers.css — NOT here:
|
|
307
|
+
// globalCss emits into the `base` layer, which the legacy-Safari
|
|
308
|
+
// cascade-layer flattening specificity-boosts above runtime-injected
|
|
309
|
+
// CSS (CodeMirror themes) and other app CSS files. Resets must stay in
|
|
310
|
+
// the bottom layer.
|
|
311
|
+
// Panda's preflight doesn't set the pointer cursor on buttons.
|
|
312
|
+
// Recipes' disabled states (cursor: not-allowed) override this from
|
|
313
|
+
// the higher recipes layer.
|
|
318
314
|
"button, [role='button']": {
|
|
319
315
|
cursor: "pointer",
|
|
320
316
|
},
|
|
321
|
-
// Panda's preflight balance-wraps headings;
|
|
322
|
-
//
|
|
317
|
+
// Panda's preflight balance-wraps headings; balanced multi-line
|
|
318
|
+
// headings break at different points (mobile/translations), so undo it.
|
|
323
319
|
"h1, h2, h3, h4, h5, h6": {
|
|
324
320
|
textWrap: "wrap",
|
|
325
321
|
},
|
|
@@ -336,8 +332,8 @@ export const basePreset = definePreset({
|
|
|
336
332
|
},
|
|
337
333
|
// Toast enter/exit (the ToastQueue wraps updates in
|
|
338
334
|
// document.startViewTransition — see Toast.tsx, which also stamps the
|
|
339
|
-
// scoping class on <html> while its transitions run). Timings
|
|
340
|
-
//
|
|
335
|
+
// scoping class on <html> while its transitions run). Timings: 0.4s
|
|
336
|
+
// fade+slide in, 0.2s fade+shrink out; the
|
|
341
337
|
// stack reflow comes from the default group animation. `(*)` +
|
|
342
338
|
// `:only-child` matches exactly the entering/exiting toast groups: the
|
|
343
339
|
// root snapshot always has both old and new children, and toasts are
|
|
@@ -365,8 +361,8 @@ export const basePreset = definePreset({
|
|
|
365
361
|
// can silently lose runtime-prop variants.
|
|
366
362
|
staticCss: {
|
|
367
363
|
recipes: {
|
|
368
|
-
// Size is passed responsively at call sites
|
|
369
|
-
// `size={["md", "lg"]}
|
|
364
|
+
// Size is passed responsively at call sites
|
|
365
|
+
// (`size={["md", "lg"]}`), so generate the breakpoint-prefixed variants
|
|
370
366
|
// too — otherwise the class lands on the element with no rule behind it
|
|
371
367
|
// and the button silently falls back to the base size.
|
|
372
368
|
avatar: ["*"],
|
|
@@ -410,8 +406,8 @@ export const basePreset = definePreset({
|
|
|
410
406
|
},
|
|
411
407
|
},
|
|
412
408
|
},
|
|
413
|
-
// Widen the interaction conditions so
|
|
414
|
-
//
|
|
409
|
+
// Widen the interaction conditions so recipe/style objects written with
|
|
410
|
+
// `_hover`/`_active`/`_focusVisible`/`_disabled` also respond to
|
|
415
411
|
// react-aria-components' data attributes, not just native pseudo-classes.
|
|
416
412
|
conditions: {
|
|
417
413
|
extend: {
|
package/src/button-icon.ts
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { cva } from "styled-system/css";
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
//
|
|
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",
|
package/src/dense-preset.ts
CHANGED
|
@@ -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,
|
|
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
|
|
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"
|
|
85
|
-
* × 0.88 and `fontSizes` from `md` up at × 0.9. The two
|
|
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
|
|
88
|
-
*
|
|
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
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
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.
|
|
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
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
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 —
|
|
17
|
-
*
|
|
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
|
|
20
|
-
*
|
|
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,
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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(
|
package/src/hooks/usePrevious.ts
CHANGED
|
@@ -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
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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";
|
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 —
|
|
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
|
|
31
|
+
// "styled-system/jsx" for that.
|
|
32
32
|
export {
|
|
33
33
|
AspectRatio,
|
|
34
34
|
Box,
|