@a4ui/core 0.3.1 â 0.4.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 +20 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1000 -711
- package/dist/layout/ThemedScenery.d.ts +20 -0
- package/dist/styles.css +70 -11
- package/dist/themes/index.d.ts +34 -0
- package/dist/themes/palettes.d.ts +42 -0
- package/package.json +4 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
2
|
+
/** Props for {@link ThemedScenery}. */
|
|
3
|
+
export interface ThemedSceneryProps {
|
|
4
|
+
/** Emoji/text glyphs scattered and gently floating across the backdrop. */
|
|
5
|
+
motifs: string[];
|
|
6
|
+
/** How many glyphs to render. @default 16 */
|
|
7
|
+
count?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A lightweight, theme-tinted backdrop for non-`space` themes: the same
|
|
11
|
+
* token-driven nebula as {@link SpaceBackground} plus slowly floating motif
|
|
12
|
+
* glyphs you pass in. Mount it as {@link AppShell}'s `background` (fixed z-0
|
|
13
|
+
* layer behind all content). Motion is skipped under `motionReduced()`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <AppShell background={<ThemedScenery motifs={['ðĶ', 'ðŋ', 'ðĶī']} />}>âĶ</AppShell>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function ThemedScenery(props: ThemedSceneryProps): JSX.Element;
|
package/dist/styles.css
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
--accent: 199 89% 55%;
|
|
24
24
|
--accent-foreground: 0 0% 100%;
|
|
25
25
|
--ring: 217 91% 52%;
|
|
26
|
-
--destructive: 0 72%
|
|
26
|
+
--destructive: 0 72% 52%;
|
|
27
27
|
--destructive-foreground: 0 0% 100%;
|
|
28
28
|
|
|
29
29
|
/* Semantic data colors (financial direction) â constant across themes. */
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
--accent: 199 89% 48%;
|
|
60
60
|
--accent-foreground: 0 0% 100%;
|
|
61
61
|
--ring: 217 91% 52%;
|
|
62
|
-
--destructive: 0 72%
|
|
62
|
+
--destructive: 0 72% 50%;
|
|
63
63
|
--destructive-foreground: 0 0% 100%;
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -227,21 +227,25 @@ body {
|
|
|
227
227
|
overflow: hidden;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
/* Nebula tinted from the active theme (--primary / --accent / --destructive), so
|
|
231
|
+
switching palettes recolors the whole backdrop. Space's tokens keep it blue. */
|
|
230
232
|
#space .sky {
|
|
231
233
|
position: absolute;
|
|
232
234
|
inset: 0;
|
|
233
235
|
background:
|
|
234
|
-
radial-gradient(1200px 700px at 82% -8%, hsl(
|
|
235
|
-
radial-gradient(900px 600px at 8% 12%, hsl(
|
|
236
|
-
radial-gradient(1000px 800px at 50% 120%, hsl(
|
|
237
|
-
radial-gradient(700px 500px at 30% 55%, hsl(
|
|
236
|
+
radial-gradient(1200px 700px at 82% -8%, hsl(var(--primary) / 0.34), transparent 60%),
|
|
237
|
+
radial-gradient(900px 600px at 8% 12%, hsl(var(--accent) / 0.28), transparent 60%),
|
|
238
|
+
radial-gradient(1000px 800px at 50% 120%, hsl(var(--accent) / 0.22), transparent 55%),
|
|
239
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.12), transparent 60%),
|
|
240
|
+
hsl(var(--background));
|
|
238
241
|
}
|
|
239
242
|
[data-theme='light'] #space .sky {
|
|
240
243
|
background:
|
|
241
|
-
radial-gradient(1100px 680px at 84% -10%, hsl(
|
|
242
|
-
radial-gradient(900px 600px at 6% 8%, hsl(
|
|
243
|
-
radial-gradient(1000px 820px at 50% 120%, hsl(
|
|
244
|
-
radial-gradient(700px 500px at 30% 55%, hsl(
|
|
244
|
+
radial-gradient(1100px 680px at 84% -10%, hsl(var(--primary) / 0.22), transparent 60%),
|
|
245
|
+
radial-gradient(900px 600px at 6% 8%, hsl(var(--accent) / 0.2), transparent 60%),
|
|
246
|
+
radial-gradient(1000px 820px at 50% 120%, hsl(var(--accent) / 0.16), transparent 55%),
|
|
247
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.1), transparent 60%),
|
|
248
|
+
hsl(var(--background));
|
|
245
249
|
}
|
|
246
250
|
@keyframes nebulaShift {
|
|
247
251
|
0%,
|
|
@@ -260,7 +264,12 @@ body {
|
|
|
260
264
|
left: -10%;
|
|
261
265
|
right: -10%;
|
|
262
266
|
height: 46%;
|
|
263
|
-
background: linear-gradient(
|
|
267
|
+
background: linear-gradient(
|
|
268
|
+
180deg,
|
|
269
|
+
hsl(var(--accent) / 0.16),
|
|
270
|
+
hsl(var(--primary) / 0.1) 45%,
|
|
271
|
+
transparent 80%
|
|
272
|
+
);
|
|
264
273
|
filter: blur(40px);
|
|
265
274
|
opacity: 0.55;
|
|
266
275
|
mix-blend-mode: screen;
|
|
@@ -552,3 +561,53 @@ body {
|
|
|
552
561
|
display: none;
|
|
553
562
|
}
|
|
554
563
|
}
|
|
564
|
+
|
|
565
|
+
/* ---- Generic themed scenery (non-space themes) --------------------------
|
|
566
|
+
A themed nebula (same token-tinted gradients as the starfield) plus a field
|
|
567
|
+
of slowly floating motif glyphs â <ThemedScenery motifs={[...]} />. Lighter
|
|
568
|
+
than the bespoke SpaceBackground so every extra theme costs almost nothing. */
|
|
569
|
+
#scenery {
|
|
570
|
+
position: fixed;
|
|
571
|
+
inset: 0;
|
|
572
|
+
z-index: 0;
|
|
573
|
+
pointer-events: none;
|
|
574
|
+
overflow: hidden;
|
|
575
|
+
}
|
|
576
|
+
#scenery .themed-sky {
|
|
577
|
+
position: absolute;
|
|
578
|
+
inset: 0;
|
|
579
|
+
background:
|
|
580
|
+
radial-gradient(1200px 700px at 82% -8%, hsl(var(--primary) / 0.34), transparent 60%),
|
|
581
|
+
radial-gradient(900px 600px at 8% 12%, hsl(var(--accent) / 0.28), transparent 60%),
|
|
582
|
+
radial-gradient(1000px 800px at 50% 120%, hsl(var(--accent) / 0.22), transparent 55%),
|
|
583
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.12), transparent 60%),
|
|
584
|
+
hsl(var(--background));
|
|
585
|
+
}
|
|
586
|
+
[data-theme='light'] #scenery .themed-sky {
|
|
587
|
+
background:
|
|
588
|
+
radial-gradient(1100px 680px at 84% -10%, hsl(var(--primary) / 0.22), transparent 60%),
|
|
589
|
+
radial-gradient(900px 600px at 6% 8%, hsl(var(--accent) / 0.2), transparent 60%),
|
|
590
|
+
radial-gradient(1000px 820px at 50% 120%, hsl(var(--accent) / 0.16), transparent 55%),
|
|
591
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.1), transparent 60%),
|
|
592
|
+
hsl(var(--background));
|
|
593
|
+
}
|
|
594
|
+
#scenery .motif {
|
|
595
|
+
position: absolute;
|
|
596
|
+
user-select: none;
|
|
597
|
+
will-change: transform;
|
|
598
|
+
animation: motifFloat var(--dur, 9s) ease-in-out var(--delay, 0s) infinite;
|
|
599
|
+
}
|
|
600
|
+
@keyframes motifFloat {
|
|
601
|
+
0%,
|
|
602
|
+
100% {
|
|
603
|
+
transform: translateY(0) rotate(var(--r, 0deg));
|
|
604
|
+
}
|
|
605
|
+
50% {
|
|
606
|
+
transform: translateY(-16px) rotate(calc(var(--r, 0deg) + 5deg));
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
@media (prefers-reduced-motion: reduce) {
|
|
610
|
+
html:not(.force-motion) #scenery .motif {
|
|
611
|
+
animation: none !important;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Palette, ThemeDefinition } from './palettes';
|
|
2
|
+
export type { Palette, ThemeDefinition } from './palettes';
|
|
3
|
+
export { themes, space, dino, doctor, scientist, soccer, TOKEN_ORDER } from './palettes';
|
|
4
|
+
/**
|
|
5
|
+
* Render a theme to the CSS you'd paste into your own stylesheet: a `:root`
|
|
6
|
+
* block (dark) plus a `:root[data-theme='light']` block. Same output the docs
|
|
7
|
+
* Theme Builder exports.
|
|
8
|
+
*/
|
|
9
|
+
export declare function themeToCss(theme: ThemeDefinition): string;
|
|
10
|
+
/** Render a theme's tokens to a `{ dark, light }` JSON object. */
|
|
11
|
+
export declare function themeToJson(theme: ThemeDefinition): {
|
|
12
|
+
dark: Palette;
|
|
13
|
+
light: Palette;
|
|
14
|
+
};
|
|
15
|
+
declare const activeTheme: import('solid-js').Accessor<ThemeDefinition>;
|
|
16
|
+
/** Reactive accessor for the currently applied theme. */
|
|
17
|
+
export { activeTheme };
|
|
18
|
+
/**
|
|
19
|
+
* Apply a theme's palette globally by injecting/replacing the
|
|
20
|
+
* `<style id="a4ui-theme">` element. No-op during SSR. Does not persist or update
|
|
21
|
+
* the reactive signal â use {@link selectTheme} for the full, persisted version.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyThemeDefinition(theme: ThemeDefinition): void;
|
|
24
|
+
/**
|
|
25
|
+
* Select the active theme by definition or name: applies it, updates the
|
|
26
|
+
* reactive {@link activeTheme} signal, and persists the choice to localStorage.
|
|
27
|
+
* Unknown names are ignored.
|
|
28
|
+
*/
|
|
29
|
+
export declare function selectTheme(theme: ThemeDefinition | string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Restore the persisted theme (or fall back to Space) and apply it. Call once at
|
|
32
|
+
* startup. No-op during SSR.
|
|
33
|
+
*/
|
|
34
|
+
export declare function initTheme(): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** The 15 recolorable tokens, each an "H S% L%" channel string. */
|
|
2
|
+
export interface Palette {
|
|
3
|
+
background: string;
|
|
4
|
+
foreground: string;
|
|
5
|
+
card: string;
|
|
6
|
+
'card-foreground': string;
|
|
7
|
+
muted: string;
|
|
8
|
+
'muted-foreground': string;
|
|
9
|
+
border: string;
|
|
10
|
+
input: string;
|
|
11
|
+
primary: string;
|
|
12
|
+
'primary-foreground': string;
|
|
13
|
+
accent: string;
|
|
14
|
+
'accent-foreground': string;
|
|
15
|
+
ring: string;
|
|
16
|
+
destructive: string;
|
|
17
|
+
'destructive-foreground': string;
|
|
18
|
+
}
|
|
19
|
+
/** A named theme: a label plus a dark and a light palette. */
|
|
20
|
+
export interface ThemeDefinition {
|
|
21
|
+
/** URL/storage-safe slug, e.g. `space`. */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Human label for the picker, e.g. `Space`. */
|
|
24
|
+
label: string;
|
|
25
|
+
/** One-line flavour text. */
|
|
26
|
+
description: string;
|
|
27
|
+
/** Emoji shown in the theme picker. */
|
|
28
|
+
icon: string;
|
|
29
|
+
dark: Palette;
|
|
30
|
+
light: Palette;
|
|
31
|
+
/** Motif glyphs for the generic `ThemedScenery` backdrop. Omit for themes that
|
|
32
|
+
ship their own bespoke scenery (e.g. `space` uses `SpaceBackground`). */
|
|
33
|
+
motifs?: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare const TOKEN_ORDER: (keyof Palette)[];
|
|
36
|
+
export declare const space: ThemeDefinition;
|
|
37
|
+
export declare const dino: ThemeDefinition;
|
|
38
|
+
export declare const doctor: ThemeDefinition;
|
|
39
|
+
export declare const scientist: ThemeDefinition;
|
|
40
|
+
export declare const soccer: ThemeDefinition;
|
|
41
|
+
/** All built-in themes, in picker order. Space is the default. */
|
|
42
|
+
export declare const themes: ThemeDefinition[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a4ui/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A4ui â Spatial Glass design system & component library for SolidJS (Kobalte behavior + Tailwind glass tokens + motion).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"test:unit": "vitest run",
|
|
59
59
|
"test": "playwright test",
|
|
60
60
|
"test:ui": "playwright test --ui",
|
|
61
|
+
"test:a11y": "playwright test a11y --project=desktop",
|
|
61
62
|
"test:report": "playwright show-report",
|
|
62
63
|
"prepublishOnly": "npm run build"
|
|
63
64
|
},
|
|
@@ -74,10 +75,12 @@
|
|
|
74
75
|
"tailwind-merge": "^3.6.0"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
78
|
+
"@axe-core/playwright": "^4.12.1",
|
|
77
79
|
"@eslint/js": "^9.39.5",
|
|
78
80
|
"@playwright/test": "^1.61.1",
|
|
79
81
|
"@solidjs/testing-library": "^0.8.10",
|
|
80
82
|
"@testing-library/jest-dom": "^6.9.1",
|
|
83
|
+
"axe-core": "^4.12.1",
|
|
81
84
|
"eslint": "^9.39.5",
|
|
82
85
|
"eslint-config-prettier": "^10.1.8",
|
|
83
86
|
"eslint-plugin-solid": "^0.14.5",
|