@sylwellsoftware/fray 0.5.0 → 0.7.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 +198 -30
- package/colors/README.md +28 -13
- package/colors/gray/colors.css +54 -26
- package/colors/green/colors.css +54 -26
- package/colors/iceblue/colors.css +54 -26
- package/colors/ocean/colors.css +54 -26
- package/colors/orange/colors.css +54 -26
- package/colors/purple/colors.css +54 -26
- package/colors/red/colors.css +54 -26
- package/colors/yellow/colors.css +54 -26
- package/dist/Components/component.d.ts.map +1 -1
- package/dist/Components/data/descriptionList.d.ts.map +1 -1
- package/dist/Components/data/listview/listview.d.ts.map +1 -1
- package/dist/Components/data/table/DataTable.d.ts.map +1 -1
- package/dist/Components/data/table/FilterPanel.d.ts.map +1 -1
- package/dist/Components/data/table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Components/data/treeview/treeview.d.ts.map +1 -1
- package/dist/Components/dialog/dialog.d.ts.map +1 -1
- package/dist/Components/layout/panel.d.ts +0 -1
- package/dist/Components/layout/panel.d.ts.map +1 -1
- package/dist/Components/layout/sidebar.d.ts +0 -1
- package/dist/Components/layout/sidebar.d.ts.map +1 -1
- package/dist/Components/layout/tabpanel/tab.d.ts +2 -0
- package/dist/Components/layout/tabpanel/tab.d.ts.map +1 -1
- package/dist/Components/layout/tabpanel/tabline.d.ts.map +1 -1
- package/dist/Components/layout/tabpanel/tabpanel.d.ts +9 -1
- package/dist/Components/layout/tabpanel/tabpanel.d.ts.map +1 -1
- package/dist/Components/lineinputs/checkbox/Checkbox.d.ts +0 -1
- package/dist/Components/lineinputs/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/Components/lineinputs/dropdown.d.ts.map +1 -1
- package/dist/Components/lineinputs/radio.d.ts +51 -0
- package/dist/Components/lineinputs/radio.d.ts.map +1 -0
- package/dist/Components/lineinputs/textbox.d.ts.map +1 -1
- package/dist/Components/lineinputs/toggle.d.ts.map +1 -1
- package/dist/Components/menu/toolbar.d.ts +0 -1
- package/dist/Components/menu/toolbar.d.ts.map +1 -1
- package/dist/Components/status/progressBar.d.ts.map +1 -1
- package/dist/Components/theme/stylesheetPicker.d.ts.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2485 -1456
- package/dist/index.js.map +1 -1
- package/dist/{jsx-dev-runtime-pzseD2Sz.js → jsx-dev-runtime-Kf1Dhu-y.js} +412 -469
- package/dist/jsx-dev-runtime-Kf1Dhu-y.js.map +1 -0
- package/dist/jsx-dev-runtime.js +1 -1
- package/dist/jsx-runtime.js +1 -1
- package/dist/routing/RouteLink.d.ts +17 -0
- package/dist/routing/RouteLink.d.ts.map +1 -0
- package/dist/routing/RouteQuery.d.ts +18 -0
- package/dist/routing/RouteQuery.d.ts.map +1 -0
- package/dist/routing/RouteScope.d.ts +17 -0
- package/dist/routing/RouteScope.d.ts.map +1 -0
- package/dist/routing/RouteValue.d.ts +18 -0
- package/dist/routing/RouteValue.d.ts.map +1 -0
- package/dist/routing/navigationAdapter.d.ts +33 -0
- package/dist/routing/navigationAdapter.d.ts.map +1 -0
- package/dist/routing/route.d.ts +64 -0
- package/dist/routing/route.d.ts.map +1 -0
- package/dist/routing/router.d.ts +109 -0
- package/dist/routing/router.d.ts.map +1 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/styling/baseStyleDefinitions.d.ts +0 -82
- package/dist/styling/baseStyleDefinitions.d.ts.map +1 -1
- package/dist/styling/theme.d.ts +3 -3
- package/dist/styling/theme.d.ts.map +1 -1
- package/package.json +3 -3
- package/styles/structural.css +220 -429
- package/themes/README.md +68 -66
- package/themes/dark.css +60 -1
- package/themes/java/theme.css +422 -135
- package/themes/light.css +60 -1
- package/themes/minimal/theme.css +420 -125
- package/themes/shiny/theme.css +492 -294
- package/dist/jsx-dev-runtime-pzseD2Sz.js.map +0 -1
package/README.md
CHANGED
|
@@ -85,7 +85,8 @@ Responsibility stays at the narrowest layer that understands it:
|
|
|
85
85
|
| Domain state, service implementations/providers, endpoint configuration, page composition, theme availability and selection policy | Application |
|
|
86
86
|
| DOM structure, native events, accessibility, component lifetime, service-scope propagation, visual async states | Fray components/runtime |
|
|
87
87
|
| Mutable/computed values, query timing/results, fetch state, optional causality | Glue |
|
|
88
|
-
|
|
|
88
|
+
| Remote wire serialization and retrieval mechanism | Injected Glue query handler/application adapter |
|
|
89
|
+
| Browser navigation placement, restoration, and routed component integration | Caller-owned Fray router with an injected navigation adapter |
|
|
89
90
|
| Layout/flow CSS and stable component/part hooks | Fray structural styling |
|
|
90
91
|
| Look-and-feel treatment and palette | Separately loaded Fray-compatible theme/color CSS |
|
|
91
92
|
|
|
@@ -214,6 +215,164 @@ query state comes from caller-owned endpoint results. Function components stay
|
|
|
214
215
|
presentation-oriented and receive rendered values or emitters from a nearby
|
|
215
216
|
lifecycle-owning class component.
|
|
216
217
|
|
|
218
|
+
## Hierarchical browser routing
|
|
219
|
+
|
|
220
|
+
Routing is optional and application-scoped. Route descriptors name immutable
|
|
221
|
+
relative segments; the mounted component hierarchy supplies their parentage.
|
|
222
|
+
This lets a `TabPanel` discover immediate routes from ordinary `Tab`
|
|
223
|
+
annotations without requiring a duplicate central route tree:
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
import {Emitter} from '@sylwellsoftware/glue'
|
|
227
|
+
import {
|
|
228
|
+
Component,
|
|
229
|
+
RouteLink,
|
|
230
|
+
RouteQuery,
|
|
231
|
+
RouteUnavailableError,
|
|
232
|
+
RouteValue,
|
|
233
|
+
Tab,
|
|
234
|
+
TabPanel,
|
|
235
|
+
createBrowserRouter,
|
|
236
|
+
createHashNavigation,
|
|
237
|
+
createFrayRuntime,
|
|
238
|
+
defineRoute,
|
|
239
|
+
defineRouteParameter,
|
|
240
|
+
routeTarget,
|
|
241
|
+
stringRouteCodec,
|
|
242
|
+
waitForRouteValue,
|
|
243
|
+
} from '@sylwellsoftware/fray'
|
|
244
|
+
|
|
245
|
+
const routes = {
|
|
246
|
+
changes: defineRoute('changes'),
|
|
247
|
+
security: defineRoute('security'),
|
|
248
|
+
overview: defineRoute('security-overview', 'overview'),
|
|
249
|
+
projects: defineRoute('security-projects', 'projects'),
|
|
250
|
+
}
|
|
251
|
+
const activeApplication = new Emitter('changes')
|
|
252
|
+
const activeSecurityView = new Emitter('overview')
|
|
253
|
+
|
|
254
|
+
class SecurityApplication extends Component {
|
|
255
|
+
render() {
|
|
256
|
+
return <TabPanel valueEmitter={activeSecurityView} label="Security views">
|
|
257
|
+
<Tab id="overview" label="Overview" route={routes.overview}>Summary</Tab>
|
|
258
|
+
<Tab id="projects" label="Projects" route={routes.projects}>Projects</Tab>
|
|
259
|
+
</TabPanel>
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
static dependencies = [Tab, TabPanel]
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
class App extends Component {
|
|
266
|
+
render() {
|
|
267
|
+
return <>
|
|
268
|
+
<nav aria-label="Applications">
|
|
269
|
+
<RouteLink to={routeTarget(routes.security, routes.projects)}>
|
|
270
|
+
Security projects
|
|
271
|
+
</RouteLink>
|
|
272
|
+
</nav>
|
|
273
|
+
<TabPanel valueEmitter={activeApplication} label="Applications">
|
|
274
|
+
<Tab id="changes" label="Changes" route={routes.changes}>Changes</Tab>
|
|
275
|
+
<Tab id="security" label="Security" route={routes.security}>
|
|
276
|
+
<SecurityApplication />
|
|
277
|
+
</Tab>
|
|
278
|
+
</TabPanel>
|
|
279
|
+
</>
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
static dependencies = [RouteLink, SecurityApplication, Tab, TabPanel]
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const router = createBrowserRouter({adapter: createHashNavigation(window)})
|
|
286
|
+
const runtime = createFrayRuntime({router})
|
|
287
|
+
const app = runtime.mount(runtime.create(App), document.querySelector('#app')!)
|
|
288
|
+
|
|
289
|
+
addEventListener('pagehide', () => {
|
|
290
|
+
app.destroy()
|
|
291
|
+
router.dispose()
|
|
292
|
+
}, {once: true})
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
The runtime opens the root scope. A selected routed tab opens its own scope for
|
|
296
|
+
nested components, so `/security/projects` restores the outer tab first and
|
|
297
|
+
then discovers and restores the inner tab. Every scope declares when its
|
|
298
|
+
immediate registrations are complete; this distinguishes an unknown child
|
|
299
|
+
from one whose parent has not mounted yet. Duplicate IDs or literal paths and
|
|
300
|
+
multiple parameter routes in one scope fail at completion. Literal routes take
|
|
301
|
+
precedence over the optional parameter route.
|
|
302
|
+
|
|
303
|
+
`RouteLink` is a native anchor. A descriptor resolves against the current
|
|
304
|
+
lineage, which is convenient for sibling destinations. A link outside the
|
|
305
|
+
destination's mounted lineage uses `routeTarget(...)` with the full chain from
|
|
306
|
+
the root. Modified clicks, downloads, and non-`_self` targets retain native
|
|
307
|
+
browser behavior. `router.navigate(target)` pushes by default;
|
|
308
|
+
`router.redirect(target)` and `navigate(target, {history: 'replace'})` replace.
|
|
309
|
+
`router.href(target)`, `router.resolve(descriptor, context)`, and
|
|
310
|
+
`router.isActive(target, exact)` support advanced composition.
|
|
311
|
+
|
|
312
|
+
Dynamic path values use a typed codec and an application-owned nullable
|
|
313
|
+
emitter:
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
const projectRoute = defineRouteParameter('project', stringRouteCodec, 'project-id')
|
|
317
|
+
const selectedProjectId = new Emitter<string | null>(null)
|
|
318
|
+
|
|
319
|
+
<RouteValue
|
|
320
|
+
route={projectRoute}
|
|
321
|
+
valueEmitter={selectedProjectId}
|
|
322
|
+
resolve={async (projectId, _context, signal) => {
|
|
323
|
+
const projects = await waitForRouteValue(
|
|
324
|
+
projectResults,
|
|
325
|
+
(items) => items.length > 0,
|
|
326
|
+
signal,
|
|
327
|
+
)
|
|
328
|
+
if (!projects.some(({id}) => id === projectId)) {
|
|
329
|
+
throw new RouteUnavailableError(`Unknown project "${projectId}"`)
|
|
330
|
+
}
|
|
331
|
+
return projectId
|
|
332
|
+
}}
|
|
333
|
+
>
|
|
334
|
+
<ProjectView />
|
|
335
|
+
</RouteValue>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Resolvers run in path order, may normalize the decoded value, and receive the
|
|
339
|
+
settled ancestor values plus an `AbortSignal`. A newer navigation or router
|
|
340
|
+
disposal aborts outstanding work. `waitForRouteValue` is a convenience for a
|
|
341
|
+
Glue readable; fetching, authorization, retries, and domain validation remain
|
|
342
|
+
application-owned. Set `scopeChildren` on `RouteValue` only when further route
|
|
343
|
+
levels live beneath the dynamic value. Leaving it off avoids remounting an
|
|
344
|
+
otherwise stable leaf view when selection changes.
|
|
345
|
+
|
|
346
|
+
Explicit query bindings make selected shareable view state routable without
|
|
347
|
+
coupling the originating control to the router:
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
<RouteQuery
|
|
351
|
+
name="range"
|
|
352
|
+
valueEmitter={historyRange}
|
|
353
|
+
codec={historyRangeCodec}
|
|
354
|
+
defaultValue="12m"
|
|
355
|
+
>
|
|
356
|
+
<HistoryView />
|
|
357
|
+
</RouteQuery>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Defaults are omitted, owned names sort deterministically, foreign query keys
|
|
361
|
+
are preserved, and passive emitter changes replace the current URL. Invalid
|
|
362
|
+
owned values reset to the default and produce a structured `router.issue`.
|
|
363
|
+
Path failures similarly fall back to the deepest resolved parent and replace
|
|
364
|
+
the failed entry. Applications observe `router.transition` for pending/idle
|
|
365
|
+
state and render `router.issue` as localized, accessible feedback. An explicit
|
|
366
|
+
navigation clears the issue.
|
|
367
|
+
|
|
368
|
+
Choose `createHashNavigation(window)` for static hosting; it reserves the URL
|
|
369
|
+
fragment. Choose `createHistoryNavigation(window, {basePath: '/app/'})` for
|
|
370
|
+
ordinary paths; the deployment must serve the application entry point for
|
|
371
|
+
direct requests below that base. `MemoryNavigationAdapter` supplies
|
|
372
|
+
deterministic tests and does not imply server rendering. The application owns
|
|
373
|
+
and disposes the router; destroying a runtime root removes mounted route
|
|
374
|
+
registrations but does not dispose the caller-owned router.
|
|
375
|
+
|
|
217
376
|
## Component host elements
|
|
218
377
|
|
|
219
378
|
Fray components with a wrapper render a standards-valid custom host element,
|
|
@@ -221,7 +380,7 @@ not a framework identity class. The default application runtime therefore
|
|
|
221
380
|
produces DOM such as:
|
|
222
381
|
|
|
223
382
|
```html
|
|
224
|
-
<fray-panel data-fray-component="panel">
|
|
383
|
+
<fray-panel class="panellike" data-fray-component="panel">
|
|
225
384
|
<fray-textbox data-fray-component="textbox">
|
|
226
385
|
<input type="text">
|
|
227
386
|
</fray-textbox>
|
|
@@ -233,8 +392,10 @@ Native semantics remain native: `Button` renders `button`, `Toggle` renders
|
|
|
233
392
|
`fieldset`, `Sidebar` renders `aside`, and table header components render
|
|
234
393
|
`thead`/`th`. `Tab` is a declarative child consumed by `TabPanel` and has no
|
|
235
394
|
independent root. The
|
|
236
|
-
`data-fray-component`
|
|
237
|
-
|
|
395
|
+
`data-fray-component` keeps diagnostics unambiguous. It is not a structural or
|
|
396
|
+
theme selector. Fray may merge public presentation traits such as `panellike`
|
|
397
|
+
with an application-supplied `class`/`className`; those traits describe a
|
|
398
|
+
reusable capability, not component identity.
|
|
238
399
|
|
|
239
400
|
Element naming is an immutable application-runtime setting:
|
|
240
401
|
|
|
@@ -538,6 +699,8 @@ sibling-local `key` through the common component props.
|
|
|
538
699
|
| `Toolbar` | `label`, `orientation`, `id`, `children` | None | Stateless named toolbar; orientation is horizontal or vertical. |
|
|
539
700
|
| `Textbox` | `label` or `ariaLabel`, value props, `disabled`, `required`, `readOnly`, `error`, native text constraints, `inputRef` | `onInput(value, event)`, `onChange(value, event)` | String `valueEmitter`; external emitter changes patch the native input without replacing it. |
|
|
540
701
|
| `Dropdown<T>` | `options`, `label` or `ariaLabel`, value props, `disabled`, `required`, `error`, `placeholder`, `name` | `onChange(value, event)` | Typed string/number `valueEmitter`; `options` may be an array or readable emitter. |
|
|
702
|
+
| `RadioButton` | `label`, `name`, `value`, `checked`, `disabled`, `required` | `onChange(checked, event)` | Native radio input with a label; use a shared `name` to associate standalone buttons. |
|
|
703
|
+
| `RadioGroup<T>` | `options`, `label` or `ariaLabel`, value props, `name`, `disabled`, `required` | `onChange(value, event)` | Native radio inputs with one selected `valueEmitter` option. |
|
|
541
704
|
| `Toggle<T>` | `options`, `label` or `ariaLabel`, value props, `disabled`, `required` | `onChange(value, event)` | One selected value; arrow keys, Home, and End move and select within the radio group. |
|
|
542
705
|
| `Checkbox<T>` | `symbols`, `label`, value props, `disabled`, `required`, `name` | `onChange(value, event)` | Two-state semantic value by default; click/Space advances and arrow keys move in either direction. |
|
|
543
706
|
| `TriCheckbox` | Checkbox props except `symbols` | `onChange(value, event)` | Cycles deny → neutral → prefer using `FilterMode`. |
|
|
@@ -549,9 +712,9 @@ sibling-local `key` through the common component props.
|
|
|
549
712
|
| `ProgressBar` | `label`, `value` or `valueEmitter`, `max`, `valueText` | None | Labelled native progress; a null value is indeterminate. |
|
|
550
713
|
| `ThemePicker` | `label` or `ariaLabel`, theme `options`, value props, `targetDocument`, `disabled` | `onChange(value, option, event)` | String `valueEmitter`; replaces only the theme stylesheet link. |
|
|
551
714
|
| `ColorPicker` | `label` or `ariaLabel`, color `options`, value props, `targetDocument`, `disabled` | `onChange(value, option, event)` | String `valueEmitter`; replaces only the color stylesheet link. |
|
|
552
|
-
| `Tab` | `id`, `label`, `disabled`, `children` | None | Declarative content marker consumed by `TabPanel`;
|
|
715
|
+
| `Tab` | `id`, `label`, `disabled`, optional literal `route`, `children` | None | Declarative content marker consumed by `TabPanel`; a route annotation binds tab activation to the current route scope. |
|
|
553
716
|
| `TabLine` | `tabs`, `label`, `baseId`, value props | `onChange(id, event)` | Active-tab `valueEmitter`; arrow keys skip disabled tabs, with Home/End support. |
|
|
554
|
-
| `TabPanel` | `tabs` or `Tab` children, `label`, `id`, value props | `onChange(id, event)` | Owns or consumes the active-tab emitter
|
|
717
|
+
| `TabPanel` | `tabs` or `Tab` children, `label`, `id`, value props | `onChange(id, event)` | Owns or consumes the active-tab emitter, wires the selected tabpanel, and contextually registers annotated tabs when a router is present. |
|
|
555
718
|
|
|
556
719
|
Invalid option arrays, duplicate tab IDs, unsupported orientations, malformed
|
|
557
720
|
emitters, and non-function callbacks fail with descriptive errors.
|
|
@@ -680,7 +843,7 @@ Fray's styling system has three physically and conceptually separate layers:
|
|
|
680
843
|
| --- | --- | --- | --- |
|
|
681
844
|
| Structure | `styles/structural.css` | Generated component layout, flow, sizing, positioning, accessibility mechanics, stable hooks, and variable consumption | Loaded once; remains stable during presentation changes |
|
|
682
845
|
| Theme | `themes/<name>/theme.css` | Typography, spacing, geometry, depth, surface treatment, semantic family mappings, and exceptional pseudo/native rendering | Loaded separately and independently replaceable |
|
|
683
|
-
| Colors | `colors/<name>/colors.css` |
|
|
846
|
+
| Colors | `colors/<name>/colors.css` | Primary, secondary, and neutral ramps plus contrast/color primitives; no UI-semantic roles | Loaded separately and independently replaceable |
|
|
684
847
|
|
|
685
848
|
Component authors place only structure and mechanics in `static css`: display,
|
|
686
849
|
flow, sizing, positioning, overflow, stable state hooks, and consumption of
|
|
@@ -708,7 +871,7 @@ CSS custom properties are Fray's primary theme integration protocol:
|
|
|
708
871
|
|
|
709
872
|
```text
|
|
710
873
|
colors.css
|
|
711
|
-
--
|
|
874
|
+
--palette-primary-* / --palette-secondary-* / --palette-neutral-*
|
|
712
875
|
│
|
|
713
876
|
▼
|
|
714
877
|
theme.css
|
|
@@ -732,39 +895,44 @@ that should look different. `frayThemeVariableCatalog` exports this contract in
|
|
|
732
895
|
machine-readable form, including every variable's layer, family, value kind,
|
|
733
896
|
purpose, and optional fallback.
|
|
734
897
|
|
|
735
|
-
A custom component
|
|
736
|
-
|
|
898
|
+
A custom component can apply the public trait matching the treatment it needs
|
|
899
|
+
and optionally consume the same variable hierarchy:
|
|
737
900
|
|
|
738
901
|
```css
|
|
739
|
-
acme-grid > header {
|
|
740
|
-
color: var(
|
|
741
|
-
|
|
742
|
-
var(--fray-table-header-color, var(--fray-header-color))
|
|
743
|
-
);
|
|
744
|
-
background: var(
|
|
745
|
-
--acme-grid-header-background,
|
|
746
|
-
var(--fray-table-header-background, var(--fray-header-background))
|
|
747
|
-
);
|
|
902
|
+
acme-grid.datacomponentlike > header {
|
|
903
|
+
color: var(--table-header-color, var(--header-color));
|
|
904
|
+
background: var(--table-header-background, var(--header-background));
|
|
748
905
|
}
|
|
749
906
|
```
|
|
750
907
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
`
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
908
|
+
Complete traits use the `like` suffix. A component whose outer and content
|
|
909
|
+
regions are distinct uses `shell` and `inner`, for example `buttonshell` with
|
|
910
|
+
`buttoninner`, or `datacomponentshell` with `datacomponentinner`. Other public
|
|
911
|
+
families include `inputlike`, `headerlike`, `coloredlike`, `panellike`, and
|
|
912
|
+
`toolbarlike`; the panel and toolbar families also expose
|
|
913
|
+
`panelshell`/`panelinner` and `toolbarshell`/`toolbarinner`. Wrappers are not
|
|
914
|
+
introduced solely to carry a split trait.
|
|
915
|
+
|
|
916
|
+
Themes directly target native elements, public traits, native pseudo-parts,
|
|
917
|
+
and native/ARIA state. They never target `data-fray-component` or `data-part`.
|
|
918
|
+
Every theme seeds inherited variables with a zero-specificity
|
|
919
|
+
`:root`/`[data-theme]` boundary rule. Presentation selectors use `@scope` with
|
|
920
|
+
nested theme roots and `[data-theme-exclude]` limits, a named cascade layer,
|
|
921
|
+
and low-specificity `:where()` selectors. Shiny's highlights and
|
|
922
|
+
select/progress decoration follow that contract and yield to native
|
|
923
|
+
representation under forced colors.
|
|
924
|
+
|
|
925
|
+
`coloredlike` defaults to the primary palette. Components can provide
|
|
926
|
+
`--colored-base`, `--colored-light`, `--colored-dark`, and
|
|
927
|
+
`--colored-contrast`; the active theme decides whether those inputs become a
|
|
928
|
+
flat color, gradient, other polish, or no special treatment.
|
|
761
929
|
|
|
762
930
|
### Runtime selection
|
|
763
931
|
|
|
764
932
|
`replaceFrayStylesheet` maintains one
|
|
765
933
|
`link[data-fray-stylesheet="theme"]` and one
|
|
766
934
|
`link[data-fray-stylesheet="colors"]`. Replacing either link also sets the
|
|
767
|
-
corresponding `data-
|
|
935
|
+
corresponding `data-theme` or `data-color` root attribute. The
|
|
768
936
|
`ThemePicker` and `ColorPicker` controls expose the same operation through the
|
|
769
937
|
normal Fray value-control contract.
|
|
770
938
|
|
package/colors/README.md
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
# Fray color palettes
|
|
2
2
|
|
|
3
|
-
Each `<name>/colors.css` file defines
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
Each `<name>/colors.css` file defines a replaceable, prefix-free color
|
|
4
|
+
language. It contains palette values only; it does not decide what a panel,
|
|
5
|
+
button, input, selection, or application surface looks like.
|
|
6
|
+
|
|
7
|
+
Every palette supplies three complete ramps:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
--palette-primary-{50,100,200,300,400,500,600,700,800,900,950}
|
|
11
|
+
--palette-secondary-{50,100,200,300,400,500,600,700,800,900,950}
|
|
12
|
+
--palette-neutral-{50,100,200,300,400,500,600,700,800,900,950}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
It also supplies `--palette-<family>`, `--palette-<family>-light`, and
|
|
16
|
+
`--palette-<family>-dark` aliases; `--palette-light`, `--palette-dark`,
|
|
17
|
+
`--palette-contrast-light`, and `--palette-contrast-dark`; and named hue
|
|
18
|
+
primitives such as `--palette-red` and `--palette-green`. Additional numeric
|
|
19
|
+
stops may be added without changing the existing contract.
|
|
20
|
+
|
|
21
|
+
Themes map these values to semantic variables. For example, a theme may map a
|
|
22
|
+
light-mode button to `--palette-neutral-100`, a selected item to
|
|
23
|
+
`--palette-primary-600`, and an error to `--palette-red`. A different theme can
|
|
24
|
+
use the same palette in entirely different places.
|
|
25
|
+
|
|
26
|
+
Palette declarations use a zero-specificity boundary selector for `:root` or
|
|
27
|
+
the matching `[data-color]` root. They select no descendants; the custom
|
|
28
|
+
properties propagate through normal inheritance and a nested color root seeds
|
|
29
|
+
its own palette. `frayThemeVariableCatalog` entries whose `layer` is `palette`
|
|
30
|
+
expose the machine-readable required vocabulary.
|
package/colors/gray/colors.css
CHANGED
|
@@ -1,29 +1,57 @@
|
|
|
1
1
|
@charset "utf-8";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
3
|
+
@layer palette {
|
|
4
|
+
:where(:root:not([data-color]), [data-color="gray"]) {
|
|
5
|
+
--palette-light: #ffffff;
|
|
6
|
+
--palette-dark: #111827;
|
|
7
|
+
--palette-contrast-light: var(--palette-light);
|
|
8
|
+
--palette-contrast-dark: var(--palette-dark);
|
|
9
|
+
--palette-red: #b3261e;
|
|
10
|
+
--palette-green: #287a3c;
|
|
11
|
+
|
|
12
|
+
--palette-primary-500: #5d6873;
|
|
13
|
+
--palette-primary-50: color-mix(in oklch, var(--palette-primary-500) 8%, var(--palette-light));
|
|
14
|
+
--palette-primary-100: color-mix(in oklch, var(--palette-primary-500) 16%, var(--palette-light));
|
|
15
|
+
--palette-primary-200: color-mix(in oklch, var(--palette-primary-500) 32%, var(--palette-light));
|
|
16
|
+
--palette-primary-300: color-mix(in oklch, var(--palette-primary-500) 50%, var(--palette-light));
|
|
17
|
+
--palette-primary-400: color-mix(in oklch, var(--palette-primary-500) 72%, var(--palette-light));
|
|
18
|
+
--palette-primary-600: color-mix(in oklch, var(--palette-primary-500) 85%, var(--palette-dark));
|
|
19
|
+
--palette-primary-700: color-mix(in oklch, var(--palette-primary-500) 72%, var(--palette-dark));
|
|
20
|
+
--palette-primary-800: color-mix(in oklch, var(--palette-primary-500) 58%, var(--palette-dark));
|
|
21
|
+
--palette-primary-900: color-mix(in oklch, var(--palette-primary-500) 42%, var(--palette-dark));
|
|
22
|
+
--palette-primary-950: color-mix(in oklch, var(--palette-primary-500) 28%, var(--palette-dark));
|
|
23
|
+
--palette-primary: var(--palette-primary-500);
|
|
24
|
+
--palette-primary-light: var(--palette-primary-200);
|
|
25
|
+
--palette-primary-dark: var(--palette-primary-800);
|
|
26
|
+
|
|
27
|
+
--palette-secondary-500: #1769aa;
|
|
28
|
+
--palette-secondary-50: color-mix(in oklch, var(--palette-secondary-500) 8%, var(--palette-light));
|
|
29
|
+
--palette-secondary-100: color-mix(in oklch, var(--palette-secondary-500) 16%, var(--palette-light));
|
|
30
|
+
--palette-secondary-200: color-mix(in oklch, var(--palette-secondary-500) 32%, var(--palette-light));
|
|
31
|
+
--palette-secondary-300: color-mix(in oklch, var(--palette-secondary-500) 50%, var(--palette-light));
|
|
32
|
+
--palette-secondary-400: color-mix(in oklch, var(--palette-secondary-500) 72%, var(--palette-light));
|
|
33
|
+
--palette-secondary-600: color-mix(in oklch, var(--palette-secondary-500) 85%, var(--palette-dark));
|
|
34
|
+
--palette-secondary-700: color-mix(in oklch, var(--palette-secondary-500) 72%, var(--palette-dark));
|
|
35
|
+
--palette-secondary-800: color-mix(in oklch, var(--palette-secondary-500) 58%, var(--palette-dark));
|
|
36
|
+
--palette-secondary-900: color-mix(in oklch, var(--palette-secondary-500) 42%, var(--palette-dark));
|
|
37
|
+
--palette-secondary-950: color-mix(in oklch, var(--palette-secondary-500) 28%, var(--palette-dark));
|
|
38
|
+
--palette-secondary: var(--palette-secondary-500);
|
|
39
|
+
--palette-secondary-light: var(--palette-secondary-200);
|
|
40
|
+
--palette-secondary-dark: var(--palette-secondary-800);
|
|
41
|
+
|
|
42
|
+
--palette-neutral-500: #858d95;
|
|
43
|
+
--palette-neutral-50: color-mix(in oklch, var(--palette-neutral-500) 6%, var(--palette-light));
|
|
44
|
+
--palette-neutral-100: color-mix(in oklch, var(--palette-neutral-500) 13%, var(--palette-light));
|
|
45
|
+
--palette-neutral-200: color-mix(in oklch, var(--palette-neutral-500) 26%, var(--palette-light));
|
|
46
|
+
--palette-neutral-300: color-mix(in oklch, var(--palette-neutral-500) 43%, var(--palette-light));
|
|
47
|
+
--palette-neutral-400: color-mix(in oklch, var(--palette-neutral-500) 68%, var(--palette-light));
|
|
48
|
+
--palette-neutral-600: color-mix(in oklch, var(--palette-neutral-500) 84%, var(--palette-dark));
|
|
49
|
+
--palette-neutral-700: color-mix(in oklch, var(--palette-neutral-500) 67%, var(--palette-dark));
|
|
50
|
+
--palette-neutral-800: color-mix(in oklch, var(--palette-neutral-500) 50%, var(--palette-dark));
|
|
51
|
+
--palette-neutral-900: color-mix(in oklch, var(--palette-neutral-500) 32%, var(--palette-dark));
|
|
52
|
+
--palette-neutral-950: color-mix(in oklch, var(--palette-neutral-500) 18%, var(--palette-dark));
|
|
53
|
+
--palette-neutral: var(--palette-neutral-500);
|
|
54
|
+
--palette-neutral-light: var(--palette-neutral-200);
|
|
55
|
+
--palette-neutral-dark: var(--palette-neutral-800);
|
|
56
|
+
}
|
|
29
57
|
}
|
package/colors/green/colors.css
CHANGED
|
@@ -1,29 +1,57 @@
|
|
|
1
1
|
@charset "utf-8";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
3
|
+
@layer palette {
|
|
4
|
+
:where(:root:not([data-color]), [data-color="green"]) {
|
|
5
|
+
--palette-light: #ffffff;
|
|
6
|
+
--palette-dark: #111827;
|
|
7
|
+
--palette-contrast-light: var(--palette-light);
|
|
8
|
+
--palette-contrast-dark: var(--palette-dark);
|
|
9
|
+
--palette-red: #b3261e;
|
|
10
|
+
--palette-green: #287a3c;
|
|
11
|
+
|
|
12
|
+
--palette-primary-500: #287a3c;
|
|
13
|
+
--palette-primary-50: color-mix(in oklch, var(--palette-primary-500) 8%, var(--palette-light));
|
|
14
|
+
--palette-primary-100: color-mix(in oklch, var(--palette-primary-500) 16%, var(--palette-light));
|
|
15
|
+
--palette-primary-200: color-mix(in oklch, var(--palette-primary-500) 32%, var(--palette-light));
|
|
16
|
+
--palette-primary-300: color-mix(in oklch, var(--palette-primary-500) 50%, var(--palette-light));
|
|
17
|
+
--palette-primary-400: color-mix(in oklch, var(--palette-primary-500) 72%, var(--palette-light));
|
|
18
|
+
--palette-primary-600: color-mix(in oklch, var(--palette-primary-500) 85%, var(--palette-dark));
|
|
19
|
+
--palette-primary-700: color-mix(in oklch, var(--palette-primary-500) 72%, var(--palette-dark));
|
|
20
|
+
--palette-primary-800: color-mix(in oklch, var(--palette-primary-500) 58%, var(--palette-dark));
|
|
21
|
+
--palette-primary-900: color-mix(in oklch, var(--palette-primary-500) 42%, var(--palette-dark));
|
|
22
|
+
--palette-primary-950: color-mix(in oklch, var(--palette-primary-500) 28%, var(--palette-dark));
|
|
23
|
+
--palette-primary: var(--palette-primary-500);
|
|
24
|
+
--palette-primary-light: var(--palette-primary-200);
|
|
25
|
+
--palette-primary-dark: var(--palette-primary-800);
|
|
26
|
+
|
|
27
|
+
--palette-secondary-500: #087f78;
|
|
28
|
+
--palette-secondary-50: color-mix(in oklch, var(--palette-secondary-500) 8%, var(--palette-light));
|
|
29
|
+
--palette-secondary-100: color-mix(in oklch, var(--palette-secondary-500) 16%, var(--palette-light));
|
|
30
|
+
--palette-secondary-200: color-mix(in oklch, var(--palette-secondary-500) 32%, var(--palette-light));
|
|
31
|
+
--palette-secondary-300: color-mix(in oklch, var(--palette-secondary-500) 50%, var(--palette-light));
|
|
32
|
+
--palette-secondary-400: color-mix(in oklch, var(--palette-secondary-500) 72%, var(--palette-light));
|
|
33
|
+
--palette-secondary-600: color-mix(in oklch, var(--palette-secondary-500) 85%, var(--palette-dark));
|
|
34
|
+
--palette-secondary-700: color-mix(in oklch, var(--palette-secondary-500) 72%, var(--palette-dark));
|
|
35
|
+
--palette-secondary-800: color-mix(in oklch, var(--palette-secondary-500) 58%, var(--palette-dark));
|
|
36
|
+
--palette-secondary-900: color-mix(in oklch, var(--palette-secondary-500) 42%, var(--palette-dark));
|
|
37
|
+
--palette-secondary-950: color-mix(in oklch, var(--palette-secondary-500) 28%, var(--palette-dark));
|
|
38
|
+
--palette-secondary: var(--palette-secondary-500);
|
|
39
|
+
--palette-secondary-light: var(--palette-secondary-200);
|
|
40
|
+
--palette-secondary-dark: var(--palette-secondary-800);
|
|
41
|
+
|
|
42
|
+
--palette-neutral-500: #75947a;
|
|
43
|
+
--palette-neutral-50: color-mix(in oklch, var(--palette-neutral-500) 6%, var(--palette-light));
|
|
44
|
+
--palette-neutral-100: color-mix(in oklch, var(--palette-neutral-500) 13%, var(--palette-light));
|
|
45
|
+
--palette-neutral-200: color-mix(in oklch, var(--palette-neutral-500) 26%, var(--palette-light));
|
|
46
|
+
--palette-neutral-300: color-mix(in oklch, var(--palette-neutral-500) 43%, var(--palette-light));
|
|
47
|
+
--palette-neutral-400: color-mix(in oklch, var(--palette-neutral-500) 68%, var(--palette-light));
|
|
48
|
+
--palette-neutral-600: color-mix(in oklch, var(--palette-neutral-500) 84%, var(--palette-dark));
|
|
49
|
+
--palette-neutral-700: color-mix(in oklch, var(--palette-neutral-500) 67%, var(--palette-dark));
|
|
50
|
+
--palette-neutral-800: color-mix(in oklch, var(--palette-neutral-500) 50%, var(--palette-dark));
|
|
51
|
+
--palette-neutral-900: color-mix(in oklch, var(--palette-neutral-500) 32%, var(--palette-dark));
|
|
52
|
+
--palette-neutral-950: color-mix(in oklch, var(--palette-neutral-500) 18%, var(--palette-dark));
|
|
53
|
+
--palette-neutral: var(--palette-neutral-500);
|
|
54
|
+
--palette-neutral-light: var(--palette-neutral-200);
|
|
55
|
+
--palette-neutral-dark: var(--palette-neutral-800);
|
|
56
|
+
}
|
|
29
57
|
}
|
|
@@ -1,29 +1,57 @@
|
|
|
1
1
|
@charset "utf-8";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
3
|
+
@layer palette {
|
|
4
|
+
:where(:root:not([data-color]), [data-color="iceblue"]) {
|
|
5
|
+
--palette-light: #ffffff;
|
|
6
|
+
--palette-dark: #111827;
|
|
7
|
+
--palette-contrast-light: var(--palette-light);
|
|
8
|
+
--palette-contrast-dark: var(--palette-dark);
|
|
9
|
+
--palette-red: #b3261e;
|
|
10
|
+
--palette-green: #287a3c;
|
|
11
|
+
|
|
12
|
+
--palette-primary-500: #1769aa;
|
|
13
|
+
--palette-primary-50: color-mix(in oklch, var(--palette-primary-500) 8%, var(--palette-light));
|
|
14
|
+
--palette-primary-100: color-mix(in oklch, var(--palette-primary-500) 16%, var(--palette-light));
|
|
15
|
+
--palette-primary-200: color-mix(in oklch, var(--palette-primary-500) 32%, var(--palette-light));
|
|
16
|
+
--palette-primary-300: color-mix(in oklch, var(--palette-primary-500) 50%, var(--palette-light));
|
|
17
|
+
--palette-primary-400: color-mix(in oklch, var(--palette-primary-500) 72%, var(--palette-light));
|
|
18
|
+
--palette-primary-600: color-mix(in oklch, var(--palette-primary-500) 85%, var(--palette-dark));
|
|
19
|
+
--palette-primary-700: color-mix(in oklch, var(--palette-primary-500) 72%, var(--palette-dark));
|
|
20
|
+
--palette-primary-800: color-mix(in oklch, var(--palette-primary-500) 58%, var(--palette-dark));
|
|
21
|
+
--palette-primary-900: color-mix(in oklch, var(--palette-primary-500) 42%, var(--palette-dark));
|
|
22
|
+
--palette-primary-950: color-mix(in oklch, var(--palette-primary-500) 28%, var(--palette-dark));
|
|
23
|
+
--palette-primary: var(--palette-primary-500);
|
|
24
|
+
--palette-primary-light: var(--palette-primary-200);
|
|
25
|
+
--palette-primary-dark: var(--palette-primary-800);
|
|
26
|
+
|
|
27
|
+
--palette-secondary-500: #7137a8;
|
|
28
|
+
--palette-secondary-50: color-mix(in oklch, var(--palette-secondary-500) 8%, var(--palette-light));
|
|
29
|
+
--palette-secondary-100: color-mix(in oklch, var(--palette-secondary-500) 16%, var(--palette-light));
|
|
30
|
+
--palette-secondary-200: color-mix(in oklch, var(--palette-secondary-500) 32%, var(--palette-light));
|
|
31
|
+
--palette-secondary-300: color-mix(in oklch, var(--palette-secondary-500) 50%, var(--palette-light));
|
|
32
|
+
--palette-secondary-400: color-mix(in oklch, var(--palette-secondary-500) 72%, var(--palette-light));
|
|
33
|
+
--palette-secondary-600: color-mix(in oklch, var(--palette-secondary-500) 85%, var(--palette-dark));
|
|
34
|
+
--palette-secondary-700: color-mix(in oklch, var(--palette-secondary-500) 72%, var(--palette-dark));
|
|
35
|
+
--palette-secondary-800: color-mix(in oklch, var(--palette-secondary-500) 58%, var(--palette-dark));
|
|
36
|
+
--palette-secondary-900: color-mix(in oklch, var(--palette-secondary-500) 42%, var(--palette-dark));
|
|
37
|
+
--palette-secondary-950: color-mix(in oklch, var(--palette-secondary-500) 28%, var(--palette-dark));
|
|
38
|
+
--palette-secondary: var(--palette-secondary-500);
|
|
39
|
+
--palette-secondary-light: var(--palette-secondary-200);
|
|
40
|
+
--palette-secondary-dark: var(--palette-secondary-800);
|
|
41
|
+
|
|
42
|
+
--palette-neutral-500: #7892aa;
|
|
43
|
+
--palette-neutral-50: color-mix(in oklch, var(--palette-neutral-500) 6%, var(--palette-light));
|
|
44
|
+
--palette-neutral-100: color-mix(in oklch, var(--palette-neutral-500) 13%, var(--palette-light));
|
|
45
|
+
--palette-neutral-200: color-mix(in oklch, var(--palette-neutral-500) 26%, var(--palette-light));
|
|
46
|
+
--palette-neutral-300: color-mix(in oklch, var(--palette-neutral-500) 43%, var(--palette-light));
|
|
47
|
+
--palette-neutral-400: color-mix(in oklch, var(--palette-neutral-500) 68%, var(--palette-light));
|
|
48
|
+
--palette-neutral-600: color-mix(in oklch, var(--palette-neutral-500) 84%, var(--palette-dark));
|
|
49
|
+
--palette-neutral-700: color-mix(in oklch, var(--palette-neutral-500) 67%, var(--palette-dark));
|
|
50
|
+
--palette-neutral-800: color-mix(in oklch, var(--palette-neutral-500) 50%, var(--palette-dark));
|
|
51
|
+
--palette-neutral-900: color-mix(in oklch, var(--palette-neutral-500) 32%, var(--palette-dark));
|
|
52
|
+
--palette-neutral-950: color-mix(in oklch, var(--palette-neutral-500) 18%, var(--palette-dark));
|
|
53
|
+
--palette-neutral: var(--palette-neutral-500);
|
|
54
|
+
--palette-neutral-light: var(--palette-neutral-200);
|
|
55
|
+
--palette-neutral-dark: var(--palette-neutral-800);
|
|
56
|
+
}
|
|
29
57
|
}
|