@microbit/ui 0.1.0-alpha.3
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 +21 -0
- package/README.md +118 -0
- package/lang/ui.ca.json +22 -0
- package/lang/ui.en-us.json +22 -0
- package/lang/ui.en.json +22 -0
- package/lang/ui.es-es.json +22 -0
- package/lang/ui.fr.json +22 -0
- package/lang/ui.ja.json +22 -0
- package/lang/ui.ko.json +22 -0
- package/lang/ui.lol.json +22 -0
- package/lang/ui.nl.json +22 -0
- package/lang/ui.pl.json +22 -0
- package/lang/ui.pt-br.json +22 -0
- package/lang/ui.zh-tw.json +22 -0
- package/package.json +54 -0
- package/src/Button.recipe.ts +162 -0
- package/src/Button.tsx +84 -0
- package/src/ButtonGroup.tsx +63 -0
- package/src/Card.recipe.ts +49 -0
- package/src/Card.tsx +56 -0
- package/src/Checkbox.recipe.ts +71 -0
- package/src/Checkbox.tsx +66 -0
- package/src/CloseButton.tsx +87 -0
- package/src/CloseIcon.tsx +40 -0
- package/src/Divider.tsx +21 -0
- package/src/Drawer.recipe.ts +98 -0
- package/src/Drawer.tsx +138 -0
- package/src/Heading.recipe.ts +52 -0
- package/src/Heading.tsx +14 -0
- package/src/Icon.tsx +55 -0
- package/src/IconButton.tsx +39 -0
- package/src/Image.tsx +11 -0
- package/src/Input.recipe.ts +63 -0
- package/src/Input.tsx +33 -0
- package/src/InputGroup.tsx +48 -0
- package/src/Link.tsx +23 -0
- package/src/LinkBox.tsx +88 -0
- package/src/List.tsx +27 -0
- package/src/Menu.recipe.ts +88 -0
- package/src/Menu.tsx +172 -0
- package/src/Modal.recipe.ts +163 -0
- package/src/Modal.tsx +265 -0
- package/src/NativeSelect.tsx +76 -0
- package/src/PopoverArrow.tsx +52 -0
- package/src/ProgressBar.tsx +61 -0
- package/src/SharedUIProvider.tsx +55 -0
- package/src/Slide.tsx +54 -0
- package/src/Slider.recipe.ts +91 -0
- package/src/Slider.tsx +99 -0
- package/src/Spinner.tsx +69 -0
- package/src/Svg.tsx +23 -0
- package/src/Switch.recipe.ts +80 -0
- package/src/Switch.tsx +60 -0
- package/src/Text.tsx +12 -0
- package/src/TextField.recipe.ts +54 -0
- package/src/TextField.tsx +72 -0
- package/src/Toast.recipe.ts +98 -0
- package/src/Toast.tsx +165 -0
- package/src/Tooltip.tsx +91 -0
- package/src/UnmountCallback.tsx +18 -0
- package/src/VisuallyHidden.tsx +14 -0
- package/src/base-preset.ts +278 -0
- package/src/chakra-tokens.ts +1014 -0
- package/src/hooks/useBreakpointValue.ts +63 -0
- package/src/index.ts +45 -0
- package/src/messages.ts +17 -0
- package/src/system.ts +36 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Micro:bit Educational Foundation and contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @microbit/ui
|
|
2
|
+
|
|
3
|
+
react-aria-components + Panda CSS primitives with a design language ported from
|
|
4
|
+
the Micro:bit Educational Foundation apps' original Chakra UI v2 themes.
|
|
5
|
+
|
|
6
|
+
The package **ships as source**: components import `styled-system/*`, which
|
|
7
|
+
each consumer generates with its own Panda preset stack. There is no build
|
|
8
|
+
step and no CSS shipped — the consumer's codegen produces exactly the styles
|
|
9
|
+
its tree uses.
|
|
10
|
+
|
|
11
|
+
## App-side installation
|
|
12
|
+
|
|
13
|
+
This package's own Storybook (`.storybook/` + `panda.config.ts`) is a
|
|
14
|
+
worked example of the setup below, minus the app/brand presets. Everything
|
|
15
|
+
an app must do:
|
|
16
|
+
|
|
17
|
+
1. **Panda preset stack** (`panda.config.ts`): `@pandacss/preset-base`, then
|
|
18
|
+
the **base preset** (`@microbit/ui/base-preset` — the complete micro:bit
|
|
19
|
+
design system , then optionally the app's own preset, then optionally a
|
|
20
|
+
**private brand preset** (these are used for Foundation colours, licensed
|
|
21
|
+
fonts).
|
|
22
|
+
|
|
23
|
+
Later presets override earlier ones token-by-token — the base recipes and
|
|
24
|
+
semantic tokens reference the brand tokens, which is how a brand swap
|
|
25
|
+
restyles everything without touching recipes. Set `eject: true` (the stack
|
|
26
|
+
supplies the full token system). After changing an _external_ preset
|
|
27
|
+
dependency, regenerate clean: `rm -rf styled-system styled-system.css &&
|
|
28
|
+
npm run panda` — incremental codegen does not detect external preset
|
|
29
|
+
changes.
|
|
30
|
+
|
|
31
|
+
2. **Include this package's source** in `panda.config.ts` so Panda extracts
|
|
32
|
+
the styles the components use:
|
|
33
|
+
```ts
|
|
34
|
+
include: [
|
|
35
|
+
"./src/**/*.{ts,tsx}",
|
|
36
|
+
"./node_modules/@microbit/ui/src/**/*.{ts,tsx}",
|
|
37
|
+
],
|
|
38
|
+
```
|
|
39
|
+
3. **Resolve `styled-system/*` onto the generated output** for all
|
|
40
|
+
importers, this package's source included — a `styled-system` alias in
|
|
41
|
+
both `tsconfig.json` `paths` and the bundler config (see the
|
|
42
|
+
`viteFinal` in `.storybook/main.ts`).
|
|
43
|
+
4. **Cascade layers** (`src/layers.css`, imported first): declares the
|
|
44
|
+
document-wide layer order including the `vendor` layer for third-party
|
|
45
|
+
stylesheets — import any vendor CSS with `@import "..." layer(vendor)`
|
|
46
|
+
so it beats the preflight but loses to app styling.
|
|
47
|
+
5. **react-intl**: an `IntlProvider` above any shared-ui usage. English
|
|
48
|
+
works with no setup (components carry inline `defaultMessage`); for
|
|
49
|
+
other locales compile this package's `lang/ui.<locale>.json` into the
|
|
50
|
+
app's per-locale catalogs as part of the app's formatjs compile step,
|
|
51
|
+
e.g. `formatjs compile lang/ui.fr.json
|
|
52
|
+
node_modules/@microbit/ui/lang/ui.fr.json --ast --out-file ...` (multiple
|
|
53
|
+
input files merge; ids are `ui.`-namespaced so they can't collide). This
|
|
54
|
+
keeps the strings in the app's lazily loaded locale chunks rather than
|
|
55
|
+
an eagerly bundled catalog-of-all-locales.
|
|
56
|
+
6. **`ToastProvider`** once near the root, inside the `IntlProvider`.
|
|
57
|
+
7. Optionally **`SharedUIProvider`** with an overlay-close registrar so the
|
|
58
|
+
app can dismiss open menus from outside the tree (e.g. the Android
|
|
59
|
+
hardware back button). Apps without one can omit the provider.
|
|
60
|
+
|
|
61
|
+
## The CSS-variable contract
|
|
62
|
+
|
|
63
|
+
Panda emits every token as a CSS custom property with its default naming —
|
|
64
|
+
`{category}-{path}` with dots become dashes, camelCase becomes kebab-case:
|
|
65
|
+
|
|
66
|
+
- `colors.brand.500` → `var(--colors-brand-500)`
|
|
67
|
+
- `colors.statusBarBg` → `var(--colors-status-bar-bg)`
|
|
68
|
+
- `fonts.display` → `var(--fonts-display)`
|
|
69
|
+
|
|
70
|
+
These names are **API** for styling that lives outside React/Panda — e.g.
|
|
71
|
+
CodeMirror highlight styles or xterm themes written as raw CSS. Two rules
|
|
72
|
+
keep them stable:
|
|
73
|
+
|
|
74
|
+
- Never set `hashing` or `prefix` in `panda.config.ts`.
|
|
75
|
+
- Brand/app presets may change token _values_, never token _names_.
|
|
76
|
+
|
|
77
|
+
Semantic tokens (`languageText`, `statusBarBg`, `danger.*`, `toast*Bg`,
|
|
78
|
+
`controlCheckedBg`, `focusBorder`, …) are the extension points brand presets
|
|
79
|
+
override; they resolve through var indirection, so overrides apply wherever
|
|
80
|
+
the token is consumed.
|
|
81
|
+
|
|
82
|
+
## Runtime token lookups
|
|
83
|
+
|
|
84
|
+
For values that feed _computation_ rather than stylesheets (canvas painting,
|
|
85
|
+
colour math, inline `style` for data-driven values — see gotcha #9 in
|
|
86
|
+
RAC-MIGRATION.md), import the runtime lookup:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { token } from "@microbit/ui"; // re-exports styled-system/tokens
|
|
90
|
+
|
|
91
|
+
token("colors.brand.500"); // "#007dbc" — raw value, safe for colour math
|
|
92
|
+
token("colors.statusBarBg"); // "var(--colors-brand2-500)" — CSS contexts only
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Base tokens resolve to raw values; **semantic tokens resolve to `var()`
|
|
96
|
+
references**, which are only meaningful where the browser interprets CSS.
|
|
97
|
+
For computation, look up the base token the semantic one points at, or read
|
|
98
|
+
the computed style. `token.var("colors.x.y")` returns the variable reference
|
|
99
|
+
form explicitly.
|
|
100
|
+
|
|
101
|
+
## Strings
|
|
102
|
+
|
|
103
|
+
Components never hardcode user-facing text. The few strings this package
|
|
104
|
+
needs internally (close-button labels, toast status announcements) are
|
|
105
|
+
react-intl messages with ids in the `ui.` namespace; everything else is
|
|
106
|
+
passed in by the caller as already-localized content.
|
|
107
|
+
|
|
108
|
+
The `lang/ui.<locale>.json` files (formatjs extracted format) are the source
|
|
109
|
+
of truth and are shipped as-is (exported at `./lang/*`); consuming apps
|
|
110
|
+
compile them into their own per-locale catalogs (see the consumption setup
|
|
111
|
+
above). Components also carry the English text inline as `defaultMessage`,
|
|
112
|
+
so an app that compiles no catalogs still renders English.
|
|
113
|
+
|
|
114
|
+
`en` is hand-edited; `en-US` is maintained manually. Other locales come from
|
|
115
|
+
Crowdin via the repo-root `npm run update-translations -- <path to extracted
|
|
116
|
+
Crowdin ZIP>` (config-driven over packages in
|
|
117
|
+
`bin/update-translations.cjs`), after which you run `npm run i18n:tidy`
|
|
118
|
+
from the root.
|
package/lang/ui.ca.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Tanca ",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Close",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.en.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Close",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Cerrar",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.fr.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Fermer",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.ja.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "閉じる",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.ko.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "닫기",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.lol.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "crwdns362700:0crwdne362700:0",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.nl.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Afsluiten",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/lang/ui.pl.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Zamknij",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "Fechar",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ui.close-action": {
|
|
3
|
+
"defaultMessage": "關閉",
|
|
4
|
+
"description": "Close button text or label"
|
|
5
|
+
},
|
|
6
|
+
"ui.toast-status-error": {
|
|
7
|
+
"defaultMessage": "Error",
|
|
8
|
+
"description": "Announced by screen readers before an error notification"
|
|
9
|
+
},
|
|
10
|
+
"ui.toast-status-info": {
|
|
11
|
+
"defaultMessage": "Information",
|
|
12
|
+
"description": "Announced by screen readers before an informational notification"
|
|
13
|
+
},
|
|
14
|
+
"ui.toast-status-success": {
|
|
15
|
+
"defaultMessage": "Success",
|
|
16
|
+
"description": "Announced by screen readers before a success notification"
|
|
17
|
+
},
|
|
18
|
+
"ui.toast-status-warning": {
|
|
19
|
+
"defaultMessage": "Warning",
|
|
20
|
+
"description": "Announced by screen readers before a warning notification"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@microbit/ui",
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
|
+
"description": "micro:bit design-system primitives: react-aria-components + Panda CSS with a Chakra v2 design language. Ships as source; see README for the consumption setup.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.ts",
|
|
9
|
+
"./base-preset": "./src/base-preset.ts",
|
|
10
|
+
"./chakra-tokens": "./src/chakra-tokens.ts",
|
|
11
|
+
"./messages": "./src/messages.ts",
|
|
12
|
+
"./lang/*": "./lang/*"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src",
|
|
16
|
+
"lang",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE.md"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"scripts": {
|
|
22
|
+
"panda": "panda codegen && panda cssgen --outfile styled-system.css",
|
|
23
|
+
"typecheck": "npm run panda && tsc --noEmit",
|
|
24
|
+
"prestorybook": "npm run panda",
|
|
25
|
+
"storybook": "storybook dev -p 6006 --no-open",
|
|
26
|
+
"prebuild-storybook": "npm run panda",
|
|
27
|
+
"build-storybook": "storybook build"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@pandacss/dev": "^1.11.4",
|
|
31
|
+
"react": "^18.3.1",
|
|
32
|
+
"react-aria-components": "^1.19.0",
|
|
33
|
+
"react-icons": "^4.12.0 || ^5.0.0",
|
|
34
|
+
"react-intl": "^6.6.8 || ^7.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@pandacss/dev": "^1.11.4",
|
|
38
|
+
"@storybook/react-vite": "^10.5.2",
|
|
39
|
+
"@types/react": "^18.3.3",
|
|
40
|
+
"@types/react-dom": "^18.3.0",
|
|
41
|
+
"@vitejs/plugin-react": "^4.5.2",
|
|
42
|
+
"react": "^18.3.1",
|
|
43
|
+
"react-aria-components": "^1.19.0",
|
|
44
|
+
"react-dom": "^18.3.1",
|
|
45
|
+
"react-icons": "^4.12.0",
|
|
46
|
+
"react-intl": "^6.6.8",
|
|
47
|
+
"storybook": "^10.5.2",
|
|
48
|
+
"typescript": "^5.4.2",
|
|
49
|
+
"vite": "^6.3.5"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"tag": "alpha"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (c) 2026, Micro:bit Educational Foundation and contributors
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { defineRecipe } from "@pandacss/dev";
|
|
7
|
+
|
|
8
|
+
// Chakra's transition.property.common, inlined (Panda has no transitionProperty
|
|
9
|
+
// token category). Matches Chakra's Button base transition.
|
|
10
|
+
const transitionCommon =
|
|
11
|
+
"background-color, border-color, color, fill, stroke, opacity, box-shadow, transform";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Button recipe — Chakra's default Button base + sizes, with this app's
|
|
15
|
+
* borderRadius (`button` = 2rem) and variant set ported from
|
|
16
|
+
* `components/button.ts`. Interaction conditions (`_hover`/`_active`/
|
|
17
|
+
* `_disabled`/`_focusVisible`) are widened in the preset to also match
|
|
18
|
+
* react-aria-components' data attributes, so these Chakra-shaped variant
|
|
19
|
+
* objects work unchanged on RAC's <Button>.
|
|
20
|
+
*
|
|
21
|
+
* A config recipe (not a component cva): styles land in the `recipes` layer so
|
|
22
|
+
* call sites can override with plain style props, and presets extend the
|
|
23
|
+
* variants. This file holds the brand-independent variant set — the core
|
|
24
|
+
* Chakra variants plus the family-wide `language`/`toolbar` variants; a
|
|
25
|
+
* consuming app's preset extends it with app vocabulary (e.g. ml-trainer's
|
|
26
|
+
* `led`/`record*`/`secondary-disabled`). Brand divergence within a variant is
|
|
27
|
+
* token-driven (see the `languageText` semantic tokens).
|
|
28
|
+
*
|
|
29
|
+
* Registered in the base preset (base-preset.ts).
|
|
30
|
+
*/
|
|
31
|
+
export const button = defineRecipe({
|
|
32
|
+
className: "btn",
|
|
33
|
+
jsx: ["Button", "IconButton"],
|
|
34
|
+
base: {
|
|
35
|
+
lineHeight: "1.2",
|
|
36
|
+
borderRadius: "button",
|
|
37
|
+
fontWeight: "semibold",
|
|
38
|
+
transitionProperty: transitionCommon,
|
|
39
|
+
transitionDuration: "normal",
|
|
40
|
+
display: "inline-flex",
|
|
41
|
+
appearance: "none",
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "center",
|
|
44
|
+
userSelect: "none",
|
|
45
|
+
position: "relative",
|
|
46
|
+
whiteSpace: "nowrap",
|
|
47
|
+
verticalAlign: "middle",
|
|
48
|
+
outline: "none",
|
|
49
|
+
_focusVisible: {
|
|
50
|
+
focusShadow: "outline",
|
|
51
|
+
},
|
|
52
|
+
_disabled: {
|
|
53
|
+
opacity: 0.4,
|
|
54
|
+
cursor: "not-allowed",
|
|
55
|
+
boxShadow: "none",
|
|
56
|
+
},
|
|
57
|
+
_hover: {
|
|
58
|
+
_disabled: {
|
|
59
|
+
bg: "initial",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
variants: {
|
|
64
|
+
size: {
|
|
65
|
+
lg: { h: "12", minW: "12", fontSize: "lg", px: "6" },
|
|
66
|
+
md: { h: "10", minW: "10", fontSize: "md", px: "4" },
|
|
67
|
+
sm: { h: "8", minW: "8", fontSize: "sm", px: "3" },
|
|
68
|
+
xs: { h: "6", minW: "6", fontSize: "xs", px: "2" },
|
|
69
|
+
},
|
|
70
|
+
variant: {
|
|
71
|
+
// Chakra's unstyled reset + this app's border-radius removal.
|
|
72
|
+
unstyled: {
|
|
73
|
+
bg: "none",
|
|
74
|
+
color: "inherit",
|
|
75
|
+
display: "inline",
|
|
76
|
+
lineHeight: "inherit",
|
|
77
|
+
m: "0",
|
|
78
|
+
p: "0",
|
|
79
|
+
borderRadius: "unset",
|
|
80
|
+
},
|
|
81
|
+
// Chakra's link layout (no padding/height) + this app's colours.
|
|
82
|
+
link: {
|
|
83
|
+
padding: 0,
|
|
84
|
+
height: "auto",
|
|
85
|
+
lineHeight: "normal",
|
|
86
|
+
verticalAlign: "baseline",
|
|
87
|
+
borderWidth: "0",
|
|
88
|
+
color: "brand.600",
|
|
89
|
+
fontWeight: "normal",
|
|
90
|
+
bg: "transparent",
|
|
91
|
+
_hover: {
|
|
92
|
+
textDecoration: "underline",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
secondary: {
|
|
96
|
+
borderWidth: "2px",
|
|
97
|
+
borderColor: "brand.500",
|
|
98
|
+
color: "brand.700",
|
|
99
|
+
bg: "transparent",
|
|
100
|
+
_hover: { borderColor: "brand.600" },
|
|
101
|
+
_active: { bg: "brand.50", borderColor: "brand.700" },
|
|
102
|
+
},
|
|
103
|
+
ghost: {
|
|
104
|
+
color: "black",
|
|
105
|
+
bg: "transparent",
|
|
106
|
+
_hover: { bg: "blackAlpha.50" },
|
|
107
|
+
_active: { bg: "blackAlpha.100" },
|
|
108
|
+
},
|
|
109
|
+
// Chakra had no `plain` variant, so `variant="plain"` fell through to
|
|
110
|
+
// base-only styling: a transparent, colour-inheriting button. Used for the
|
|
111
|
+
// action-bar icon-button menu triggers (settings/help), which supply their
|
|
112
|
+
// own colour and shape via instance styles.
|
|
113
|
+
plain: {
|
|
114
|
+
bg: "transparent",
|
|
115
|
+
color: "inherit",
|
|
116
|
+
},
|
|
117
|
+
primary: {
|
|
118
|
+
color: "white",
|
|
119
|
+
bg: "brand.500",
|
|
120
|
+
_hover: { bg: "brand.600", _disabled: { bg: "brand.500" } },
|
|
121
|
+
_active: { bg: "brand.700" },
|
|
122
|
+
},
|
|
123
|
+
warning: {
|
|
124
|
+
borderWidth: "2px",
|
|
125
|
+
borderColor: "danger.500",
|
|
126
|
+
color: "danger.500",
|
|
127
|
+
bg: "transparent",
|
|
128
|
+
_hover: { borderColor: "danger.600" },
|
|
129
|
+
_active: { bg: "danger.50", borderColor: "danger.500" },
|
|
130
|
+
},
|
|
131
|
+
// Chakra's built-in solid + red colorScheme (destructive confirm
|
|
132
|
+
// buttons). Same values as `record` today, but a separate variant so
|
|
133
|
+
// recording UI and destructive actions can diverge - hence danger
|
|
134
|
+
// tokens here, red.* literals there.
|
|
135
|
+
warningSolid: {
|
|
136
|
+
color: "white",
|
|
137
|
+
bg: "danger.500",
|
|
138
|
+
_hover: { bg: "danger.600", _disabled: { bg: "danger.500" } },
|
|
139
|
+
_active: { bg: "danger.700" },
|
|
140
|
+
},
|
|
141
|
+
// Family-wide variants (every censused app has language- and
|
|
142
|
+
// toolbar-class buttons).
|
|
143
|
+
toolbar: {
|
|
144
|
+
color: "black",
|
|
145
|
+
bg: "white",
|
|
146
|
+
_hover: { bg: "whiteAlpha.900", _disabled: { bg: "white" } },
|
|
147
|
+
_active: { bg: "whiteAlpha.800" },
|
|
148
|
+
_focusVisible: { focusShadow: "outlineDark" },
|
|
149
|
+
},
|
|
150
|
+
language: {
|
|
151
|
+
borderWidth: "2px",
|
|
152
|
+
borderColor: "gray.200",
|
|
153
|
+
color: "languageText",
|
|
154
|
+
_hover: { color: "languageTextHover", bg: "gray.100" },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
defaultVariants: {
|
|
159
|
+
variant: "secondary",
|
|
160
|
+
size: "md",
|
|
161
|
+
},
|
|
162
|
+
});
|