@aria-framework/theme 0.5.0 → 0.6.0
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/README.md +25 -2
- package/package.json +2 -1
- package/web/theme-init.js +38 -0
package/README.md
CHANGED
|
@@ -116,8 +116,8 @@ to a 64px icon rail. The package ships the **CSS** (in `theme.css`) and the
|
|
|
116
116
|
Notes:
|
|
117
117
|
- `data-storage-key` namespaces the persisted collapsed state per app (default
|
|
118
118
|
`aria-sidebar-collapsed`). Keep an app's historical key across migrations.
|
|
119
|
-
- To avoid a flash of the expanded rail on load,
|
|
120
|
-
|
|
119
|
+
- To avoid a flash of the expanded rail on load, load `theme-init.js` (below)
|
|
120
|
+
synchronously in `<head>` — it pre-applies the class before first paint.
|
|
121
121
|
- State classes live on `<html>`: `.sidebar-open` (mobile overlay),
|
|
122
122
|
`.sidebar-collapsed` (desktop icon rail).
|
|
123
123
|
- Sidebar tokens are themeable in `tokens.json` under `"sidebar"` (per-scheme
|
|
@@ -127,6 +127,25 @@ Notes:
|
|
|
127
127
|
scheme (e.g. a permanently-dark login hero panel), use fixed values there —
|
|
128
128
|
since 0.5.0 these tokens follow the active scheme.
|
|
129
129
|
|
|
130
|
+
## Pre-paint init (`theme-init.js`, since 0.6.0)
|
|
131
|
+
|
|
132
|
+
Resolves the color mode BEFORE first paint (no FOUC) and pre-applies the
|
|
133
|
+
collapsed-sidebar class. Load it synchronously in `<head>` — NOT `defer`red:
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<html data-theme-pref="system"> <!-- server stamps light|dark|system -->
|
|
137
|
+
<head>
|
|
138
|
+
<script src="/theme/theme-init.js" data-storage-key="myapp-sidebar-collapsed"></script>
|
|
139
|
+
...
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- `data-theme-pref="system"` resolves from the OS color scheme and live-updates
|
|
143
|
+
if the OS theme changes; `light`/`dark` are forced modes. The result lands on
|
|
144
|
+
`<html data-bs-theme="...">` (Bootstrap 5.3 convention, what `theme.css` keys on).
|
|
145
|
+
- `data-storage-key` MUST match the key given to `sidebar.js` (same default:
|
|
146
|
+
`aria-sidebar-collapsed`).
|
|
147
|
+
- CSP-safe: external + self-hosted, works under `script-src 'self'`.
|
|
148
|
+
|
|
130
149
|
## Mobile (Expo / React Native)
|
|
131
150
|
|
|
132
151
|
```tsx
|
|
@@ -179,6 +198,10 @@ Token change → edit `tokens.json`, run `npm run build`, commit the regenerated
|
|
|
179
198
|
`strong` (emphasis text, replaces hardcoded `#fff`) and `accent` (active bar /
|
|
180
199
|
icon / focus ring). Apps that used `--side-*` for deliberately-always-dark
|
|
181
200
|
surfaces must pin fixed colors instead.
|
|
201
|
+
- **v0.6.0** — added **`web/theme-init.js`**: pre-paint color-mode resolver
|
|
202
|
+
(`data-theme-pref` light/dark/system + live OS-change sync) and
|
|
203
|
+
collapsed-sidebar pre-apply, parameterized by the same `data-storage-key` as
|
|
204
|
+
`sidebar.js`. Apps can delete their local copies.
|
|
182
205
|
|
|
183
206
|
> **0.x semver reminder:** `^0.4.0` matches `<0.5.0` only — consumers pick up
|
|
184
207
|
> patches via `npm update`, but every **minor** bump (0.4 → 0.5) requires
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aria-framework/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Aria App Framework — theme module. Field Ops Console design system: tokens.json single source of record + a generator that emits a Bootstrap 5.3 web theme (theme.css + self-hosted fonts) and a React Native palette/provider/primitives. Light + dark.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"exports": {
|
|
27
27
|
"./theme.css": "./web/theme.css",
|
|
28
28
|
"./sidebar.js": "./web/sidebar.js",
|
|
29
|
+
"./theme-init.js": "./web/theme-init.js",
|
|
29
30
|
"./mobile": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
|
|
30
31
|
"./tokens": { "types": "./dist/tokens.d.ts", "default": "./dist/tokens.js" },
|
|
31
32
|
"./fonts": { "types": "./dist/fonts.d.ts", "default": "./dist/fonts.js" },
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* theme-init.js — resolve the active color mode BEFORE first paint (no FOUC).
|
|
3
|
+
*
|
|
4
|
+
* Load synchronously in <head> (NOT deferred) so it runs before the body
|
|
5
|
+
* renders. The server stamps <html data-theme-pref="light|dark|system"> from
|
|
6
|
+
* the signed-in user's saved preference and a best-guess data-bs-theme. When
|
|
7
|
+
* the preference is "system" we resolve it here from the OS color scheme and
|
|
8
|
+
* keep it in sync if the OS theme changes while the app is open. CSP-safe:
|
|
9
|
+
* external, self-hosted, no inline script.
|
|
10
|
+
*
|
|
11
|
+
* Also pre-applies the collapsed-sidebar preference so a collapsed rail does
|
|
12
|
+
* not flash open on load. The localStorage key comes from this script tag's
|
|
13
|
+
* data-storage-key attribute and MUST match the one passed to sidebar.js:
|
|
14
|
+
*
|
|
15
|
+
* <script src="/theme/theme-init.js" data-storage-key="myapp-sidebar-collapsed"></script>
|
|
16
|
+
*/
|
|
17
|
+
(function () {
|
|
18
|
+
var el = document.documentElement;
|
|
19
|
+
var script = document.currentScript;
|
|
20
|
+
var sidebarKey = (script && script.dataset && script.dataset.storageKey) || 'aria-sidebar-collapsed';
|
|
21
|
+
|
|
22
|
+
var pref = el.getAttribute('data-theme-pref') || 'system';
|
|
23
|
+
function resolve() {
|
|
24
|
+
var mode = pref === 'dark' ? 'dark'
|
|
25
|
+
: pref === 'light' ? 'light'
|
|
26
|
+
: (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
27
|
+
el.setAttribute('data-bs-theme', mode);
|
|
28
|
+
}
|
|
29
|
+
resolve();
|
|
30
|
+
if (pref === 'system' && window.matchMedia) {
|
|
31
|
+
try { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', resolve); }
|
|
32
|
+
catch (e) { /* older browsers: no live OS-change updates */ }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
if (localStorage.getItem(sidebarKey) === '1') el.classList.add('sidebar-collapsed');
|
|
37
|
+
} catch (e) { /* private mode / storage disabled */ }
|
|
38
|
+
})();
|