astryx-dracula 0.2.0 → 0.3.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/BRAND.md +30 -18
- package/README.md +22 -11
- package/USAGE.md +29 -10
- package/astryx-dracula.js +19 -13
- package/astryx-dracula.variants.d.ts +15 -0
- package/package.json +59 -17
- package/shared/auth-chrome-config.ts +18 -0
- package/shared/auth-chrome.tsx +25 -0
- package/shared/auth-copy.ts +22 -0
- package/shared/chaptered-doc-config.ts +92 -0
- package/shared/chaptered-doc.tsx +332 -0
- package/shared/chart-hues.ts +27 -0
- package/shared/chart-labels.tsx +44 -0
- package/shared/chart-legend.tsx +100 -0
- package/shared/chart-panel-style.ts +13 -0
- package/shared/data-bar.tsx +160 -0
- package/shared/gallery-image.ts +20 -0
- package/shared/login-demo.ts +7 -0
- package/shared/metric-delta.tsx +36 -0
- package/shared/order-desk.tsx +273 -0
- package/shared/revenue-chart.tsx +174 -0
- package/shared/scene-castle.tsx +322 -0
- package/shared/scene-frame.tsx +88 -0
- package/shared/scene-hues.ts +49 -0
- package/shared/scene-tile.tsx +128 -0
- package/shared/settings-data.ts +125 -0
- package/shared/settings-rows.tsx +179 -0
- package/shared/sparkline.tsx +94 -0
- package/shared/sso-icons.tsx +30 -0
- package/templates/ai-chat-landing.tsx +67 -32
- package/templates/ai-chat.tsx +41 -20
- package/templates/blank.tsx +5 -2
- package/templates/centered-hero.tsx +15 -124
- package/templates/classic-gallery.tsx +21 -65
- package/templates/contact-form.tsx +62 -40
- package/templates/dashboard-portfolio.tsx +146 -227
- package/templates/dashboard.tsx +123 -121
- package/templates/detail-page.tsx +101 -95
- package/templates/documentation-design.template.mjs +1 -1
- package/templates/documentation-design.tsx +85 -96
- package/templates/documentation-technical.template.mjs +1 -1
- package/templates/documentation-technical.tsx +33 -21
- package/templates/documentation.template.mjs +1 -1
- package/templates/documentation.tsx +54 -74
- package/templates/editor.tsx +119 -89
- package/templates/file-explorer.tsx +133 -84
- package/templates/form-two-column.tsx +62 -124
- package/templates/gallery-hero.tsx +17 -171
- package/templates/ide.tsx +27 -21
- package/templates/incident-console.tsx +105 -69
- package/templates/kanban-board.tsx +100 -41
- package/templates/library.template.mjs +2 -2
- package/templates/library.tsx +38 -41
- package/templates/login-card.tsx +59 -86
- package/templates/login-split.tsx +88 -128
- package/templates/login-sso.tsx +107 -68
- package/templates/login.tsx +108 -52
- package/templates/messaging-shell.tsx +172 -143
- package/templates/mixed-gallery.tsx +31 -130
- package/templates/payment-form.tsx +369 -289
- package/templates/product-detail.tsx +40 -57
- package/templates/product-gallery.tsx +31 -40
- package/templates/product-tour.template.mjs +6 -0
- package/templates/product-tour.tsx +916 -0
- package/templates/settings-dialog.tsx +145 -286
- package/templates/settings-sidebar.tsx +179 -267
- package/templates/settings.tsx +42 -13
- package/templates/shell-nav.tsx +32 -23
- package/templates/shell-side-nav.tsx +30 -19
- package/templates/shell-top-nav.tsx +81 -43
- package/templates/side-gallery.tsx +39 -93
- package/templates/table-grouped.tsx +63 -33
- package/templates/table-page-chart.tsx +24 -297
- package/templates/table-page-heatmap-status.tsx +157 -91
- package/templates/table-page-shoe-store-heatmap.tsx +19 -288
- package/templates/table-page.tsx +24 -6
- package/templates/table.tsx +24 -7
- package/templates/tech-report.template.mjs +6 -0
- package/templates/tech-report.tsx +1486 -0
- package/templates/theme-showcase.template.mjs +1 -1
- package/templates/theme-showcase.tsx +313 -249
- package/theme.css +76 -14
- package/tokens.css +425 -30
package/BRAND.md
CHANGED
|
@@ -8,30 +8,40 @@ Source of truth is `astryx-theme.ts`. Do not add hexes; `bun run audit` enforces
|
|
|
8
8
|
| Role | Hex | Use |
|
|
9
9
|
|---|---|---|
|
|
10
10
|
| Background | #282A36 | page bg |
|
|
11
|
-
| Current line | #6272A4 | line highlight, subtle borders (doubles as comment) |
|
|
11
|
+
| Current line | #6272A4 | line highlight, subtle borders (doubles as comment)[^current-line] |
|
|
12
12
|
| Selection | #44475A | selected rows, quiet surfaces |
|
|
13
13
|
| Background Light | #343746 | cards, surfaces |
|
|
14
14
|
| Background Lighter | #424450 | popovers, floating elements |
|
|
15
|
-
| Background Dark | #21222C | shadows |
|
|
15
|
+
| Background Dark | #21222C | shadows, on-fill text |
|
|
16
|
+
| Darker | #191A21 | shadow washes only (never a surface: `--shadow-*` alpha blends) |
|
|
16
17
|
| Foreground | #F8F8F2 | primary text on dark |
|
|
17
|
-
| Comment | #6272A4 |
|
|
18
|
+
| Comment | #6272A4 | subtle borders, empty cells, disabled text[^comment] |
|
|
18
19
|
| Cyan | #8BE9FD | info, secondary links |
|
|
19
20
|
| Green | #50FA7B | positive, success |
|
|
20
|
-
| Orange | #FFB86C |
|
|
21
|
+
| Orange | #FFB86C | attention, constants (never warning) |
|
|
21
22
|
| Pink | #FF79C6 | flair, accent |
|
|
22
23
|
| Purple | #BD93F9 | primary, links and titles unvisited |
|
|
23
24
|
| Red | #FF5555 | negative, error |
|
|
24
|
-
| Yellow | #F1FA8C | tags, chips |
|
|
25
|
+
| Yellow | #F1FA8C | tags, chips, warning states |
|
|
26
|
+
| Inverted error | #FFD5CC | pale surface for the inverted error Toast (not a spec hex) |
|
|
27
|
+
|
|
28
|
+
[^comment]: Comment sits **between** the two WCAG floors on the scene backdrop `#21222C`: 3.36:1 clears 1.4.11's **graphical** floor and fails the **text** floor, and any `fillOpacity` below 0.9 is worse (0.85 → 2.81). So Comment is correct on an empty cell or a subtle grid line and **never** on a `<text fill>`. Scene text uses `--color-text-paragraph` (7.59:1). Do not "improve" an empty cell to `--color-separator`: its ceiling on `#21222C` is 1.73:1 at full opacity and 1.32:1 at 0.55, and a grid whose empty cells have vanished is not a grid.
|
|
29
|
+
|
|
30
|
+
[^current-line]: Upstream pins both Current Line and Comment to #6272A4. This kit follows suit for line affordances, including scrollbar thumbs in `tokens.css`. Do not "correct" one of them to #44475A.
|
|
25
31
|
|
|
26
32
|
## Semantic map (glimpse)
|
|
27
33
|
|
|
28
34
|
- Purple links/titles unvisited. Visited falls back to text-base, hover goes primary + underline. Users learn purple means tappable title.
|
|
29
|
-
- Green positive and success. Red negative and error. Yellow tags and
|
|
30
|
-
- Subdue #4C5067 for
|
|
35
|
+
- Green positive and success. Red negative and error. Yellow tags, chips, and warning states (`--color-warning` ships Yellow; Orange never carries warning). Cyan info and secondary links. Pink flair. Orange attention and constants.
|
|
36
|
+
- Subdue #4C5067 for separators and hairline chrome, never text (1.8:1 on the page background, 1.5:1 on cards). Not a Dracula hex; derived from the glimpse ramp for chrome hierarchy.
|
|
37
|
+
|
|
38
|
+
## Borders
|
|
39
|
+
|
|
40
|
+
`--color-border` is Comment `#6272A4`. `--color-border-emphasized` is **`#9AA1BC`**, repinned from Comment: core tone-bumps that token to ≥3:1 for form-control boundaries, but `pin()` returns a literal so that guarantee is inert here, and the old value cleared *no* surface tier at 3:1 while the new one clears all four (5.56 / 4.60 / 3.77 / 3.57). `DropdownMenuRadioItem` reads it on a popover, so the popover tier is a real consumer. Known shortfall: the inverted surface at 2.40, which has no live consumer — recorded, not certified.
|
|
31
41
|
|
|
32
42
|
## Charts
|
|
33
43
|
|
|
34
|
-
Categorical series use nearest Dracula hues: blue goes comment, orange orange, purple purple,
|
|
44
|
+
A chart mark takes a `--color-data-*` **role token**, never a `--dracula-*` primitive, and the types enforce it — widening `ChartLegendEntry.color` and `DataBarSegment.color` from `string` to template-literal unions caught ten real violations at compile time, including eight demo bars painting `--color-success` on a data mark. Categorical series use nearest Dracula hues: blue goes comment, orange orange, purple purple (compat token only — purple means tappable, never encode data; the ban is a **module rule** enforced by `chart-hues.ts`, not token absence),
|
|
35
45
|
green green, pink pink, cyan cyan, red red. Teal uses ANSI bright cyan #A4FFFF and indigo
|
|
36
46
|
ANSI bright blue #D6ACFF; brown has no spectral match and reuses orange. Sequential ramps cover 9 families (purple, pink, red,
|
|
37
47
|
orange, yellow, teal, blue, shamrock, gray) with 5 lightness steps each (28/44/60/74/88),
|
|
@@ -39,8 +49,8 @@ constant hue and saturation per family.
|
|
|
39
49
|
|
|
40
50
|
## Code highlighting
|
|
41
51
|
|
|
42
|
-
|
|
43
|
-
pink keywords, yellow strings, comment
|
|
52
|
+
Syntax theme (`draculaSyntax` in `astryx-theme.ts`, 14 slots per the spec Token Classification):
|
|
53
|
+
pink keywords/operators/tags, yellow strings, comment-gray comments, orange numbers, green functions and attributes, cyan types, purple constants, foreground variables/properties/punctuation, Background canvas. Regexps get no split (core's tokenizer emits no regexp scope); attributes/tags follow the official Dracula editors and the core `dracula` preset, not the Support bucket's Cyan.
|
|
44
54
|
|
|
45
55
|
## Status surfaces
|
|
46
56
|
|
|
@@ -49,13 +59,14 @@ Each status scope redefines its muted token to the categorical tint
|
|
|
49
59
|
(`--color-background-<hue>`, 10% accent wash) with a semantic accent border.
|
|
50
60
|
Text on fills is always `#21222C`; spec never uses raw black. Links render accent
|
|
51
61
|
with underline and resolve to foreground on hover. Focus and interactive edges
|
|
52
|
-
use Functional Purple
|
|
62
|
+
use accent, not Functional Purple: `--color-functional-*` is pinned for spec parity
|
|
63
|
+
(token compat — never encode status in these) and no shipped component consumes it.
|
|
53
64
|
|
|
54
65
|
## Interactions
|
|
55
66
|
|
|
56
67
|
Buttons darken on hover; destructive pairs red fill with dark text. Links render accent
|
|
57
68
|
underlined and resolve to foreground on hover. Focus rings use accent, not Functional
|
|
58
|
-
Purple: 5.9 contrast beats 3.
|
|
69
|
+
Purple: 5.9 contrast beats 3.0 on dark backgrounds, verified by keyboard screenshot.
|
|
59
70
|
Inputs take accent and error rings from core; table rows lift on hover. Cards, banners,
|
|
60
71
|
badges, and progress bars are static.
|
|
61
72
|
|
|
@@ -65,13 +76,14 @@ Radii flat and crisp (5px elements, 4px inner). Everything below is a core defau
|
|
|
65
76
|
|
|
66
77
|
- Motion durations: neutral defaults (fast 175ms, medium 410ms).
|
|
67
78
|
- Spacing/size/ease scales: core defaults. Shadows, radii, and surfaces are Dracula-hued tokens above.
|
|
68
|
-
-
|
|
69
|
-
- Derived AA lifts (not spec hexes, same hues): secondary text #9AA1BC, muted text #8288A6, paragraph #B0B3C4
|
|
70
|
-
- Icon glyphs
|
|
71
|
-
- onDark:
|
|
72
|
-
- `--color-data-neutral`:
|
|
79
|
+
- One runtime dependency: `lucide-react` (icons render from it at runtime, both the theme `draculaIconRegistry` in `icons.tsx` and every template's direct imports — `bun run audit` fails when a registered glyph stops resolving to a real export). Everything else is defined here.
|
|
80
|
+
- Derived AA lifts (not spec hexes, same hues): secondary text #9AA1BC, muted text #8288A6, paragraph #B0B3C4. Subdue #4C5067 is chrome, below every text floor.
|
|
81
|
+
- Icon glyphs from Lucide in `icons.tsx` (MIT). The theme also sets icon colors (primary, secondary, disabled, accent).
|
|
82
|
+
- onDark: `--color-on-dark` is repinned to spec Foreground `#F8F8F2` — the spec has **no pure white**, so a `#FFFFFF` here is off-palette. The pair is **deliberately asymmetric** and should not be "fixed" into symmetry: on-dark = spec Foreground `#F8F8F2`, on-light = spec black `#000000`. `--color-tint-hover` is **`#FFFFFF` and ruled correct — do not repaint.** It looks like a second pure white next to the line above, and it is not: core only ever reads it as a `color-mix` **partner** at 5–20% (`CheckboxInput.tsx:115-138`, `Slider.tsx:252`), never as a paint, and it is core's own dark value (`tokens.stylex.ts:81`, `light-dark(black, white)`). Retinting it to a Dracula grey would silently change every mix core builds and break the only thing it is for. `#FFFFFF` is not on-palette; the *token* is.
|
|
83
|
+
- `--color-data-neutral`: `#8C939B`, **inherited from core** (core declares `light-dark(#8494A3, #8C939B)` in `core/src/theme/domainTokens/dataTokens.ts`) and off-palette — neither a Dracula hex nor on our gray ramp, whose L60 computes to `#8A8EA8`. It stays because it reads fine on dark. The "Stone" label in an earlier line here was never an Astryx brand name: `grep -ril stone node_modules/@astryxdesign/` hits only a separate `@astryxdesign/theme-stone` package, not this value. **Open question, deliberately not answered:** the value is off-palette and we could ship a gray ramp step instead — but it is core's own default, and diverging from core on a data role buys brand purity at the cost of surprising anyone who ports a core chart. That trade is the human's.
|
|
84
|
+
- Tag accents: `--color-tag-<orange|pink|cyan|yellow|green|purple>`. The purple tag was **renamed from `blue`** — it always held `#BD93F9` (spec Purple) and never a blue. Dracula has no blue, so the value was right and the name was the lie. Historical trap for anyone who greps: `blue` is also the name of six *other* tokens that genuinely are Comment (`--color-background-blue`, `-border-`, `-icon-`, `-text-`, `--color-data-categorical-blue`, `--color-data-blue-1..5`), so a repo-wide find/replace on "blue" would silently repoint all six at Purple. A name that contradicts its own value is invisible to every contrast gate, which is why this needed a ruling rather than a threshold.
|
|
73
85
|
- No color-scale config: HCT generation would fight the pinned hexes. No light mode, ever.
|
|
74
86
|
|
|
75
87
|
## Dims
|
|
76
88
|
|
|
77
|
-
Gap 24px, viewport 16px, content 15px vertical / 16px horizontal, widget-gap 24px, tile-row 96px, radius 5px everywhere, JetBrains Mono, type scale base 14 ratio 1.2: h1 24 / h2 20 / h3
|
|
89
|
+
Gap 24px, viewport 16px, content 15px vertical / 16px horizontal, widget-gap 24px, tile-row 96px, radius 5px everywhere, JetBrains Mono, type scale base 14 ratio 1.2, generated steps 12 / 14 / 17 / 20 / 24. The pinned heading tokens are compat dims, not a strict 1.2 ladder: h1 24 / h2 20 / h3 16 / h4 14 / h5 13 / h6 12, body 14, supporting 12. Astryx `Heading` sizes come from the scale roles instead, so level 3 renders the 17px `lg` step. Outer Card padding 4, nested inset 3. Touch targets 24px floor, 44 where touch matters.
|
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@ Live showcase: https://yuzu-octopus.github.io/astryx-dracula/
|
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- Prebuilt CSS
|
|
13
|
+
- Dracula tokens pinned in `astryx-theme.ts` (`grep -c "pin(" astryx-theme.ts` pins) (191 public props in the prebuilt `theme.css`, plus 3 private `--_*-radius` aliases; `tokens.css` is a full plain-CSS mirror, `grep -c "^ --" tokens.css` vars), dark-only. No gate asserts these counts — `bun run theme:check` asserts freshness, `bun run audit` asserts palette purity and contrast.
|
|
14
|
+
- Syntax theme plus chart series and sequential ramps
|
|
15
|
+
- Prebuilt CSS plus runtime theme injection, or runtime injection alone for prototyping
|
|
16
16
|
- WCAG contrast gates enforced in CI via `bun run audit`
|
|
17
|
-
-
|
|
17
|
+
- JetBrains Mono fonts and Lucide icons, one runtime dependency (`lucide-react`)
|
|
18
18
|
- Agent skill, `llms.txt`, and copy-paste quickstart for AI-assisted adoption
|
|
19
|
-
-
|
|
19
|
+
- Around 45 themed pages in `templates/`, published as an Astryx integration pack and viewable live at `/astryx-dracula/#/templates`
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
22
22
|
|
|
@@ -27,9 +27,12 @@ bun add astryx-dracula
|
|
|
27
27
|
## Usage
|
|
28
28
|
|
|
29
29
|
```tsx
|
|
30
|
+
import '@astryxdesign/core/reset.css';
|
|
31
|
+
import '@astryxdesign/core/astryx.css';
|
|
32
|
+
import 'astryx-dracula/tokens.css';
|
|
33
|
+
import 'astryx-dracula/theme.css';
|
|
30
34
|
import { Theme } from '@astryxdesign/core/theme';
|
|
31
35
|
import { astryxDraculaTheme } from 'astryx-dracula';
|
|
32
|
-
import 'astryx-dracula/theme.css';
|
|
33
36
|
|
|
34
37
|
<Theme theme={astryxDraculaTheme} mode="dark">
|
|
35
38
|
<App />
|
|
@@ -39,18 +42,19 @@ import 'astryx-dracula/theme.css';
|
|
|
39
42
|
Copy `fonts/` from the package into your served `public/fonts/` directory.
|
|
40
43
|
|
|
41
44
|
> [!NOTE]
|
|
42
|
-
> For the plain-CSS path, migrating an existing codebase, and the full token reference, see [USAGE.md](USAGE.md) and [BRAND.md](BRAND.md). AI agents should start with the skill in `.agents/skills/astryx-dracula/SKILL.md
|
|
45
|
+
> For the plain-CSS path, migrating an existing codebase, and the full token reference, see [USAGE.md](USAGE.md) and [BRAND.md](BRAND.md). AI agents should start with the skill in `.agents/skills/astryx-dracula/SKILL.md` (agent index: [AGENTS.snippet.md](AGENTS.snippet.md)).
|
|
43
46
|
|
|
44
47
|
## Project layout
|
|
45
48
|
|
|
46
49
|
```text
|
|
47
50
|
astryx-theme.ts defineTheme source, single source of truth
|
|
48
51
|
theme.css prebuilt output of bun run theme:build
|
|
49
|
-
tokens.css plain-CSS :root
|
|
50
|
-
icons.tsx
|
|
52
|
+
tokens.css plain-CSS :root mirror for any stack
|
|
53
|
+
icons.tsx Lucide icon registry (runtime `lucide-react` dependency)
|
|
51
54
|
fonts/ JetBrains Mono woff2 files
|
|
52
|
-
templates/
|
|
53
|
-
|
|
55
|
+
templates/ around 45 themed pages plus integration specs
|
|
56
|
+
shared/ reusable modules templates compose (23 files)
|
|
57
|
+
scripts/check.ts palette, contrast, and packaging gates
|
|
54
58
|
demo/ showcase source, deployed to GitHub Pages
|
|
55
59
|
```
|
|
56
60
|
|
|
@@ -62,3 +66,10 @@ demo/ showcase source, deployed to GitHub Pages
|
|
|
62
66
|
| `bun run theme:build`| Rebuild `theme.css` from the source |
|
|
63
67
|
| `bun run theme:check`| Fail if committed theme outputs are stale |
|
|
64
68
|
| `bun run build` | Typecheck plus showcase build |
|
|
69
|
+
| `bunx react-doctor@latest` | Component health scan (currently 100/100) |
|
|
70
|
+
|
|
71
|
+
## Attribution & License
|
|
72
|
+
|
|
73
|
+
- **Astryx Design System**: Created by the Astryx team at Meta Platforms, Inc. under the [MIT License](https://github.com/facebook/astryx/blob/main/LICENSE). The template files in `templates/` (around 45) are derived from Astryx's open source page templates and adapted for the Dracula brand (pure Dracula spec retokening, recharts replaced with zero-dependency inline SVGs, heroicons mapped to Lucide, XLE/XLO structural expression headers, and responsive layout hardening).
|
|
74
|
+
- **Dracula Theme**: Color palette and specification by [Zeno Rocha and the Dracula Theme community](https://draculatheme.com).
|
|
75
|
+
- **Package & Additions**: Released under the [MIT License](LICENSE).
|
package/USAGE.md
CHANGED
|
@@ -14,7 +14,7 @@ Or clone `https://github.com/yuzu-octopus/astryx-dracula.git` and copy
|
|
|
14
14
|
|
|
15
15
|
## Prebuilt (recommended for Astryx apps)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Prebuilt CSS plus runtime theme injection (the CSS carries the paint, the `<Theme>` object carries the tokens). Built with `bun run theme:build` from `astryx-theme.ts`.
|
|
18
18
|
|
|
19
19
|
```tsx
|
|
20
20
|
import '@astryxdesign/core/reset.css';
|
|
@@ -62,7 +62,7 @@ import '../tokens.css';
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
Then use `var(--color-primary)`, `var(--dracula-purple)`, `var(--space-gap)`.
|
|
65
|
-
`tokens.css` sets real `:root` values with `color-scheme: dark`, so first paint is correct with no runtime.
|
|
65
|
+
`tokens.css` sets real `:root` values with `color-scheme: dark`, so first paint is correct with no runtime. It is a full plain-CSS mirror of the theme (`grep -c "^ --" tokens.css` `:root` vars, unlayered by design so it beats core layers with zero `!important`); edit the theme, not this file, then re-mirror.
|
|
66
66
|
|
|
67
67
|
## Migrating an existing site
|
|
68
68
|
|
|
@@ -73,7 +73,7 @@ Then use `var(--color-primary)`, `var(--dracula-purple)`, `var(--space-gap)`.
|
|
|
73
73
|
|
|
74
74
|
## Templates
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Around 45 themed pages ship in `templates/`, each with a `<id>.template.mjs` spec, published
|
|
77
77
|
as an Astryx integration pack (`astryx.integration.mjs`). List this package in your
|
|
78
78
|
`astryx.config`, then scaffold any of them:
|
|
79
79
|
|
|
@@ -81,15 +81,17 @@ as an Astryx integration pack (`astryx.integration.mjs`). List this package in y
|
|
|
81
81
|
bunx astryx template dashboard --package astryx-dracula
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
View all
|
|
85
|
-
import
|
|
84
|
+
View them all live at `/astryx-dracula/#/templates` on the showcase (agent index: [AGENTS.snippet.md](AGENTS.snippet.md)). Pack rules: templates
|
|
85
|
+
import `@astryxdesign/core`, `lucide-react`, and the kit's own shared modules (`astryx-dracula/shared/*`: auth-copy, auth-chrome-config, chaptered-doc, chaptered-doc-config, chart-hues, chart-labels, chart-panel-style, gallery-image, login-demo, metric-delta, revenue-chart, scene-castle, scene-hues, scene-tile, settings-data, settings-rows, sparkline, sso-icons), no chart libraries.
|
|
86
86
|
|
|
87
87
|
## Fonts
|
|
88
88
|
|
|
89
89
|
Copy `fonts/` to your app's served static dir (Vite: `public/fonts/`).
|
|
90
90
|
`tokens.css` declares the `@font-face` blocks; the theme sets JetBrains Mono
|
|
91
|
-
for body, heading, and code roles.
|
|
92
|
-
|
|
91
|
+
for body, heading, and code roles. The shipped URLs are base-scoped
|
|
92
|
+
(`/astryx-dracula/fonts/*.woff2`, matching this repo's demo `base`) — apps
|
|
93
|
+
served from `/` remap or self-host the files at that path, otherwise text
|
|
94
|
+
falls back to `monospace`. `bun run audit` fails when the files are missing here. Only the package root `fonts/` ships them: a subpath import resolves nothing, so a fallback after copying means the copy step missed the expected path.
|
|
93
95
|
|
|
94
96
|
## Consumer Vite config
|
|
95
97
|
|
|
@@ -97,7 +99,9 @@ No special config needed. This kit follows the glimpse path: prebuilt
|
|
|
97
99
|
`@astryxdesign/core` CSS plus `<Theme>` injection. A stock Vite React
|
|
98
100
|
config works. The only recommended extra is the CSS layer-order snippet so
|
|
99
101
|
theme overrides beat component base styles (our repo `vite.config.ts` also
|
|
100
|
-
sets a demo-only `base` path; do not copy that)
|
|
102
|
+
sets a demo-only `base` path; do not copy that). Tailwind projects keep their
|
|
103
|
+
own setup and add the snippet as a plain `<style>` tag in `index.html` — the
|
|
104
|
+
layer names are the contract, not the Vite plugin:
|
|
101
105
|
|
|
102
106
|
```ts
|
|
103
107
|
// vite.config.ts
|
|
@@ -113,7 +117,7 @@ export default defineConfig({
|
|
|
113
117
|
{
|
|
114
118
|
tag: 'style',
|
|
115
119
|
children:
|
|
116
|
-
'@layer reset,
|
|
120
|
+
'@layer reset, astryx-base, astryx-theme;',
|
|
117
121
|
injectTo: 'head-prepend',
|
|
118
122
|
},
|
|
119
123
|
];
|
|
@@ -132,7 +136,7 @@ README. Not required for this kit.
|
|
|
132
136
|
|
|
133
137
|
- Unstyled components: entry is missing `reset.css`/`astryx.css` or the import order is wrong.
|
|
134
138
|
- Monospace fallback: `fonts/` not copied to served `public/fonts/`.
|
|
135
|
-
- Wrong colors after a theme edit: rebuild with `bun run theme:build`; `bun run theme:check` confirms staleness.
|
|
139
|
+
- Wrong colors after a theme edit: rebuild with `bun run theme:build`; `bun run theme:check` confirms staleness (it ignores `astryx-dracula.js` by design — that file is a build artifact, not a freshness signal).
|
|
136
140
|
- Old `:root` `--color-*` overrides winning: delete them.
|
|
137
141
|
|
|
138
142
|
## Rules
|
|
@@ -141,3 +145,18 @@ README. Not required for this kit.
|
|
|
141
145
|
- Never override `--color-*` in app `:root`. Brand changes live in `astryx-theme.ts` via `defineTheme`, then `bun run theme:build`.
|
|
142
146
|
- Tokens for every value: `var(--color-*|--space-*|--radius-*)`. No raw hex or px in components.
|
|
143
147
|
- Component styling: props first, then theme `components` overrides in `astryx-theme.ts`. No per-app CSS wars.
|
|
148
|
+
- A chart mark takes a `--color-data-*` role token, never a `--dracula-*` primitive. The `chart-hues` / `chart-legend` / `data-bar` types reject anything else at compile time.
|
|
149
|
+
- `--dracula-comment` is legal on a **graphical** mark (3.36:1 clears WCAG 1.4.11) and illegal on **text** (fails 4.5:1). Any `fillOpacity` under 0.9 makes it worse. Text in a scene uses `--color-text-paragraph`.
|
|
150
|
+
- A `Layout height="fill"` needs `style={{height: '100dvh'}}` or it silently degrades to document scroll. `minHeight: '100%'` computes to 0 against an indefinite parent, so it is a no-op.
|
|
151
|
+
- Derive any count a page prints from its data. Hardcoded numerals are how `documentation.tsx` came to say "twenty-eight components" over 31 entries.
|
|
152
|
+
- A `.tsx` exports components only; shared data lives in a sibling `.ts`, so React Fast Refresh works.
|
|
153
|
+
|
|
154
|
+
## Release checklist
|
|
155
|
+
|
|
156
|
+
Before tagging a release:
|
|
157
|
+
|
|
158
|
+
1. Pin versions: `@astryxdesign/core` / `@astryxdesign/cli` in `package.json` match the showcase and CI.
|
|
159
|
+
2. Nothing to refresh by hand: the version badges in `templates/product-tour.tsx` + `templates/centered-hero.tsx` (rendered text *and* XLE header) are gated against `package.json` by `bun run audit`, so bump the version and the audit tells you if you missed one.
|
|
160
|
+
3. Rebuild and gate: `bun run theme:build`, then `bun run theme:check`, then `bun run audit`, then `bunx react-doctor@latest` (must stay 100/100).
|
|
161
|
+
4. Counts in the docs are cited with the command that produces them, so there is nothing to refresh by hand. If you find a bare numeral, replace it with its command.
|
|
162
|
+
5. `npm publish` runs the same four gates itself via `prepublishOnly`, so a tree that fails cannot reach the registry. There is no publish workflow in CI — publishing is deliberately a human step.
|
package/astryx-dracula.js
CHANGED
|
@@ -55,7 +55,7 @@ export const astryxDraculaTheme = {
|
|
|
55
55
|
"--text-large-weight": "var(--font-weight-semibold)",
|
|
56
56
|
"--text-large-leading": "1.4118",
|
|
57
57
|
"--text-label-size": "var(--font-size-base)",
|
|
58
|
-
"--text-label-weight": "var(--font-weight-
|
|
58
|
+
"--text-label-weight": "var(--font-weight-semibold)",
|
|
59
59
|
"--text-label-leading": "1.4286",
|
|
60
60
|
"--text-code-size": "var(--font-size-base)",
|
|
61
61
|
"--text-code-weight": "var(--font-weight-normal)",
|
|
@@ -92,16 +92,18 @@ export const astryxDraculaTheme = {
|
|
|
92
92
|
"--color-syntax-type": "#8BE9FD",
|
|
93
93
|
"--color-syntax-variable": "#F8F8F2",
|
|
94
94
|
"--color-syntax-operator": "#FF79C6",
|
|
95
|
-
"--color-syntax-constant": "#
|
|
95
|
+
"--color-syntax-constant": "#BD93F9",
|
|
96
96
|
"--color-syntax-tag": "#FF79C6",
|
|
97
|
-
"--color-syntax-attribute": "#
|
|
98
|
-
"--color-syntax-property": "#
|
|
97
|
+
"--color-syntax-attribute": "#50FA7B",
|
|
98
|
+
"--color-syntax-property": "#F8F8F2",
|
|
99
99
|
"--color-syntax-punctuation": "#F8F8F2",
|
|
100
100
|
"--color-syntax-background": "#282A36",
|
|
101
101
|
"--radius-inner": "4px",
|
|
102
102
|
"--radius-element": "5px",
|
|
103
103
|
"--radius-container": "5px",
|
|
104
104
|
"--radius-page": "5px",
|
|
105
|
+
"--radius-chat": "5px",
|
|
106
|
+
"--font-family-mono": "'JetBrains Mono', monospace",
|
|
105
107
|
"--font-size-h1": "24px",
|
|
106
108
|
"--font-size-h2": "20px",
|
|
107
109
|
"--font-size-h3": "16px",
|
|
@@ -112,12 +114,17 @@ export const astryxDraculaTheme = {
|
|
|
112
114
|
"--shadow-med": "0 2px 4px #191A210D, 0 4px 12px #191A211A",
|
|
113
115
|
"--shadow-high": "0 4px 6px #191A211A, 0 12px 24px #191A2126",
|
|
114
116
|
"--shadow-inset-hover": "inset 0px 0px 0px 2px #6272A430",
|
|
117
|
+
"--shadow-inset-selected": "inset 0px 0px 0px 2px #BD93F930",
|
|
115
118
|
"--shadow-inset-success": "inset 0px 0px 0px 2px #50FA7B30",
|
|
116
119
|
"--shadow-inset-warning": "inset 0px 0px 0px 2px #F1FA8C30",
|
|
117
120
|
"--shadow-inset-error": "inset 0px 0px 0px 2px #FF555530",
|
|
118
121
|
"--color-neutral": "light-dark(#F8F8F21A, #F8F8F21A)",
|
|
119
122
|
"--color-background-inverted": "light-dark(#F8F8F2, #F8F8F2)",
|
|
120
123
|
"--color-background-error-inverted": "light-dark(#FFD5CC, #FFD5CC)",
|
|
124
|
+
"--color-tint-hover": "light-dark(#FFFFFF, #FFFFFF)",
|
|
125
|
+
"--color-on-dark": "light-dark(#F8F8F2, #F8F8F2)",
|
|
126
|
+
"--color-on-light": "light-dark(#000000, #000000)",
|
|
127
|
+
"--color-shadow": "light-dark(#21222C, #21222C)",
|
|
121
128
|
"--color-accent-muted": "var(--color-background-purple)",
|
|
122
129
|
"--color-success-muted": "var(--color-background-green)",
|
|
123
130
|
"--color-warning-muted": "var(--color-background-yellow)",
|
|
@@ -139,7 +146,7 @@ export const astryxDraculaTheme = {
|
|
|
139
146
|
"--color-overlay-hover": "light-dark(#0000001F, #0000001F)",
|
|
140
147
|
"--color-overlay-pressed": "light-dark(#00000033, #00000033)",
|
|
141
148
|
"--color-border": "light-dark(#6272A4, #6272A4)",
|
|
142
|
-
"--color-border-emphasized": "light-dark(#
|
|
149
|
+
"--color-border-emphasized": "light-dark(#9AA1BC, #9AA1BC)",
|
|
143
150
|
"--color-accent": "light-dark(#BD93F9, #BD93F9)",
|
|
144
151
|
"--color-success": "light-dark(#50FA7B, #50FA7B)",
|
|
145
152
|
"--color-error": "light-dark(#FF5555, #FF5555)",
|
|
@@ -158,6 +165,7 @@ export const astryxDraculaTheme = {
|
|
|
158
165
|
"--color-on-warning": "light-dark(#21222C, #21222C)",
|
|
159
166
|
"--color-on-error": "light-dark(#21222C, #21222C)",
|
|
160
167
|
"--color-on-info": "light-dark(#21222C, #21222C)",
|
|
168
|
+
"--color-data-neutral": "light-dark(#8C939B, #8C939B)",
|
|
161
169
|
"--color-track": "light-dark(#6272A4, #6272A4)",
|
|
162
170
|
"--color-skeleton": "light-dark(#6272A4, #6272A4)",
|
|
163
171
|
"--color-functional-red": "light-dark(#DE5735, #DE5735)",
|
|
@@ -167,13 +175,11 @@ export const astryxDraculaTheme = {
|
|
|
167
175
|
"--color-functional-purple": "light-dark(#815CD6, #815CD6)",
|
|
168
176
|
"--color-data-categorical-blue": "light-dark(#6272A4, #6272A4)",
|
|
169
177
|
"--color-data-categorical-orange": "light-dark(#FFB86C, #FFB86C)",
|
|
170
|
-
"--color-data-categorical-purple": "light-dark(#BD93F9, #BD93F9)",
|
|
171
178
|
"--color-data-categorical-green": "light-dark(#50FA7B, #50FA7B)",
|
|
172
179
|
"--color-data-categorical-pink": "light-dark(#FF79C6, #FF79C6)",
|
|
173
180
|
"--color-data-categorical-cyan": "light-dark(#8BE9FD, #8BE9FD)",
|
|
174
181
|
"--color-data-categorical-red": "light-dark(#FF5555, #FF5555)",
|
|
175
182
|
"--color-data-categorical-teal": "light-dark(#A4FFFF, #A4FFFF)",
|
|
176
|
-
"--color-data-categorical-brown": "light-dark(#FFB86C, #FFB86C)",
|
|
177
183
|
"--color-data-categorical-indigo": "light-dark(#D6ACFF, #D6ACFF)",
|
|
178
184
|
"--color-background-blue": "light-dark(#6272A41A, #6272A41A)",
|
|
179
185
|
"--color-border-blue": "light-dark(#6272A44D, #6272A44D)",
|
|
@@ -240,11 +246,11 @@ export const astryxDraculaTheme = {
|
|
|
240
246
|
"--color-data-yellow-3": "light-dark(hsl(64.91 91.67% 60%), hsl(64.91 91.67% 60%))",
|
|
241
247
|
"--color-data-yellow-2": "light-dark(hsl(64.91 91.67% 74%), hsl(64.91 91.67% 74%))",
|
|
242
248
|
"--color-data-yellow-1": "light-dark(hsl(64.91 91.67% 88%), hsl(64.91 91.67% 88%))",
|
|
243
|
-
"--color-data-teal-5": "light-dark(hsl(
|
|
244
|
-
"--color-data-teal-4": "light-dark(hsl(
|
|
245
|
-
"--color-data-teal-3": "light-dark(hsl(
|
|
246
|
-
"--color-data-teal-2": "light-dark(hsl(
|
|
247
|
-
"--color-data-teal-1": "light-dark(hsl(
|
|
249
|
+
"--color-data-teal-5": "light-dark(hsl(180 100% 28%), hsl(180 100% 28%))",
|
|
250
|
+
"--color-data-teal-4": "light-dark(hsl(180 100% 44%), hsl(180 100% 44%))",
|
|
251
|
+
"--color-data-teal-3": "light-dark(hsl(180 100% 60%), hsl(180 100% 60%))",
|
|
252
|
+
"--color-data-teal-2": "light-dark(hsl(180 100% 74%), hsl(180 100% 74%))",
|
|
253
|
+
"--color-data-teal-1": "light-dark(hsl(180 100% 88%), hsl(180 100% 88%))",
|
|
248
254
|
"--color-data-blue-5": "light-dark(hsl(225.45 26.61% 28%), hsl(225.45 26.61% 28%))",
|
|
249
255
|
"--color-data-blue-4": "light-dark(hsl(225.45 26.61% 44%), hsl(225.45 26.61% 44%))",
|
|
250
256
|
"--color-data-blue-3": "light-dark(hsl(225.45 26.61% 60%), hsl(225.45 26.61% 60%))",
|
|
@@ -287,7 +293,7 @@ export const astryxDraculaTheme = {
|
|
|
287
293
|
"--color-tag-cyan": "light-dark(#8BE9FD, #8BE9FD)",
|
|
288
294
|
"--color-tag-yellow": "light-dark(#F1FA8C, #F1FA8C)",
|
|
289
295
|
"--color-tag-green": "light-dark(#50FA7B, #50FA7B)",
|
|
290
|
-
"--color-tag-
|
|
296
|
+
"--color-tag-purple": "light-dark(#BD93F9, #BD93F9)"
|
|
291
297
|
},
|
|
292
298
|
icons: draculaIconRegistry,
|
|
293
299
|
};
|
|
@@ -9,11 +9,26 @@
|
|
|
9
9
|
// Generated by astryx theme build
|
|
10
10
|
export {};
|
|
11
11
|
|
|
12
|
+
declare module '@astryxdesign/core/StatusDot' {
|
|
13
|
+
interface StatusDotVariantMap {
|
|
14
|
+
'info': true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
declare module '@astryxdesign/core/ProgressBar' {
|
|
13
19
|
interface ProgressBarVariantMap {
|
|
14
20
|
'accent': true;
|
|
15
21
|
'success': true;
|
|
16
22
|
'warning': true;
|
|
17
23
|
'error': true;
|
|
24
|
+
'neutral': true;
|
|
25
|
+
'disabled': true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare module '@astryxdesign/core/Avatar' {
|
|
30
|
+
interface AvatarStatusDotVariantMap {
|
|
31
|
+
'success': true;
|
|
32
|
+
'error': true;
|
|
18
33
|
}
|
|
19
34
|
}
|
package/package.json
CHANGED
|
@@ -1,68 +1,110 @@
|
|
|
1
1
|
{
|
|
2
|
+
"author": "Yuzu Octopus",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/yuzu-octopus/astryx-dracula/issues"
|
|
5
|
+
},
|
|
2
6
|
"dependencies": {
|
|
3
|
-
"
|
|
4
|
-
"@stylexjs/stylex": "^0.19.0",
|
|
5
|
-
"lucide-react": "^1.33.0",
|
|
6
|
-
"react": "^19.2.8",
|
|
7
|
-
"react-dom": "^19.2.8"
|
|
7
|
+
"lucide-react": "^1.45.0"
|
|
8
8
|
},
|
|
9
9
|
"description": "Pure Dracula brand theme for Astryx React sites. Dark-only tokens, syntax highlighting, and chart colors with prebuilt CSS.",
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@astryxdesign/cli": "^0.3.0",
|
|
12
|
-
"@types/bun": "^1.4.
|
|
13
|
-
"@types/node": "^26.
|
|
14
|
-
"@types/react": "^19.
|
|
15
|
-
"@types/react-dom": "^19.
|
|
16
|
-
"@vitejs/plugin-react": "^6.1.
|
|
12
|
+
"@types/bun": "^1.4.2",
|
|
13
|
+
"@types/node": "^26.5.1",
|
|
14
|
+
"@types/react": "^19.3.0",
|
|
15
|
+
"@types/react-dom": "^19.3.0",
|
|
16
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
17
17
|
"typescript": "^7.0.2",
|
|
18
|
-
"vite": "^8.
|
|
18
|
+
"vite": "^8.3.0"
|
|
19
19
|
},
|
|
20
20
|
"exports": {
|
|
21
|
+
"./shared/auth-chrome": "./shared/auth-chrome.tsx",
|
|
22
|
+
"./shared/auth-chrome-config": "./shared/auth-chrome-config.ts",
|
|
23
|
+
"./shared/auth-copy": "./shared/auth-copy.ts",
|
|
24
|
+
"./shared/chaptered-doc": "./shared/chaptered-doc.tsx",
|
|
25
|
+
"./shared/chaptered-doc-config": "./shared/chaptered-doc-config.ts",
|
|
26
|
+
"./shared/chart-hues": "./shared/chart-hues.ts",
|
|
27
|
+
"./shared/chart-labels": "./shared/chart-labels.tsx",
|
|
28
|
+
"./shared/chart-legend": "./shared/chart-legend.tsx",
|
|
29
|
+
"./shared/chart-panel-style": "./shared/chart-panel-style.ts",
|
|
30
|
+
"./shared/data-bar": "./shared/data-bar.tsx",
|
|
31
|
+
"./shared/gallery-image": "./shared/gallery-image.ts",
|
|
32
|
+
"./shared/login-demo": "./shared/login-demo.ts",
|
|
33
|
+
"./shared/metric-delta": "./shared/metric-delta.tsx",
|
|
34
|
+
"./shared/order-desk": "./shared/order-desk.tsx",
|
|
35
|
+
"./shared/revenue-chart": "./shared/revenue-chart.tsx",
|
|
36
|
+
"./shared/scene-castle": "./shared/scene-castle.tsx",
|
|
37
|
+
"./shared/scene-frame": "./shared/scene-frame.tsx",
|
|
38
|
+
"./shared/scene-hues": "./shared/scene-hues.ts",
|
|
39
|
+
"./shared/scene-tile": "./shared/scene-tile.tsx",
|
|
40
|
+
"./shared/settings-data": "./shared/settings-data.ts",
|
|
41
|
+
"./shared/settings-rows": "./shared/settings-rows.tsx",
|
|
42
|
+
"./shared/sparkline": "./shared/sparkline.tsx",
|
|
43
|
+
"./shared/sso-icons": "./shared/sso-icons.tsx",
|
|
21
44
|
".": {
|
|
22
45
|
"default": "./astryx-dracula.js",
|
|
23
46
|
"types": "./astryx-dracula.d.ts"
|
|
24
47
|
},
|
|
25
|
-
"./
|
|
26
|
-
"default": "./astryx-dracula.js",
|
|
27
|
-
"types": "./astryx-dracula.d.ts"
|
|
28
|
-
},
|
|
48
|
+
"./astryx.integration.mjs": "./astryx.integration.mjs",
|
|
29
49
|
"./package.json": "./package.json",
|
|
50
|
+
"./templates/*": "./templates/*",
|
|
30
51
|
"./theme.css": "./theme.css",
|
|
31
52
|
"./tokens.css": "./tokens.css"
|
|
32
53
|
},
|
|
33
54
|
"files": [
|
|
34
55
|
"BRAND.md",
|
|
35
56
|
"LICENSE",
|
|
57
|
+
"README.md",
|
|
36
58
|
"USAGE.md",
|
|
37
59
|
"astryx-dracula.d.ts",
|
|
38
60
|
"astryx-dracula.js",
|
|
39
61
|
"astryx-dracula.variants.d.ts",
|
|
40
62
|
"fonts/",
|
|
41
63
|
"icons.tsx",
|
|
64
|
+
"shared/",
|
|
42
65
|
"theme.css",
|
|
43
66
|
"tokens.css",
|
|
44
67
|
"templates/",
|
|
45
68
|
"astryx.integration.mjs"
|
|
46
69
|
],
|
|
70
|
+
"keywords": [
|
|
71
|
+
"astryx",
|
|
72
|
+
"dracula",
|
|
73
|
+
"dracula-theme",
|
|
74
|
+
"theme",
|
|
75
|
+
"design-system",
|
|
76
|
+
"dark-theme",
|
|
77
|
+
"react",
|
|
78
|
+
"tokens"
|
|
79
|
+
],
|
|
47
80
|
"license": "MIT",
|
|
48
81
|
"name": "astryx-dracula",
|
|
49
82
|
"peerDependencies": {
|
|
50
83
|
"@astryxdesign/core": "^0.3.0",
|
|
84
|
+
"lucide-react": "^1.45.0",
|
|
51
85
|
"react": ">=19.0.0",
|
|
52
86
|
"react-dom": ">=19.0.0"
|
|
53
87
|
},
|
|
88
|
+
"repository": {
|
|
89
|
+
"type": "git",
|
|
90
|
+
"url": "git+https://github.com/yuzu-octopus/astryx-dracula.git"
|
|
91
|
+
},
|
|
54
92
|
"scripts": {
|
|
55
93
|
"audit": "bun scripts/check.ts",
|
|
56
94
|
"build": "tsc --noEmit && vite build",
|
|
57
95
|
"dev": "vite",
|
|
58
96
|
"preview": "vite preview",
|
|
59
97
|
"theme:build": "bunx astryx theme build astryx-theme.ts -o theme.css",
|
|
60
|
-
"theme:check": "bunx astryx theme build astryx-theme.ts -o theme.css --check"
|
|
98
|
+
"theme:check": "bunx astryx theme build astryx-theme.ts -o theme.css --check --json | bun -e 'const r = JSON.parse(await Bun.stdin.text()); if (r.type !== \"theme.build.check\") { console.error(\"theme:check: unexpected CLI response \" + JSON.stringify(r).slice(0, 200)); process.exit(1); } const stale = r.data.stale.filter(s => s.path !== \"astryx-dracula.js\"); for (const s of stale) console.error(\"stale: \" + s.path + \" (\" + s.reason + \")\"); if (stale.length) process.exit(1); const entry = await import(\"./astryx-dracula.js\"); if (!entry.astryxDraculaTheme || !entry.draculaIconRegistry) { console.error(\"astryx-dracula.js is missing its theme or icon registry export\"); process.exit(1); } console.log(\"theme outputs up to date; astryx-dracula.js (hand-maintained) loads and exports\");'",
|
|
99
|
+
"prepublishOnly": "bun run theme:check && bun run audit && tsc --noEmit && bunx react-doctor@latest --score"
|
|
61
100
|
},
|
|
101
|
+
"sideEffects": [
|
|
102
|
+
"**/*.css"
|
|
103
|
+
],
|
|
62
104
|
"trustedDependencies": [
|
|
63
105
|
"@astryxdesign/core",
|
|
64
106
|
"@astryxdesign/cli"
|
|
65
107
|
],
|
|
66
108
|
"type": "module",
|
|
67
|
-
"version": "0.
|
|
109
|
+
"version": "0.3.0"
|
|
68
110
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Auth page chrome, split from the component that renders it, for the same
|
|
2
|
+
// reason as shared/scene-hues.ts: a .tsx exporting non-components breaks React
|
|
3
|
+
// Fast Refresh. Five templates import these, so they are genuinely shared --
|
|
4
|
+
// they were only ever co-located by accident of history.
|
|
5
|
+
import type {CSSProperties} from 'react';
|
|
6
|
+
|
|
7
|
+
// Standalone auth pages paint their own body background (no host shell).
|
|
8
|
+
export const authPageStyle: CSSProperties = {
|
|
9
|
+
minHeight: '100%',
|
|
10
|
+
backgroundColor: 'var(--color-background-body)',
|
|
11
|
+
padding: 'var(--spacing-6)',
|
|
12
|
+
};
|
|
13
|
+
// Cap the column at 400px but let it shrink to fit narrow screens.
|
|
14
|
+
export const authContentStyle: CSSProperties = {width: '100%', maxWidth: 400};
|
|
15
|
+
// WCAG 1.3.5 autocomplete: TextInput forwards unknown props to <input> but its
|
|
16
|
+
// prop type omits input-only attributes, so spread through a widened record.
|
|
17
|
+
export const inputAutoComplete = (value: string) =>
|
|
18
|
+
({autoComplete: value}) as Record<string, string>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Shared login chrome: page wash + 400px column + Moon brand row + the
|
|
2
|
+
// autocomplete widen-record TextInput needs (prop type omits input attrs).
|
|
3
|
+
import type {CSSProperties} from 'react';
|
|
4
|
+
import {Moon} from 'lucide-react';
|
|
5
|
+
import {VStack} from '@astryxdesign/core/Layout';
|
|
6
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
7
|
+
import {Icon} from '@astryxdesign/core/Icon';
|
|
8
|
+
import {AUTH_BRAND_NAME} from 'astryx-dracula/shared/auth-copy';
|
|
9
|
+
import {
|
|
10
|
+
authContentStyle,
|
|
11
|
+
authPageStyle,
|
|
12
|
+
inputAutoComplete,
|
|
13
|
+
} from 'astryx-dracula/shared/auth-chrome-config';
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export function LoginBrand() {
|
|
17
|
+
return (
|
|
18
|
+
<VStack gap={2} hAlign="center">
|
|
19
|
+
<Icon icon={Moon} size="lg" color="secondary" />
|
|
20
|
+
<Text type="body" weight="semibold" size="lg">
|
|
21
|
+
{AUTH_BRAND_NAME}
|
|
22
|
+
</Text>
|
|
23
|
+
</VStack>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Auth copy shared by the four login templates. Single-sourced so the family
|
|
2
|
+
// line cannot drift again. SSO-specific strings (Work email, Whisper your
|
|
3
|
+
// details, Continue with SSO, provider names) stay per-template in login-sso.
|
|
4
|
+
export const AUTH_HEADING = 'Welcome back to the night';
|
|
5
|
+
export const AUTH_SUBTITLE = 'Sign in to your crypt';
|
|
6
|
+
export const AUTH_PRIMARY_CTA = 'Sign in';
|
|
7
|
+
export const AUTH_SIGNUP_PROMPT = 'New to the castle?';
|
|
8
|
+
export const AUTH_SIGNUP_LINK = 'Sign up';
|
|
9
|
+
export const AUTH_SSO_DIVIDER = 'Or continue with';
|
|
10
|
+
export const AUTH_FORGOT_PASSWORD = 'Forgot password?';
|
|
11
|
+
// Names the problem without apologising, and does not blame one field: a
|
|
12
|
+
// mistyped email used to be reported as a wrong password, because this string
|
|
13
|
+
// was attached to the password input only.
|
|
14
|
+
export const AUTH_ERROR_MESSAGE = 'Email or password is wrong. Try again.';
|
|
15
|
+
export const AUTH_EMAIL_PLACEHOLDER = 'you@castle.dracula';
|
|
16
|
+
// The placeholder is the only visible name on the credential inputs, so it has
|
|
17
|
+
// to actually name the field. "Whisper your password" named nothing.
|
|
18
|
+
export const AUTH_PASSWORD_PLACEHOLDER = 'Your password';
|
|
19
|
+
export const AUTH_BRAND_NAME = 'Castle Dracula';
|
|
20
|
+
export const AUTH_TERMS_PREFIX = 'By clicking continue, you agree to our';
|
|
21
|
+
export const AUTH_TERMS_SERVICE = 'Terms of service';
|
|
22
|
+
export const AUTH_TERMS_PRIVACY = 'Privacy policy';
|