@wtfalch/design 0.2.0 → 0.3.1
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 +81 -35
- package/dist/components/Brand.d.ts +12 -1
- package/dist/components/Brand.js +15 -3
- package/dist/components/Callout.d.ts +1 -1
- package/dist/components/Callout.js +1 -1
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/Card.js +1 -1
- package/dist/components/DangerZone.js +3 -3
- package/dist/components/Dialog.js +1 -1
- package/dist/components/Empty.d.ts +2 -2
- package/dist/components/Empty.js +2 -2
- package/dist/components/Icon.d.ts +2 -2
- package/dist/components/Icon.js +5 -228
- package/dist/components/Illustration.d.ts +1 -1
- package/dist/components/Illustration.js +2 -3
- package/dist/components/Input.js +1 -1
- package/dist/components/Modal.js +2 -2
- package/dist/components/Toast.js +1 -1
- package/dist/components/Tour.js +2 -2
- package/dist/components/brandMarks.d.ts +40 -1
- package/dist/components/brandMarks.js +14 -19
- package/dist/components/icons.d.ts +37 -0
- package/dist/components/icons.js +253 -0
- package/dist/index.d.ts +56 -46
- package/dist/index.js +44 -35
- package/dist/products/index.d.ts +69 -0
- package/dist/products/index.js +54 -0
- package/dist/products/tf.d.ts +32 -0
- package/dist/products/tf.js +104 -0
- package/dist/products/valet.d.ts +23 -0
- package/dist/products/valet.js +103 -0
- package/dist/tf.css +3362 -0
- package/dist/tf.d.ts +18 -0
- package/dist/tf.js +17 -0
- package/dist/themes/css.d.ts +45 -0
- package/dist/themes/css.js +78 -0
- package/dist/{themes.d.ts → themes/index.d.ts} +11 -13
- package/dist/{themes.js → themes/index.js} +12 -89
- package/dist/tokens.css +17 -0
- package/dist/valet.css +3366 -0
- package/dist/valet.d.ts +18 -0
- package/dist/valet.js +17 -0
- package/package.json +14 -4
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import BrandDefault from '../components/Brand.js';
|
|
3
|
+
import type { BrandName } from '../components/brandMarks.js';
|
|
4
|
+
import { type Theme, type ThemeTokens } from '../themes/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* A product: the layer between the system and a theme.
|
|
7
|
+
*
|
|
8
|
+
* Three layers, each falling back to the one under it. The system is the
|
|
9
|
+
* components, the base values in `tokens.css`, the shared icons and
|
|
10
|
+
* illustrations. The product is its mark and its identity -- the tokens that
|
|
11
|
+
* make it itself under every theme: font, shape, density -- plus the themes it
|
|
12
|
+
* offers and the one it wears until somebody picks. The theme is a palette and
|
|
13
|
+
* a colour scheme, and anything else it deliberately changes.
|
|
14
|
+
*
|
|
15
|
+
* The middle layer is what lets a theme be shared between products. A theme
|
|
16
|
+
* is a sparse map, and what it is sparse *over* decides what a silent token
|
|
17
|
+
* shows: over the base it shows tf, over the product it shows the product.
|
|
18
|
+
* Before this layer valet's two palettes each restated valet's font and
|
|
19
|
+
* corners, because there was nowhere else to put them.
|
|
20
|
+
*
|
|
21
|
+
* A site is one product, so each ships as one entry -- `@wtfalch/design/valet`
|
|
22
|
+
* and `valet.css` -- where `Brand`, `THEMES` and `applyTheme` are the
|
|
23
|
+
* product's. This module is the neutral view of all of them, which is what the
|
|
24
|
+
* gallery reads.
|
|
25
|
+
*/
|
|
26
|
+
export interface Product {
|
|
27
|
+
/** The id: the mark's row in `brandMarks.ts` and the stem of the CSS entry. */
|
|
28
|
+
name: BrandName;
|
|
29
|
+
/** On `:root` in the product's stylesheet, and under every palette when one
|
|
30
|
+
* is applied. Empty for a product the base values already describe. */
|
|
31
|
+
identity: Partial<ThemeTokens>;
|
|
32
|
+
/** Keyed by the id `applyTheme` takes. */
|
|
33
|
+
themes: Record<string, Theme>;
|
|
34
|
+
/** Worn until somebody picks; written on `:root` when no `data-theme` is set. */
|
|
35
|
+
defaultTheme: string;
|
|
36
|
+
}
|
|
37
|
+
/** Every product, by the name of its mark. */
|
|
38
|
+
export declare const PRODUCTS: {
|
|
39
|
+
readonly tf: Product;
|
|
40
|
+
readonly valet: Product;
|
|
41
|
+
};
|
|
42
|
+
/** Declare a product, so a default that is not a theme or a key `applyTheme`
|
|
43
|
+
* would not use is an error where it is written. */
|
|
44
|
+
export declare function defineProduct(product: Product): Product;
|
|
45
|
+
/**
|
|
46
|
+
* A theme as the product wears it: the palette over the identity.
|
|
47
|
+
*
|
|
48
|
+
* An id the product does not offer resolves to the product's default rather
|
|
49
|
+
* than the package's, so a valet setting that remembers a theme valet has
|
|
50
|
+
* since dropped comes up as valet, not as tf.
|
|
51
|
+
*/
|
|
52
|
+
export declare function productTheme(product: Product, theme?: string | Theme): Theme;
|
|
53
|
+
type BrandProps = ComponentProps<typeof BrandDefault>;
|
|
54
|
+
/**
|
|
55
|
+
* The package, as one product.
|
|
56
|
+
*
|
|
57
|
+
* `Brand` defaults to the product's mark and still takes a name. `applyTheme`
|
|
58
|
+
* resolves against the product's themes and writes the identity under the
|
|
59
|
+
* palette, so it holds even where the product's stylesheet is not the one
|
|
60
|
+
* loaded. The product entries are this, exported.
|
|
61
|
+
*/
|
|
62
|
+
export declare function bindProduct(product: Product): {
|
|
63
|
+
product: Product;
|
|
64
|
+
Brand: (props: BrandProps) => import("react").JSX.Element;
|
|
65
|
+
THEMES: Record<string, Theme>;
|
|
66
|
+
DEFAULT_THEME: string;
|
|
67
|
+
applyTheme: (theme?: string | Theme, el?: HTMLElement) => void;
|
|
68
|
+
};
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import BrandDefault from '../components/Brand.js';
|
|
3
|
+
import { applyTheme } from '../themes/index.js';
|
|
4
|
+
import { themeId } from '../themes/css.js';
|
|
5
|
+
import { tf } from './tf.js';
|
|
6
|
+
import { valet } from './valet.js';
|
|
7
|
+
/** Every product, by the name of its mark. */
|
|
8
|
+
export const PRODUCTS = { tf, valet };
|
|
9
|
+
/** Declare a product, so a default that is not a theme or a key `applyTheme`
|
|
10
|
+
* would not use is an error where it is written. */
|
|
11
|
+
export function defineProduct(product) {
|
|
12
|
+
if (!(product.defaultTheme in product.themes)) {
|
|
13
|
+
throw new Error(`product "${product.name}" defaults to "${product.defaultTheme}", which is not one of its themes`);
|
|
14
|
+
}
|
|
15
|
+
for (const [id, theme] of Object.entries(product.themes)) {
|
|
16
|
+
if (themeId(theme) !== id) {
|
|
17
|
+
throw new Error(`theme "${theme.name}" is keyed "${id}", but applyTheme calls it "${themeId(theme)}"`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return product;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A theme as the product wears it: the palette over the identity.
|
|
24
|
+
*
|
|
25
|
+
* An id the product does not offer resolves to the product's default rather
|
|
26
|
+
* than the package's, so a valet setting that remembers a theme valet has
|
|
27
|
+
* since dropped comes up as valet, not as tf.
|
|
28
|
+
*/
|
|
29
|
+
export function productTheme(product, theme = product.defaultTheme) {
|
|
30
|
+
const resolved = typeof theme === 'string'
|
|
31
|
+
? (product.themes[theme] ?? product.themes[product.defaultTheme])
|
|
32
|
+
: theme;
|
|
33
|
+
return { ...resolved, tokens: { ...product.identity, ...resolved.tokens } };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The package, as one product.
|
|
37
|
+
*
|
|
38
|
+
* `Brand` defaults to the product's mark and still takes a name. `applyTheme`
|
|
39
|
+
* resolves against the product's themes and writes the identity under the
|
|
40
|
+
* palette, so it holds even where the product's stylesheet is not the one
|
|
41
|
+
* loaded. The product entries are this, exported.
|
|
42
|
+
*/
|
|
43
|
+
export function bindProduct(product) {
|
|
44
|
+
function Brand(props) {
|
|
45
|
+
return _jsx(BrandDefault, { ...props, name: props.name ?? product.name });
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
product,
|
|
49
|
+
Brand,
|
|
50
|
+
THEMES: product.themes,
|
|
51
|
+
DEFAULT_THEME: product.defaultTheme,
|
|
52
|
+
applyTheme: (theme = product.defaultTheme, el) => applyTheme(productTheme(product, theme), el),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Theme } from '../themes/index.js';
|
|
2
|
+
import type { Product } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* tf's themes: the three the package shipped with, and the ones the gallery
|
|
5
|
+
* was photographed in first.
|
|
6
|
+
*
|
|
7
|
+
* `system` is a theme, not a mode. A `prefers-color-scheme` block that
|
|
8
|
+
* overrides `:root` unconditionally means choosing a dark theme on a
|
|
9
|
+
* light-mode laptop gets silently repainted; that media query is scoped to
|
|
10
|
+
* this theme in `base.css`, so following the OS is a choice among the others
|
|
11
|
+
* rather than a rule above them.
|
|
12
|
+
*/
|
|
13
|
+
export declare const system: Theme;
|
|
14
|
+
export declare const night: Theme;
|
|
15
|
+
export declare const paper: Theme;
|
|
16
|
+
/** Keyed by the name `applyTheme` takes, which is `name` lowercased. */
|
|
17
|
+
export declare const TF_THEMES: {
|
|
18
|
+
readonly system: Theme;
|
|
19
|
+
readonly night: Theme;
|
|
20
|
+
readonly paper: Theme;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* tf, the product.
|
|
24
|
+
*
|
|
25
|
+
* Its identity is empty on purpose: `tokens.css` carries tf's font, shape and
|
|
26
|
+
* density as the base values, so there is nothing to lay over them. `system`
|
|
27
|
+
* is the default because following the OS is the choice a tool open all day
|
|
28
|
+
* should make for you -- and because it is a `prefers-color-scheme` rule
|
|
29
|
+
* rather than a palette, tf's stylesheet writes no default on `:root`; tf sets
|
|
30
|
+
* `data-theme` before the bundle loads, as it always has.
|
|
31
|
+
*/
|
|
32
|
+
export declare const tf: Product;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tf's themes: the three the package shipped with, and the ones the gallery
|
|
3
|
+
* was photographed in first.
|
|
4
|
+
*
|
|
5
|
+
* `system` is a theme, not a mode. A `prefers-color-scheme` block that
|
|
6
|
+
* overrides `:root` unconditionally means choosing a dark theme on a
|
|
7
|
+
* light-mode laptop gets silently repainted; that media query is scoped to
|
|
8
|
+
* this theme in `base.css`, so following the OS is a choice among the others
|
|
9
|
+
* rather than a rule above them.
|
|
10
|
+
*/
|
|
11
|
+
export const system = {
|
|
12
|
+
name: 'System',
|
|
13
|
+
note: 'Follows your OS between light and dark',
|
|
14
|
+
scheme: 'dark',
|
|
15
|
+
// Empty on purpose: this is the one theme that must *not* state a palette,
|
|
16
|
+
// because the `prefers-color-scheme` block is scoped to it and needs the
|
|
17
|
+
// base values to fall through. Its swatch is a special case.
|
|
18
|
+
tokens: {},
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The dark palette, written out rather than inherited.
|
|
22
|
+
*
|
|
23
|
+
* `night` was `tokens: {}` once, "whatever the base is", and that was wrong
|
|
24
|
+
* twice over. It made the theme depend on a file it does not own, and it made
|
|
25
|
+
* its swatch in the picker preview *the theme currently applied*, because an
|
|
26
|
+
* empty map falls back to the live values.
|
|
27
|
+
*/
|
|
28
|
+
const NIGHT = {
|
|
29
|
+
'--bg': '#0f1115',
|
|
30
|
+
'--panel': '#161a21',
|
|
31
|
+
'--panel-2': '#1c222b',
|
|
32
|
+
'--border': '#262d38',
|
|
33
|
+
'--text': '#e6e9ef',
|
|
34
|
+
'--muted': '#8b94a4',
|
|
35
|
+
'--accent': '#5b9dff',
|
|
36
|
+
'--accent-dim': '#2a4877',
|
|
37
|
+
/* No `--on-accent` here on purpose, so it inherits the base near-black.
|
|
38
|
+
Night used to set `#ffffff`, which is 2.72:1 on this accent -- the exact
|
|
39
|
+
pair `tokens.css` records as the reason the token exists at all. The base
|
|
40
|
+
was fixed and the theme carrying the old palette was never revisited, so
|
|
41
|
+
the primary button in the app's fixed dark theme failed the body-text
|
|
42
|
+
minimum by a wide margin for as long as the token had been "fixed".
|
|
43
|
+
`#06181a` on `#5b9dff` is 6.69:1. Found by the contrast scan, which is the
|
|
44
|
+
argument for shipping the measurement rather than the rule. */
|
|
45
|
+
'--app-bg': '#0f1115',
|
|
46
|
+
};
|
|
47
|
+
export const night = {
|
|
48
|
+
name: 'Night',
|
|
49
|
+
note: 'The dark palette, fixed — ignores the OS',
|
|
50
|
+
scheme: 'dark',
|
|
51
|
+
tokens: NIGHT,
|
|
52
|
+
};
|
|
53
|
+
export const paper = {
|
|
54
|
+
name: 'Paper',
|
|
55
|
+
note: 'Light, with shadows that suit it',
|
|
56
|
+
scheme: 'light',
|
|
57
|
+
tokens: {
|
|
58
|
+
'--bg': '#f6f7f9',
|
|
59
|
+
'--panel': '#ffffff',
|
|
60
|
+
'--panel-2': '#f0f2f5',
|
|
61
|
+
'--border': '#e4e8ec',
|
|
62
|
+
'--border-strong': '#8792a1',
|
|
63
|
+
'--text': '#191d23',
|
|
64
|
+
'--muted': '#5d6773',
|
|
65
|
+
'--accent': '#0e7872',
|
|
66
|
+
'--accent-dim': '#7fbdb8',
|
|
67
|
+
'--on-accent': '#ffffff',
|
|
68
|
+
// The base set is tuned for a dark panel. Unoverridden, `--good` was
|
|
69
|
+
// 1.74:1 on white -- a `running` pill nobody could read.
|
|
70
|
+
'--good': '#1c7a4a',
|
|
71
|
+
'--warn': '#8a6216',
|
|
72
|
+
'--bad': '#b3312c',
|
|
73
|
+
// `#2f7fe6` was 3.96:1 on this theme's white panel -- the "information is
|
|
74
|
+
// blue" colour was measured on the dark base when it was added and never
|
|
75
|
+
// on a light one. Found by contrast.test.ts on its first run. This is the
|
|
76
|
+
// lightest step on the same hue that clears 4.5:1 on the panel *and* the
|
|
77
|
+
// page, with room: 5.24 on white, 4.88 on the page.
|
|
78
|
+
'--info': '#216bc9',
|
|
79
|
+
// Black shadows are right on a dark UI and muddy on a light one. This is
|
|
80
|
+
// the whole reason elevation had to become a token.
|
|
81
|
+
'--shadow-1': '0 4px 14px rgba(16, 24, 40, 0.08)',
|
|
82
|
+
'--shadow-2': '0 8px 24px rgba(16, 24, 40, 0.10)',
|
|
83
|
+
'--shadow-3': '0 12px 32px rgba(16, 24, 40, 0.12)',
|
|
84
|
+
'--scrim': 'rgba(16, 24, 40, 0.32)',
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
/** Keyed by the name `applyTheme` takes, which is `name` lowercased. */
|
|
88
|
+
export const TF_THEMES = { system, night, paper };
|
|
89
|
+
/**
|
|
90
|
+
* tf, the product.
|
|
91
|
+
*
|
|
92
|
+
* Its identity is empty on purpose: `tokens.css` carries tf's font, shape and
|
|
93
|
+
* density as the base values, so there is nothing to lay over them. `system`
|
|
94
|
+
* is the default because following the OS is the choice a tool open all day
|
|
95
|
+
* should make for you -- and because it is a `prefers-color-scheme` rule
|
|
96
|
+
* rather than a palette, tf's stylesheet writes no default on `:root`; tf sets
|
|
97
|
+
* `data-theme` before the bundle loads, as it always has.
|
|
98
|
+
*/
|
|
99
|
+
export const tf = {
|
|
100
|
+
name: 'tf',
|
|
101
|
+
identity: {},
|
|
102
|
+
themes: TF_THEMES,
|
|
103
|
+
defaultTheme: 'system',
|
|
104
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Theme, ThemeTokens } from '../themes/index.js';
|
|
2
|
+
import type { Product } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* valet's identity: what it is under every theme.
|
|
5
|
+
*
|
|
6
|
+
* The fonts are named, not shipped. `--font` reads a `--font-sans` variable
|
|
7
|
+
* the app defines with whatever loads its fonts, and falls back to the family
|
|
8
|
+
* by name; the gallery loads both families from `gallery/public/fonts` so the
|
|
9
|
+
* specimens are photographed in them. Sharper corners than the package
|
|
10
|
+
* default, because a console is read in rows and columns and a large radius
|
|
11
|
+
* rounds the grid away.
|
|
12
|
+
*/
|
|
13
|
+
export declare const VALET_IDENTITY: Partial<ThemeTokens>;
|
|
14
|
+
export declare const light: Theme;
|
|
15
|
+
export declare const night: Theme;
|
|
16
|
+
/** Keyed by the name `applyTheme` takes: `name` lowercased, spaces to hyphens. */
|
|
17
|
+
export declare const VALET_THEMES: {
|
|
18
|
+
readonly valet: Theme;
|
|
19
|
+
readonly 'valet-night': Theme;
|
|
20
|
+
};
|
|
21
|
+
/** valet, the product: its badge in `brandMarks.ts`, the identity above, the
|
|
22
|
+
* two palettes, and light until somebody picks. */
|
|
23
|
+
export declare const valet: Product;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* valet's two palettes.
|
|
3
|
+
*
|
|
4
|
+
* One hue that belongs to nothing else. The accent is an indigo, chosen so it
|
|
5
|
+
* sits apart from all four status tones: good is green, warn is amber, bad is
|
|
6
|
+
* red, and info is a cyan rather than a blue so a link and an information pill
|
|
7
|
+
* cannot be confused at a glance. The accent is what a person acts on; the
|
|
8
|
+
* tones are what the system says. They never share a colour.
|
|
9
|
+
*
|
|
10
|
+
* Every colour is measured, not judged: `contrast.test.ts` holds both palettes
|
|
11
|
+
* to the same pairs as tf's.
|
|
12
|
+
*
|
|
13
|
+
* The palettes name colours and nothing else. What makes valet valet under
|
|
14
|
+
* either of them -- the type and the corners -- is the identity below, on
|
|
15
|
+
* `:root` in valet's stylesheet and under every palette `applyTheme` lays on.
|
|
16
|
+
* Both palettes used to restate it, which is the shape that breaks the moment
|
|
17
|
+
* a theme is shared between products: silent on the font, it would have fallen
|
|
18
|
+
* back to tf's.
|
|
19
|
+
*/
|
|
20
|
+
const FONT = 'var(--font-sans, "IBM Plex Sans"), -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
21
|
+
const FONT_MONO = 'var(--font-mono, "JetBrains Mono"), ui-monospace, SFMono-Regular, Menlo, monospace';
|
|
22
|
+
/**
|
|
23
|
+
* valet's identity: what it is under every theme.
|
|
24
|
+
*
|
|
25
|
+
* The fonts are named, not shipped. `--font` reads a `--font-sans` variable
|
|
26
|
+
* the app defines with whatever loads its fonts, and falls back to the family
|
|
27
|
+
* by name; the gallery loads both families from `gallery/public/fonts` so the
|
|
28
|
+
* specimens are photographed in them. Sharper corners than the package
|
|
29
|
+
* default, because a console is read in rows and columns and a large radius
|
|
30
|
+
* rounds the grid away.
|
|
31
|
+
*/
|
|
32
|
+
export const VALET_IDENTITY = {
|
|
33
|
+
'--font': FONT,
|
|
34
|
+
'--font-mono': FONT_MONO,
|
|
35
|
+
'--radius-sm': '2px',
|
|
36
|
+
'--radius': '4px',
|
|
37
|
+
'--radius-md': '6px',
|
|
38
|
+
'--radius-lg': '10px',
|
|
39
|
+
};
|
|
40
|
+
export const light = {
|
|
41
|
+
name: 'valet',
|
|
42
|
+
note: 'Light. Ink on paper, indigo where you act.',
|
|
43
|
+
scheme: 'light',
|
|
44
|
+
tokens: {
|
|
45
|
+
'--bg': '#f4f5f8',
|
|
46
|
+
'--panel': '#ffffff',
|
|
47
|
+
'--panel-2': '#eceef3',
|
|
48
|
+
'--border': '#dcdfe7',
|
|
49
|
+
'--border-strong': '#7b8597',
|
|
50
|
+
'--text': '#171a21',
|
|
51
|
+
'--muted': '#5b6474',
|
|
52
|
+
'--accent': '#4f46e5',
|
|
53
|
+
'--accent-dim': '#a9a4f0',
|
|
54
|
+
'--on-accent': '#ffffff',
|
|
55
|
+
'--good': '#1b7f4b',
|
|
56
|
+
'--warn': '#8a5f0a',
|
|
57
|
+
'--bad': '#bf3a31',
|
|
58
|
+
'--info': '#0e6f8e',
|
|
59
|
+
'--app-bg': '#f4f5f8',
|
|
60
|
+
// Black shadows muddy a light surface; these carry the page's own ink.
|
|
61
|
+
'--shadow-1': '0 4px 14px rgba(23, 26, 33, 0.08)',
|
|
62
|
+
'--shadow-2': '0 8px 24px rgba(23, 26, 33, 0.10)',
|
|
63
|
+
'--shadow-3': '0 12px 32px rgba(23, 26, 33, 0.12)',
|
|
64
|
+
'--scrim': 'rgba(23, 26, 33, 0.32)',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
export const night = {
|
|
68
|
+
name: 'valet night',
|
|
69
|
+
note: 'Dark. The same ink, lit from behind.',
|
|
70
|
+
scheme: 'dark',
|
|
71
|
+
tokens: {
|
|
72
|
+
'--bg': '#0c0f14',
|
|
73
|
+
'--panel': '#141820',
|
|
74
|
+
'--panel-2': '#1b2029',
|
|
75
|
+
'--border': '#262c37',
|
|
76
|
+
'--border-strong': '#616b7d',
|
|
77
|
+
'--text': '#e8eaf0',
|
|
78
|
+
'--muted': '#9ba4b5',
|
|
79
|
+
'--accent': '#8f88ff',
|
|
80
|
+
'--accent-dim': '#3f3a8f',
|
|
81
|
+
// Near-black on the pale indigo, 6.46:1. White would be 2.6:1.
|
|
82
|
+
'--on-accent': '#0d0b2e',
|
|
83
|
+
'--good': '#5fcb8f',
|
|
84
|
+
'--warn': '#e2ae58',
|
|
85
|
+
'--bad': '#f28b84',
|
|
86
|
+
'--info': '#57c4e8',
|
|
87
|
+
'--app-bg': '#0c0f14',
|
|
88
|
+
'--shadow-1': '0 6px 20px rgba(0, 0, 0, 0.28)',
|
|
89
|
+
'--shadow-2': '0 8px 28px rgba(0, 0, 0, 0.34)',
|
|
90
|
+
'--shadow-3': '0 10px 34px rgba(0, 0, 0, 0.38)',
|
|
91
|
+
'--scrim': 'rgba(0, 0, 0, 0.5)',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
/** Keyed by the name `applyTheme` takes: `name` lowercased, spaces to hyphens. */
|
|
95
|
+
export const VALET_THEMES = { valet: light, 'valet-night': night };
|
|
96
|
+
/** valet, the product: its badge in `brandMarks.ts`, the identity above, the
|
|
97
|
+
* two palettes, and light until somebody picks. */
|
|
98
|
+
export const valet = {
|
|
99
|
+
name: 'valet',
|
|
100
|
+
identity: VALET_IDENTITY,
|
|
101
|
+
themes: VALET_THEMES,
|
|
102
|
+
defaultTheme: 'valet',
|
|
103
|
+
};
|