@astryxdesign/cli 0.7.1-canary.ff40b78 → 0.7.2-canary.c68f5e8
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/CHANGELOG.md +35 -0
- package/api/build/_adapter.d.mts +1 -0
- package/api/build/_adapter.mjs +7 -0
- package/api/build/build.mjs +4 -1
- package/api/search/search.mjs +12 -0
- package/api/template/table-filter-view-tabs.test.mjs +45 -0
- package/api/theme/build/build.core-on-demand.test.mjs +113 -0
- package/api/theme/build/build.d.mts +13 -13
- package/api/theme/build/build.mjs +72 -37
- package/assets/docs/getting-started.doc.mjs +0 -10
- package/assets/docs/styling-overview.doc.mjs +54 -15
- package/assets/docs/tree/migration-setup.doc.mjs +31 -6
- package/assets/docs/tree/responsive.doc.mjs +37 -0
- package/assets/docs/tree/tailwind.doc.mjs +12 -0
- package/assets/docs/tree/tokens-and-setup.doc.mjs +3 -2
- package/assets/docs/tree/tokens-syntax.doc.mjs +20 -0
- package/assets/docs/tree/tokens.doc.mjs +1 -1
- package/assets/templates/blocks/components/CommandPalette/CommandPaletteAsyncSearch.tsx +6 -1
- package/assets/templates/pages/table-filter/page.tsx +3 -2
- package/assets/templates/themes/butter/butterTheme.ts +53 -11
- package/assets/templates/themes/chocolate/chocolateTheme.ts +29 -5
- package/assets/templates/themes/gothic/gothicTheme.ts +44 -9
- package/assets/templates/themes/stone/stoneTheme.ts +58 -11
- package/assets/templates/themes/y2k/y2kTheme.ts +60 -10
- package/clients/cli/commands/build-theme.mjs +32 -4
- package/clients/cli/commands/build-theme.watch.test.mjs +63 -2
- package/foundation/discovery/component-discovery.mjs +27 -26
- package/foundation/discovery/hook-discovery.mjs +13 -12
- package/foundation/fs/listing-cache.d.mts +36 -0
- package/foundation/fs/listing-cache.mjs +95 -0
- package/foundation/fs/listing-cache.test.mjs +88 -0
- package/foundation/fs/paths.mjs +3 -2
- package/package.json +9 -9
|
@@ -129,15 +129,31 @@ export function AppRoot({children}: {children: React.ReactNode}) {
|
|
|
129
129
|
},
|
|
130
130
|
{
|
|
131
131
|
type: 'prose',
|
|
132
|
-
text: '
|
|
132
|
+
text: 'A layer\'s rank is set by the first stylesheet on the page that names it, so the global CSS file (or a `layers.css` holding only the `@layer` line) must be the first import in the root layout or app entry. Import it before any module that imports Astryx or theme CSS, including the `astryx-themes` module generated by `astryx theme add` and a root component like the `AppRoot` above that imports `theme.css`. If a theme stylesheet loads first, Tailwind preflight overrides Astryx base styles and theme overrides lose.',
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
type: 'code',
|
|
136
|
-
lang: '
|
|
137
|
-
label: '
|
|
138
|
-
code:
|
|
136
|
+
lang: 'tsx',
|
|
137
|
+
label: 'Root layout or app entry',
|
|
138
|
+
code: `import './globals.css'; // first: declares the cascade-layer order
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
import {AppRoot} from './AppRoot';`,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'prose',
|
|
144
|
+
text: 'On Tailwind v3 there is no preflight.css to import, so wrap the @tailwind base directive in a named layer instead. Keep utilities unlayered so existing app utility classes still win everywhere. Put the `@layer` order line in its own `layers.css` and import it first, before `globals.css`: Next.js (webpack or Turbopack) and other bundlers that hoist CSS imports move the imported files above an inline `@layer` line, so the order would arrive too late.',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'code',
|
|
148
|
+
lang: 'css',
|
|
149
|
+
label: 'layers.css (imported first)',
|
|
150
|
+
code: `@layer reset, tw-preflight, astryx-base, astryx-theme;`,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
type: 'code',
|
|
154
|
+
lang: 'css',
|
|
155
|
+
label: 'globals.css (Tailwind v3 coexistence)',
|
|
156
|
+
code: `@import "@astryxdesign/core/reset.css";
|
|
141
157
|
@import "@astryxdesign/core/astryx.css";
|
|
142
158
|
@import "@astryxdesign/theme-neutral/theme.css";
|
|
143
159
|
|
|
@@ -147,6 +163,15 @@ export function AppRoot({children}: {children: React.ReactNode}) {
|
|
|
147
163
|
@tailwind components;
|
|
148
164
|
@tailwind utilities; /* unlayered: legacy utility classes keep winning */`,
|
|
149
165
|
},
|
|
166
|
+
{
|
|
167
|
+
type: 'code',
|
|
168
|
+
lang: 'tsx',
|
|
169
|
+
label: 'Root layout or app entry (Tailwind v3)',
|
|
170
|
+
code: `import './layers.css'; // first: declares the cascade-layer order
|
|
171
|
+
import './globals.css';
|
|
172
|
+
|
|
173
|
+
import {AppRoot} from './AppRoot';`,
|
|
174
|
+
},
|
|
150
175
|
],
|
|
151
176
|
},
|
|
152
177
|
{
|
|
@@ -186,7 +211,7 @@ export function AppRoot({children}: {children: React.ReactNode}) {
|
|
|
186
211
|
type: 'list',
|
|
187
212
|
style: 'unordered',
|
|
188
213
|
items: [
|
|
189
|
-
'Declare the canonical @layer order once, before any @import. With webpack
|
|
214
|
+
'Declare the canonical @layer order once, before any @import. With Next.js (webpack or Turbopack) and other bundlers that hoist CSS imports, the order declaration must live in its own CSS file imported first, such as layers.css, because the bundler hoists @import content above the inline CSS that follows it.',
|
|
190
215
|
'Audit every pre-existing global or reset stylesheet and assign each one to a layer deliberately. Top-level imports without layer() stay unlayered and beat every layer; imports nested inside a layered file inherit that layer.',
|
|
191
216
|
'Remove or demote the app legacy reset. The design system ships its own :where() reset in the lowest layer, so any app reset belongs in that same reset layer and never in a layer above astryx-base.',
|
|
192
217
|
'Layer Tailwind preflight. On Tailwind v4, import preflight.css with layer(base). On Tailwind v3, wrap the @tailwind base directive in a named layer (see the snippet in Theme and CSS Setup). Unlayered preflight overrides theme CSS silently.',
|
|
@@ -21,6 +21,9 @@ export const docs = {
|
|
|
21
21
|
'Dialog',
|
|
22
22
|
'BottomSheet',
|
|
23
23
|
'contract',
|
|
24
|
+
'Grid',
|
|
25
|
+
'columns',
|
|
26
|
+
'minWidth',
|
|
24
27
|
],
|
|
25
28
|
|
|
26
29
|
sections: [
|
|
@@ -94,5 +97,39 @@ const isNarrow = useMediaQuery('(max-width: 1024px)');
|
|
|
94
97
|
},
|
|
95
98
|
],
|
|
96
99
|
},
|
|
100
|
+
{
|
|
101
|
+
id: 'columns-that-reflow',
|
|
102
|
+
title: 'Columns that reflow',
|
|
103
|
+
content: [
|
|
104
|
+
{
|
|
105
|
+
type: 'prose',
|
|
106
|
+
text: 'For columns that reflow on small screens, use `Grid columns={{minWidth, max}}`. A numeric `columns` is exactly N columns at every width and never reflows: `columns={4}` on a 390px phone renders four tracks under 100px wide, and the row overflows the page as soon as their content cannot shrink to fit. `{minWidth: 240, max: 4}` renders at most four columns, each at least 240px, and drops to one full-width column when the container is narrow; `max` is what lets that last column shrink to the container, and `gap` counts toward the room the columns need.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'code',
|
|
110
|
+
lang: 'tsx',
|
|
111
|
+
label: 'Reflowing stat row versus a fixed week row',
|
|
112
|
+
code: `// Reflows: 4 columns on desktop, 3 in a 768px-wide grid, 1 on a phone.
|
|
113
|
+
<Grid columns={{minWidth: 240, max: 4}} gap={3}>
|
|
114
|
+
{stats.map(stat => <StatCard key={stat.id} {...stat} />)}
|
|
115
|
+
</Grid>
|
|
116
|
+
|
|
117
|
+
// Fixed: exactly 7 columns at every width (a number never reflows).
|
|
118
|
+
<Grid columns={7} gap={1}>
|
|
119
|
+
{days.map(day => <DayCell key={day} day={day} />)}
|
|
120
|
+
</Grid>`,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'list',
|
|
124
|
+
style: 'unordered',
|
|
125
|
+
items: [
|
|
126
|
+
'`{minWidth}` alone: as many columns as fit at the floor, no cap; a container narrower than `minWidth` overflows, so add `max` for anything that reaches a phone',
|
|
127
|
+
"`{minWidth, repeat: 'fit'}`: empty tracks collapse so present items stretch",
|
|
128
|
+
"A numeric `GridSpan` wider than the grid's current columns adds implicit columns to the whole grid; items placed before and after the span flow into them, and `columns='full'` then covers only the explicit columns. In a reflowing grid keep spans within the smallest count it can reach, or use `'full'`, which adds none",
|
|
129
|
+
'Styling that changes the room columns have to fit changes the count a reflowing shape reaches: a `columnGap` or `gap` step, inline padding on the grid, or `grid-auto-flow: column` through `xstyle`, which places items into extra implicit columns. A `className` rule replaces the computed track list only when it wins the cascade against the generated styles; prefer `xstyle` for overrides',
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
},
|
|
97
134
|
],
|
|
98
135
|
};
|
|
@@ -47,6 +47,18 @@ export const docs = {
|
|
|
47
47
|
type: 'prose',
|
|
48
48
|
text: 'Pre-declare every layer before any imports. This keeps reset lowest, Tailwind preflight above reset, component/theme styles in the middle, and Tailwind utilities last so utility classes on `className` can intentionally override component defaults.',
|
|
49
49
|
},
|
|
50
|
+
{
|
|
51
|
+
type: 'prose',
|
|
52
|
+
text: 'A layer\'s rank is set by the first stylesheet on the page that names it, so this order only holds when `globals.css` loads first. Make it the first import in the root layout or app entry, before any module that imports Astryx or theme CSS. That includes the `astryx-themes` module generated by `astryx theme add` and any root component that imports a theme\'s `theme.css`. If a theme stylesheet loads first, Tailwind preflight overrides Astryx base styles and theme overrides lose. If `globals.css` cannot come first, move the `@layer` line into its own `layers.css` and import that first instead.',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'code',
|
|
56
|
+
lang: 'tsx',
|
|
57
|
+
label: 'Root layout or app entry',
|
|
58
|
+
code: `import './globals.css'; // first: declares the cascade-layer order
|
|
59
|
+
|
|
60
|
+
import {themes, defaultThemeSlug} from './astryx-themes';`,
|
|
61
|
+
},
|
|
50
62
|
{
|
|
51
63
|
type: 'code',
|
|
52
64
|
lang: 'tsx',
|
|
@@ -77,7 +77,7 @@ const styles = stylex.create({
|
|
|
77
77
|
content: [
|
|
78
78
|
{
|
|
79
79
|
type: 'prose',
|
|
80
|
-
text: 'Astryx components ship pre-compiled, so consuming the published
|
|
80
|
+
text: 'Astryx components ship pre-compiled: `astryx.css` and each package\'s own stylesheet hold all of their styles, so consuming the published packages needs no StyleX setup. But `astryx swizzle <Component>` copies the raw StyleX *source* into your app, and StyleX source requires a build-time StyleX compiler to produce atomic CSS. Without one the component compiles but renders completely unstyled: no error, no warning. If a swizzled component looks unstyled, a missing StyleX compiler is almost always why. The same applies if you author your own StyleX with `stylex.create()`.',
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
type: 'table',
|
|
@@ -105,7 +105,7 @@ const styles = stylex.create({
|
|
|
105
105
|
|
|
106
106
|
export default stylexPlugin({
|
|
107
107
|
rsOptions: {
|
|
108
|
-
// Resolve
|
|
108
|
+
// Resolve the Astryx token modules that swizzled source imports.
|
|
109
109
|
aliases: {'@/*': ['./src/*']},
|
|
110
110
|
unstable_moduleResolution: {type: 'commonJS'},
|
|
111
111
|
},
|
|
@@ -120,6 +120,7 @@ export default stylexPlugin({
|
|
|
120
120
|
'Symptom of a missing compiler: swizzled component renders with no styles, but no build or runtime error.',
|
|
121
121
|
'A Babel config turns off SWC in Next.js; skip it if you need `next/font`.',
|
|
122
122
|
'Pure theming (defineTheme + astryx theme build) needs NO StyleX compiler; only swizzled/authored StyleX source does.',
|
|
123
|
+
'Keep loading `astryx.css` with a StyleX compiler in place. The compiler builds your own and swizzled source only; never add `node_modules/@astryxdesign` to its inputs.',
|
|
123
124
|
],
|
|
124
125
|
},
|
|
125
126
|
],
|
|
@@ -88,6 +88,26 @@ export const docs = {
|
|
|
88
88
|
[
|
|
89
89
|
"--color-syntax-background",
|
|
90
90
|
"var(--color-background-muted)"
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
"--color-syntax-added",
|
|
94
|
+
"color-mix(in srgb, var(--color-success-muted) 25%, transparent)"
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
"--color-syntax-removed",
|
|
98
|
+
"color-mix(in srgb, var(--color-error-muted) 25%, transparent)"
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
"--color-syntax-diff-header",
|
|
102
|
+
"var(--color-background-muted)"
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
"--color-syntax-added-marker",
|
|
106
|
+
"var(--color-text-green)"
|
|
107
|
+
],
|
|
108
|
+
[
|
|
109
|
+
"--color-syntax-removed-marker",
|
|
110
|
+
"var(--color-text-red)"
|
|
91
111
|
]
|
|
92
112
|
]
|
|
93
113
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// AUTO-GENERATED — do not edit manually.
|
|
4
4
|
// Run: node scripts/generate-token-docs.mjs
|
|
5
|
-
// Total:
|
|
5
|
+
// Total: 263 tokens across 15 categories.
|
|
6
6
|
|
|
7
7
|
/** @type {import('@astryxdesign/cli/authoring').NamespaceDoc} */
|
|
8
8
|
export const docs = {
|
|
@@ -39,7 +39,12 @@ export default function CommandPaletteAsyncSearch() {
|
|
|
39
39
|
isInline
|
|
40
40
|
onOpenChange={() => {}}
|
|
41
41
|
searchSource={source}
|
|
42
|
-
input={
|
|
42
|
+
input={
|
|
43
|
+
<CommandPaletteInput
|
|
44
|
+
label="Search files"
|
|
45
|
+
placeholder="Search files..."
|
|
46
|
+
/>
|
|
47
|
+
}
|
|
43
48
|
emptyBootstrapText="Type a filename to search"
|
|
44
49
|
emptySearchText="No files found"
|
|
45
50
|
/>
|
|
@@ -4099,7 +4099,7 @@ export default function TableFilterTemplate() {
|
|
|
4099
4099
|
restates the selected tab word for word, and the strip already
|
|
4100
4100
|
marks which one that is. On a phone that is a line of vertical
|
|
4101
4101
|
space spent saying it twice. The panel keeps the name for anyone
|
|
4102
|
-
not seeing the strip
|
|
4102
|
+
not seeing the strip: its selected tab labels it. */}
|
|
4103
4103
|
<TabList
|
|
4104
4104
|
value={viewSection}
|
|
4105
4105
|
onChange={value => setViewSection(value as ViewSection)}
|
|
@@ -4109,6 +4109,7 @@ export default function TableFilterTemplate() {
|
|
|
4109
4109
|
{VIEW_SECTIONS.map(section => (
|
|
4110
4110
|
<Tab
|
|
4111
4111
|
key={section.key}
|
|
4112
|
+
id={`${viewPanelId}-tab-${section.key}`}
|
|
4112
4113
|
value={section.key}
|
|
4113
4114
|
label={section.label}
|
|
4114
4115
|
icon={section.icon}
|
|
@@ -4126,7 +4127,7 @@ export default function TableFilterTemplate() {
|
|
|
4126
4127
|
gap={0}
|
|
4127
4128
|
id={viewPanelId}
|
|
4128
4129
|
role="tabpanel"
|
|
4129
|
-
aria-
|
|
4130
|
+
aria-labelledby={`${viewPanelId}-tab-${viewSection}`}
|
|
4130
4131
|
paddingBlockStart={3}>
|
|
4131
4132
|
{viewPanelBody()}
|
|
4132
4133
|
</VStack>
|
|
@@ -43,6 +43,55 @@ const butterSyntax = defineSyntaxTheme({
|
|
|
43
43
|
},
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* The secondary Button treatment. Selector, MultiSelector, and ComplexSelector
|
|
48
|
+
* reuse it for their `secondary` trigger so every secondary control in this
|
|
49
|
+
* theme matches (AST-079 FR2).
|
|
50
|
+
*
|
|
51
|
+
* Secondary: blue outline + label in light, butter yellow in dark.
|
|
52
|
+
*/
|
|
53
|
+
const SECONDARY_BUTTON = {
|
|
54
|
+
backgroundColor: 'transparent',
|
|
55
|
+
borderWidth: '1.5px',
|
|
56
|
+
borderStyle: 'solid',
|
|
57
|
+
borderColor: 'light-dark(#225BFF, #FDEE8C)',
|
|
58
|
+
color: 'light-dark(#225BFF, #FDEE8C)',
|
|
59
|
+
':hover': {
|
|
60
|
+
backgroundColor: 'light-dark(#225BFF14, #FDEE8C14)',
|
|
61
|
+
},
|
|
62
|
+
} as const;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The secondary Button treatment on Selector and MultiSelector triggers
|
|
66
|
+
* (AST-079 FR2). Inside an InputGroup a trigger keeps the neutral fill and the
|
|
67
|
+
* group's edges instead (FR6). The hover stays off disabled and read-only
|
|
68
|
+
* triggers, which carry `data-disabled` and `data-readonly`.
|
|
69
|
+
*/
|
|
70
|
+
const SECONDARY_SELECTOR = {
|
|
71
|
+
':not(.astryx-input-group *)': {
|
|
72
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
73
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
74
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
75
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
76
|
+
color: SECONDARY_BUTTON.color,
|
|
77
|
+
},
|
|
78
|
+
':hover:not([data-disabled], [data-readonly], .astryx-input-group *)':
|
|
79
|
+
SECONDARY_BUTTON[':hover'],
|
|
80
|
+
} as const;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The secondary Button treatment on ComplexSelector triggers (AST-079 FR2), with
|
|
84
|
+
* the hover kept off a disabled trigger, whose inner button is disabled.
|
|
85
|
+
*/
|
|
86
|
+
const SECONDARY_COMPLEX_SELECTOR = {
|
|
87
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
88
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
89
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
90
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
91
|
+
color: SECONDARY_BUTTON.color,
|
|
92
|
+
':hover:not(:has(> :disabled))': SECONDARY_BUTTON[':hover'],
|
|
93
|
+
} as const;
|
|
94
|
+
|
|
46
95
|
export const butterTheme = defineTheme({
|
|
47
96
|
name: 'butter',
|
|
48
97
|
|
|
@@ -276,17 +325,7 @@ export const butterTheme = defineTheme({
|
|
|
276
325
|
paddingBlock: 'var(--spacing-3)',
|
|
277
326
|
paddingInline: 'var(--spacing-4)',
|
|
278
327
|
},
|
|
279
|
-
|
|
280
|
-
'variant:secondary': {
|
|
281
|
-
backgroundColor: 'transparent',
|
|
282
|
-
borderWidth: '1.5px',
|
|
283
|
-
borderStyle: 'solid',
|
|
284
|
-
borderColor: 'light-dark(#225BFF, #FDEE8C)',
|
|
285
|
-
color: 'light-dark(#225BFF, #FDEE8C)',
|
|
286
|
-
':hover': {
|
|
287
|
-
backgroundColor: 'light-dark(#225BFF14, #FDEE8C14)',
|
|
288
|
-
},
|
|
289
|
-
},
|
|
328
|
+
'variant:secondary': SECONDARY_BUTTON,
|
|
290
329
|
// Ghost: same accent color as secondary, no background.
|
|
291
330
|
'variant:ghost': {
|
|
292
331
|
color: 'light-dark(#225BFF, #FDEE8C)',
|
|
@@ -534,6 +573,7 @@ export const butterTheme = defineTheme({
|
|
|
534
573
|
'status:success': {'--color-success': '#91D143'},
|
|
535
574
|
'status:warning': {'--color-warning': '#ffc502'},
|
|
536
575
|
'status:error': {'--color-error': '#fc473b'},
|
|
576
|
+
'variant:secondary': SECONDARY_SELECTOR,
|
|
537
577
|
},
|
|
538
578
|
'multi-selector': {
|
|
539
579
|
base: {
|
|
@@ -544,7 +584,9 @@ export const butterTheme = defineTheme({
|
|
|
544
584
|
'status:success': {'--color-success': '#91D143'},
|
|
545
585
|
'status:warning': {'--color-warning': '#ffc502'},
|
|
546
586
|
'status:error': {'--color-error': '#fc473b'},
|
|
587
|
+
'variant:secondary': SECONDARY_SELECTOR,
|
|
547
588
|
},
|
|
589
|
+
'complex-selector': {'variant:secondary': SECONDARY_COMPLEX_SELECTOR},
|
|
548
590
|
typeahead: {
|
|
549
591
|
base: {
|
|
550
592
|
paddingBlock: 'var(--spacing-2)',
|
|
@@ -34,6 +34,30 @@ const chocolateSyntax = defineSyntaxTheme({
|
|
|
34
34
|
},
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* The secondary Button treatment. Selector, MultiSelector, and ComplexSelector
|
|
39
|
+
* reuse it for their `secondary` trigger so every secondary control in this
|
|
40
|
+
* theme matches (AST-079 FR2).
|
|
41
|
+
*/
|
|
42
|
+
const SECONDARY_BUTTON = {
|
|
43
|
+
borderWidth: '1px',
|
|
44
|
+
borderStyle: 'solid',
|
|
45
|
+
borderColor: 'var(--color-border-emphasized)',
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The secondary Button treatment on Selector and MultiSelector triggers
|
|
50
|
+
* (AST-079 FR2). Inside an InputGroup a trigger keeps the neutral fill and the
|
|
51
|
+
* group's edges instead (FR6).
|
|
52
|
+
*/
|
|
53
|
+
const SECONDARY_SELECTOR = {
|
|
54
|
+
':not(.astryx-input-group *)': {
|
|
55
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
56
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
57
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
58
|
+
},
|
|
59
|
+
} as const;
|
|
60
|
+
|
|
37
61
|
export const chocolateTheme = defineTheme({
|
|
38
62
|
name: 'chocolate',
|
|
39
63
|
|
|
@@ -219,12 +243,12 @@ export const chocolateTheme = defineTheme({
|
|
|
219
243
|
base: {
|
|
220
244
|
borderRadius: 'var(--radius-full)',
|
|
221
245
|
},
|
|
222
|
-
'variant:secondary':
|
|
223
|
-
borderWidth: '1px',
|
|
224
|
-
borderStyle: 'solid',
|
|
225
|
-
borderColor: 'var(--color-border-emphasized)',
|
|
226
|
-
},
|
|
246
|
+
'variant:secondary': SECONDARY_BUTTON,
|
|
227
247
|
},
|
|
248
|
+
// Secondary selector triggers match the secondary Button (AST-079 FR2).
|
|
249
|
+
selector: {'variant:secondary': SECONDARY_SELECTOR},
|
|
250
|
+
'multi-selector': {'variant:secondary': SECONDARY_SELECTOR},
|
|
251
|
+
'complex-selector': {'variant:secondary': SECONDARY_BUTTON},
|
|
228
252
|
|
|
229
253
|
card: {
|
|
230
254
|
base: {
|
|
@@ -40,9 +40,48 @@ const gothicSyntax = defineSyntaxTheme({
|
|
|
40
40
|
property: '#7cc5b3', // Verdigris
|
|
41
41
|
punctuation: '#7a8290', // Mid neutral
|
|
42
42
|
background: '#101314',
|
|
43
|
+
// Diff rows on the near-black background: any lighter wash lowers every
|
|
44
|
+
// light token's contrast, so the rows take opaque hues at the
|
|
45
|
+
// background's own luminance — a deep green and a deep red that read as
|
|
46
|
+
// colour, not brightness — and every token keeps the contrast it has on
|
|
47
|
+
// the plain background. Markers: forest moss and blood crimson.
|
|
48
|
+
added: '#081408',
|
|
49
|
+
removed: '#1e0a0a',
|
|
50
|
+
'added-marker': '#a3c987',
|
|
51
|
+
'removed-marker': '#d97580',
|
|
43
52
|
},
|
|
44
53
|
});
|
|
45
54
|
|
|
55
|
+
/**
|
|
56
|
+
* The secondary Button treatment. Selector, MultiSelector, and ComplexSelector
|
|
57
|
+
* reuse it for their `secondary` trigger so every secondary control in this
|
|
58
|
+
* theme matches (AST-079 FR2).
|
|
59
|
+
*
|
|
60
|
+
* Primary inherits default — light pill with dark text via
|
|
61
|
+
* --color-accent / --color-on-accent (matches the cream badge).
|
|
62
|
+
* Secondary uses the dark-slate "neutral" badge treatment.
|
|
63
|
+
*/
|
|
64
|
+
const SECONDARY_BUTTON = {
|
|
65
|
+
backgroundColor: 'var(--color-background-gray)',
|
|
66
|
+
color: 'var(--color-text-gray)',
|
|
67
|
+
borderColor: 'transparent',
|
|
68
|
+
borderWidth: '0',
|
|
69
|
+
} as const;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The secondary Button treatment on Selector and MultiSelector triggers
|
|
73
|
+
* (AST-079 FR2). Inside an InputGroup a trigger keeps the neutral fill and the
|
|
74
|
+
* group's edges instead (FR6).
|
|
75
|
+
*/
|
|
76
|
+
const SECONDARY_SELECTOR = {
|
|
77
|
+
':not(.astryx-input-group *)': {
|
|
78
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
79
|
+
color: SECONDARY_BUTTON.color,
|
|
80
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
81
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
82
|
+
},
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
46
85
|
export const gothicTheme = defineTheme({
|
|
47
86
|
name: 'gothic',
|
|
48
87
|
|
|
@@ -227,15 +266,7 @@ export const gothicTheme = defineTheme({
|
|
|
227
266
|
|
|
228
267
|
components: {
|
|
229
268
|
button: {
|
|
230
|
-
|
|
231
|
-
// --color-accent / --color-on-accent (matches the cream badge).
|
|
232
|
-
// Secondary uses the dark-slate "neutral" badge treatment.
|
|
233
|
-
'variant:secondary': {
|
|
234
|
-
backgroundColor: 'var(--color-background-gray)',
|
|
235
|
-
color: 'var(--color-text-gray)',
|
|
236
|
-
borderColor: 'transparent',
|
|
237
|
-
borderWidth: '0',
|
|
238
|
-
},
|
|
269
|
+
'variant:secondary': SECONDARY_BUTTON,
|
|
239
270
|
'variant:ghost': {
|
|
240
271
|
':hover': {
|
|
241
272
|
backgroundColor: 'var(--color-overlay-hover)',
|
|
@@ -248,6 +279,10 @@ export const gothicTheme = defineTheme({
|
|
|
248
279
|
color: 'var(--color-text-red)',
|
|
249
280
|
},
|
|
250
281
|
},
|
|
282
|
+
// Secondary selector triggers match the secondary Button (AST-079 FR2).
|
|
283
|
+
selector: {'variant:secondary': SECONDARY_SELECTOR},
|
|
284
|
+
'multi-selector': {'variant:secondary': SECONDARY_SELECTOR},
|
|
285
|
+
'complex-selector': {'variant:secondary': SECONDARY_BUTTON},
|
|
251
286
|
|
|
252
287
|
badge: {
|
|
253
288
|
base: {
|
|
@@ -56,9 +56,60 @@ const stoneSyntax = defineSyntaxTheme({
|
|
|
56
56
|
property: ['#4e6357', '#94b2a0'], // Teal T40 / T70
|
|
57
57
|
punctuation: ['#5e5e5e', '#ababb0'], // Stone Neutral T40 / T70
|
|
58
58
|
background: ['#f3f3f5', '#171719'],
|
|
59
|
+
// Diff rows: the muted green/red at 25% in light and 20% in dark keep
|
|
60
|
+
// every token at or above 4.5:1 on the tint; the markers are the tinted
|
|
61
|
+
// text tokens (8.1:1 light, 8.8:1 dark on their tints).
|
|
62
|
+
added: ['#d0e9ce40', '#b4cdb233'],
|
|
63
|
+
removed: ['#f9dcd740', '#dcc0bc33'],
|
|
64
|
+
'added-marker': ['#374c36', '#d0e9ce'],
|
|
65
|
+
'removed-marker': ['#58413e', '#f9dcd7'],
|
|
59
66
|
},
|
|
60
67
|
});
|
|
61
68
|
|
|
69
|
+
/**
|
|
70
|
+
* The secondary Button treatment. Selector, MultiSelector, and ComplexSelector
|
|
71
|
+
* reuse it for their `secondary` trigger so every secondary control in this
|
|
72
|
+
* theme matches (AST-079 FR2).
|
|
73
|
+
*/
|
|
74
|
+
const SECONDARY_BUTTON = {
|
|
75
|
+
backgroundColor: 'transparent',
|
|
76
|
+
borderWidth: '1.5px',
|
|
77
|
+
borderStyle: 'solid',
|
|
78
|
+
borderColor: 'var(--color-border-emphasized)',
|
|
79
|
+
':hover': {
|
|
80
|
+
backgroundColor: 'var(--color-neutral)',
|
|
81
|
+
},
|
|
82
|
+
} as const;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The secondary Button treatment on Selector and MultiSelector triggers
|
|
86
|
+
* (AST-079 FR2). Inside an InputGroup a trigger keeps the neutral fill and the
|
|
87
|
+
* group's edges instead (FR6). The hover stays off disabled and read-only
|
|
88
|
+
* triggers, which carry `data-disabled` and `data-readonly`.
|
|
89
|
+
*/
|
|
90
|
+
const SECONDARY_SELECTOR = {
|
|
91
|
+
':not(.astryx-input-group *)': {
|
|
92
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
93
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
94
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
95
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
96
|
+
},
|
|
97
|
+
':hover:not([data-disabled], [data-readonly], .astryx-input-group *)':
|
|
98
|
+
SECONDARY_BUTTON[':hover'],
|
|
99
|
+
} as const;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The secondary Button treatment on ComplexSelector triggers (AST-079 FR2), with
|
|
103
|
+
* the hover kept off a disabled trigger, whose inner button is disabled.
|
|
104
|
+
*/
|
|
105
|
+
const SECONDARY_COMPLEX_SELECTOR = {
|
|
106
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
107
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
108
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
109
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
110
|
+
':hover:not(:has(> :disabled))': SECONDARY_BUTTON[':hover'],
|
|
111
|
+
} as const;
|
|
112
|
+
|
|
62
113
|
export const stoneTheme = defineTheme({
|
|
63
114
|
name: 'stone',
|
|
64
115
|
|
|
@@ -262,15 +313,7 @@ export const stoneTheme = defineTheme({
|
|
|
262
313
|
base: {
|
|
263
314
|
borderRadius: 'var(--radius-full)',
|
|
264
315
|
},
|
|
265
|
-
'variant:secondary':
|
|
266
|
-
backgroundColor: 'transparent',
|
|
267
|
-
borderWidth: '1.5px',
|
|
268
|
-
borderStyle: 'solid',
|
|
269
|
-
borderColor: 'var(--color-border-emphasized)',
|
|
270
|
-
':hover': {
|
|
271
|
-
backgroundColor: 'var(--color-neutral)',
|
|
272
|
-
},
|
|
273
|
-
},
|
|
316
|
+
'variant:secondary': SECONDARY_BUTTON,
|
|
274
317
|
'variant:destructive': {
|
|
275
318
|
backgroundColor: 'var(--color-background-red)',
|
|
276
319
|
color: 'var(--color-text-red)',
|
|
@@ -389,8 +432,12 @@ export const stoneTheme = defineTheme({
|
|
|
389
432
|
'number-input': INPUT_STATUS_VARS,
|
|
390
433
|
'date-input': INPUT_STATUS_VARS,
|
|
391
434
|
'time-input': INPUT_STATUS_VARS,
|
|
392
|
-
selector: INPUT_STATUS_VARS,
|
|
393
|
-
'multi-selector':
|
|
435
|
+
selector: {...INPUT_STATUS_VARS, 'variant:secondary': SECONDARY_SELECTOR},
|
|
436
|
+
'multi-selector': {
|
|
437
|
+
...INPUT_STATUS_VARS,
|
|
438
|
+
'variant:secondary': SECONDARY_SELECTOR,
|
|
439
|
+
},
|
|
440
|
+
'complex-selector': {'variant:secondary': SECONDARY_COMPLEX_SELECTOR},
|
|
394
441
|
typeahead: INPUT_STATUS_VARS,
|
|
395
442
|
tokenizer: INPUT_STATUS_VARS,
|
|
396
443
|
|
|
@@ -29,9 +29,64 @@ const y2kSyntax = defineSyntaxTheme({
|
|
|
29
29
|
property: ['#3c6755', '#87b5a1'],
|
|
30
30
|
punctuation: ['#5e5e5e', '#ababab'],
|
|
31
31
|
background: ['#FFF6ED', '#190f00'],
|
|
32
|
+
// Diff rows: the muted green/red at 25% in light and 20% in dark keep
|
|
33
|
+
// every token at or above 4.5:1 on the tint. Markers: the tinted text
|
|
34
|
+
// tokens in light (7.3:1 / 7.9:1); in dark those tokens are near-black,
|
|
35
|
+
// so the string and tag colours mark the rows (5.1:1 each).
|
|
36
|
+
added: ['#C5E17A40', '#C5E17A33'],
|
|
37
|
+
removed: ['#FFC5C340', '#FFC5C333'],
|
|
38
|
+
'added-marker': ['#3a5500', '#a5af8b'],
|
|
39
|
+
'removed-marker': ['#8b1d24', '#d19f9d'],
|
|
32
40
|
},
|
|
33
41
|
});
|
|
34
42
|
|
|
43
|
+
/**
|
|
44
|
+
* The secondary Button treatment. Selector, MultiSelector, and ComplexSelector
|
|
45
|
+
* reuse it for their `secondary` trigger so every secondary control in this
|
|
46
|
+
* theme matches (AST-079 FR2).
|
|
47
|
+
*/
|
|
48
|
+
const SECONDARY_BUTTON = {
|
|
49
|
+
backgroundColor: 'var(--color-background-green)',
|
|
50
|
+
borderWidth: '1px',
|
|
51
|
+
borderStyle: 'solid',
|
|
52
|
+
borderColor: 'var(--color-text-green)',
|
|
53
|
+
color: 'var(--color-text-green)',
|
|
54
|
+
':hover': {
|
|
55
|
+
backgroundColor: 'var(--color-border-green)',
|
|
56
|
+
},
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The secondary Button treatment on Selector and MultiSelector triggers
|
|
61
|
+
* (AST-079 FR2). Inside an InputGroup a trigger keeps the neutral fill and the
|
|
62
|
+
* group's edges instead (FR6). The hover stays off disabled and read-only
|
|
63
|
+
* triggers, which carry `data-disabled` and `data-readonly`.
|
|
64
|
+
*/
|
|
65
|
+
const SECONDARY_SELECTOR = {
|
|
66
|
+
':not(.astryx-input-group *)': {
|
|
67
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
68
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
69
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
70
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
71
|
+
color: SECONDARY_BUTTON.color,
|
|
72
|
+
},
|
|
73
|
+
':hover:not([data-disabled], [data-readonly], .astryx-input-group *)':
|
|
74
|
+
SECONDARY_BUTTON[':hover'],
|
|
75
|
+
} as const;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The secondary Button treatment on ComplexSelector triggers (AST-079 FR2), with
|
|
79
|
+
* the hover kept off a disabled trigger, whose inner button is disabled.
|
|
80
|
+
*/
|
|
81
|
+
const SECONDARY_COMPLEX_SELECTOR = {
|
|
82
|
+
backgroundColor: SECONDARY_BUTTON.backgroundColor,
|
|
83
|
+
borderWidth: SECONDARY_BUTTON.borderWidth,
|
|
84
|
+
borderStyle: SECONDARY_BUTTON.borderStyle,
|
|
85
|
+
borderColor: SECONDARY_BUTTON.borderColor,
|
|
86
|
+
color: SECONDARY_BUTTON.color,
|
|
87
|
+
':hover:not(:has(> :disabled))': SECONDARY_BUTTON[':hover'],
|
|
88
|
+
} as const;
|
|
89
|
+
|
|
35
90
|
export const y2kTheme = defineTheme({
|
|
36
91
|
name: 'y2k',
|
|
37
92
|
|
|
@@ -256,16 +311,7 @@ export const y2kTheme = defineTheme({
|
|
|
256
311
|
color: 'var(--color-background-body)',
|
|
257
312
|
borderColor: 'transparent',
|
|
258
313
|
},
|
|
259
|
-
'variant:secondary':
|
|
260
|
-
backgroundColor: 'var(--color-background-green)',
|
|
261
|
-
borderWidth: '1px',
|
|
262
|
-
borderStyle: 'solid',
|
|
263
|
-
borderColor: 'var(--color-text-green)',
|
|
264
|
-
color: 'var(--color-text-green)',
|
|
265
|
-
':hover': {
|
|
266
|
-
backgroundColor: 'var(--color-border-green)',
|
|
267
|
-
},
|
|
268
|
-
},
|
|
314
|
+
'variant:secondary': SECONDARY_BUTTON,
|
|
269
315
|
'variant:ghost': {
|
|
270
316
|
borderColor: 'transparent',
|
|
271
317
|
},
|
|
@@ -277,6 +323,10 @@ export const y2kTheme = defineTheme({
|
|
|
277
323
|
borderColor: 'var(--color-text-red)',
|
|
278
324
|
},
|
|
279
325
|
},
|
|
326
|
+
// Secondary selector triggers match the secondary Button (AST-079 FR2).
|
|
327
|
+
selector: {'variant:secondary': SECONDARY_SELECTOR},
|
|
328
|
+
'multi-selector': {'variant:secondary': SECONDARY_SELECTOR},
|
|
329
|
+
'complex-selector': {'variant:secondary': SECONDARY_COMPLEX_SELECTOR},
|
|
280
330
|
|
|
281
331
|
badge: {
|
|
282
332
|
base: {
|