@webority/theme 0.96.0 → 0.99.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 CHANGED
@@ -31,34 +31,6 @@ load-bearing**:
31
31
  Importing part of the core chain is a bug: skipping `wui-aliases` leaves every
32
32
  `--color-*` reference unresolved.
33
33
 
34
- ### The primary as text: `--wui-primary-ink`
35
-
36
- A brand primary is chosen as a fill. A light one fails WCAG AA as text: an orange such as `#E8501E`
37
- measures 3.75:1 on white. So the theme keeps two colours:
38
-
39
- - `--wui-primary` (`--color-primary`): fills, borders, focus rings, the selected-day disc.
40
- - `--wui-primary-ink` (`--color-primary-ink`): every link, tab label, page number, selected option,
41
- avatar initial and primary-coloured icon. It is `$primary` darkened in 2% steps until it clears
42
- 4.5:1 on white, the page, the muted and elevated fills and the brand's own soft tint, so it equals
43
- `$primary` when the primary already clears AA. Orange `#E8501E` gets `#BA4018` (5.48:1 on white).
44
- - `--wui-primary-text` (`--color-primary-text`): the label ON a solid primary fill, white when white
45
- - `--color-primary-hover-text`: the label colour on a pressed or hovered primary button (white in light mode, near-black in dark mode).
46
- clears 4.5:1 on the primary, near-black otherwise.
47
-
48
- All three derive from `$primary` at compile time, so setting `$primary` (or `wui-brand-primary`) is
49
- enough. A product can set `$wui-primary-ink` / `$wui-primary-text` before the theme's variables, or
50
- `--wui-primary-ink` / `--wui-primary-text` at runtime. A brand layer that re-points `--wui-primary` at
51
- runtime must set `--wui-primary-ink` and `--wui-primary-text` beside it.
52
-
53
- Dark mode uses one colour, `--wui-dark-primary`, for primary text, rings, focus borders and the fill
54
- under its near-black label. It is `$primary` mixed with white in 2% steps until it clears 4.5:1 on
55
- every dark surface, on its own avatar tint, on the brand's soft tint and under that label, so
56
- `wui-brand-primary` carries the brand into dark mode (a royal blue `#2F50E4` lifts to about `#8FA1F0`). Never
57
- set it to the light brand fill: a runtime `--wui-dark-primary` must clear the same floors.
58
-
59
- `check-contrast` proves both derivations for an orange, an amber, a sky and a royal blue test brand
60
- and fails any theme rule that colours text with `--color-primary`.
61
-
62
34
  ### Country flags are opt-in
63
35
 
64
36
  The 245 `.wui-flag-*` rules are about 187 KB raw (38 KB Brotli) of inlined SVG, so
@@ -129,36 +101,20 @@ The full `wui-components` chain stays the default and renders as before. Each on
129
101
  Caution: an on-demand partial loaded after the core sheet comes after the shared focus ring and pressed
130
102
  wash (`wui/interaction`, `wui/menu-motion`), so check its hover and press states in the showcase.
131
103
 
132
- ## Signal brand layer (opt-in)
133
-
134
- `dist/webority-brand-signal.css` (export `@webority/theme/css/brand-signal`, source `scss/_brand-signal.scss`)
135
- re-points the theme to the Webority company palette: violet #4A0FBF primary, ink #16093A headings, tint
136
- #F1EBFF, pink #B517C8 for unread counts only, muted text #6A6A6A, a dark set on pure black #000 with neutral
137
- grey surfaces and violet #A98BFF kept for accents, and the Webority Serif 600 face for page and result titles at 24px and above. It is never imported by
138
- the default theme (check-theme-exports asserts the default dist has no #4A0FBF).
139
-
140
- Load it once, after the theme: React `import "@webority/theme/css/brand-signal"`; Razor
141
- `_content/Webority.Ui.Razor/css/webority-brand-signal.css`; SCSS `@import "@webority/theme/scss/brand-signal"`
142
- after the components. Dark mode is emitted under `[data-theme=dark]`, `[data-bs-theme=dark]` and the
143
- `data-theme=auto` media query. Contrast of every brand text and surface pair is held at 4.5:1 by check-contrast.
144
- `_brand-signal.scss` owns brand values only; no component CSS.
145
-
146
104
  ## Runtime brand from a product's token file (opt-in)
147
105
 
148
106
  A product's look can be applied to the precompiled theme at runtime, which is how the hosted showcase shows
149
107
  every component in a product's design language.
150
108
 
151
- - `webority-theme-export <compiled.css>... --product <name> --out tokens.json` (a bin of this package) writes
152
- the token file, format `webority-theme-tokens/1`: `{ format, product, light, dark, bootstrapDark }`, each a
153
- map of custom property to value. It reads the product's compiled CSS, not its SCSS, because Bootstrap's rgb
154
- triplets and subtle and emphasis mixes only exist after compilation. `light` is the top-level `:root`,
155
- `dark` the theme's `:root[data-theme=dark]` rule, `bootstrapDark` Bootstrap's `[data-bs-theme=dark]` rule.
109
+ - `webority brand` (the `webority` command of `@webority/tokens`) writes a product's token file, `webority-web.json`,
110
+ format `webority-theme-tokens/2`: `{ format, source, colors: { light, dark }, space, radius, text, fonts, shadow }`.
156
111
  - `dist/webority-runtime-brand.css` (export `@webority/theme/css/runtime-brand`, source
157
112
  `scss/_runtime-brand.scss`) re-points the few component rules Bootstrap compiles from `$primary` as literals
158
113
  (primary buttons, nav pills, pagination, list group, progress, range thumb, mouse focus border, `.link-primary`
159
114
  hover, `.table-primary`) at `--bs-primary`. It holds no colour of its own (check-theme-exports asserts it).
160
- - Load order: the theme, then the runtime brand layer, then the token file's values on `:root`, under the dark
161
- selectors for `dark`, and under `[data-bs-theme=dark]` for `bootstrapDark`.
115
+ - Load order: the theme, then the runtime brand layer, then the token file's values: light on `:root`, dark under
116
+ `:root[data-theme=dark]` and `:root[data-bs-theme=dark]`, and the Bootstrap primary and link triplets under
117
+ `[data-bs-theme=dark]`.
162
118
  - Each product serves its file at `/theme/tokens.json` with `Access-Control-Allow-Origin` for the showcase host.
163
119
  - A font the token file names renders only when the page has its face: the theme's own families do.
164
120
 
@@ -167,10 +123,12 @@ every component in a product's design language.
167
123
  The classes `wui-force-hover`, `wui-force-focus` and `wui-force-active` make an element show its hover, focus or
168
124
  pressed look without a pointer.
169
125
 
170
- They exist in the compiled stylesheets, `@webority/theme/css` and `@webority/theme/css/brand-signal`, not in a
126
+ They exist in the compiled stylesheet `@webority/theme/css`, not in a
171
127
  product's own SCSS build. A product that builds the theme SCSS itself adds `forcedStatesPlugin()`, imported from
172
128
  `@webority/theme/postcss/forced-states`, to its PostCSS plugins to get the same classes.
173
129
 
130
+ Code that sets the classes imports their names from `@webority/theme/runtime` as `FORCED_STATE_CLASSES` (`hover`, `focus`, `active`). The export has no dependencies, so it runs in a browser bundle or in Node.
131
+
174
132
  A class forces only the element that carries it, so a design tool sets it on a part's root and on its first
175
133
  focusable child. The purge safelist keeps these three classes.
176
134
 
@@ -277,9 +235,9 @@ Anti-over-correction checklist. When thinning the package (e.g. marketing extrac
277
235
 
278
236
  ### Tokens & system (`scss/_variables`, `_tokens`, `_wui-aliases`)
279
237
 
280
- - Theme colors + `wui-brand-primary`; body/text/surface/border ramps (incl. AA tertiary)
238
+ - Theme colors + `wui-brand-primary`; body/text/surface/border ramps
281
239
  - Radius ladder that differs from Bootstrap; spacer map extensions (6+)
282
- - Status ramps: fills **and** `-text` / danger-strong for AA
240
+ - Status ramps: fills **and** `-text` / danger-strong
283
241
  - Control heights (`--wui-control-height*`: sm 32, md 36, lg 44; md is 44 on phone-width and touch screens) and one disabled opacity (`--wui-disabled-opacity`); flat in-page elevation; overlay shadows only
284
242
  - Z-index scale (`--wui-z-*`); dark-mode `--bs-*` / RGB bridges
285
243
  - Focus: no input glow (`$input-focus-box-shadow: none`); fields keep a soft brand border and also draw the shared keyboard ring
@@ -324,7 +282,6 @@ Keep shipping all of these; classify for **when to use**, not for removal:
324
282
  `corner-shape: squircle` is applied on many controls (buttons, fields, chips, menus, shell) as **progressive enhancement**:
325
283
 
326
284
  - Supporting browsers get slightly smoother corners; others keep plain `border-radius`.
327
- - Not a cross-browser design contract; not a WCAG requirement.
328
285
  - Missing squircle is **not** a bug.
329
286
 
330
287
  **Policy:** keep on shared control surfaces for consistent geometry; do **not** strip globally. Optional `.rounded-squircle` remains an opt-in utility. Products that want pure arcs only override locally — do not fork App*.
@@ -1 +1 @@
1
- import e from"postcss";import t from"postcss-selector-parser";var n=Object.freeze({hover:`wui-force-hover`,focus:`wui-force-focus`,active:`wui-force-active`}),r=new Map([[`:hover`,n.hover],[`:focus`,n.focus],[`:focus-visible`,n.focus],[`:focus-within`,n.focus],[`:active`,n.active]]),i=new Set(Object.values(n)),a=t();function o(e){for(let t=e.parent;t;t=t.parent)if(t.type===`atrule`&&/keyframes$/i.test(t.name))return!0;return!1}function s(e,t){let n=e.parent?.parent;return n?.type!==`pseudo`||n.value.toLowerCase()!==`:is`?!1:n.nodes.some(e=>e.nodes.some(e=>e.type===`class`&&e.value===t))}function c(e){for(let t=e.prev();t&&t.type!==`combinator`;t=t.prev())if(t.type===`pseudo`&&t.value.startsWith(`::`))return!0;return!1}function l(e){let n=[];e.walkPseudos(e=>{let t=r.get(e.value.toLowerCase());t&&!s(e,t)&&!c(e)&&n.push({pseudo:e,cls:t})});for(let{pseudo:e,cls:r}of n){let n=t.selector({value:``});n.append(e.clone());let i=t.selector({value:``});i.append(t.className({value:r}));let a=t.pseudo({value:`:is`});a.append(n),a.append(i),e.replaceWith(a)}return n.length}function u(e){let t=!1;return e.walkClasses(e=>{t||=i.has(e.value)}),t}function d(e){let t=0,n=0;return e.walkRules(e=>{if(o(e))return;let r=a.astSync(e.selector),i=!1;for(let e of r.nodes)l(e)>0&&(t++,i=!0),u(e)&&n++;i&&(e.selector=r.toString())}),{rewritten:t,carrying:n}}function f(t){let n=e.parse(t);return d(n),n.toString()}function p(){return{postcssPlugin:`wui-forced-states`,OnceExit(e){d(e)}}}p.postcss=!0;export{n as FORCED_STATE_CLASSES,f as addForcedStates,p as forcedStatesPlugin,d as rewriteRoot};
1
+ import{FORCED_STATE_CLASSES as e}from"../runtime.mjs";import t from"postcss";import n from"postcss-selector-parser";var r=new Map([[`:hover`,e.hover],[`:focus`,e.focus],[`:focus-visible`,e.focus],[`:focus-within`,e.focus],[`:active`,e.active]]),i=new Set(Object.values(e)),a=n();function o(e){for(let t=e.parent;t;t=t.parent)if(t.type===`atrule`&&/keyframes$/i.test(t.name))return!0;return!1}function s(e,t){let n=e.parent?.parent;return n?.type!==`pseudo`||n.value.toLowerCase()!==`:is`?!1:n.nodes.some(e=>e.nodes.some(e=>e.type===`class`&&e.value===t))}function c(e){for(let t=e.prev();t&&t.type!==`combinator`;t=t.prev())if(t.type===`pseudo`&&t.value.startsWith(`::`))return!0;return!1}function l(e){let t=[];e.walkPseudos(e=>{let n=r.get(e.value.toLowerCase());n&&!s(e,n)&&!c(e)&&t.push({pseudo:e,cls:n})});for(let{pseudo:e,cls:r}of t){let t=n.selector({value:``});t.append(e.clone());let i=n.selector({value:``});i.append(n.className({value:r}));let a=n.pseudo({value:`:is`});a.append(t),a.append(i),e.replaceWith(a)}return t.length}function u(e){let t=!1;return e.walkClasses(e=>{t||=i.has(e.value)}),t}function d(e){let t=0,n=0;return e.walkRules(e=>{if(o(e))return;let r=a.astSync(e.selector),i=!1;for(let e of r.nodes)l(e)>0&&(t++,i=!0),u(e)&&n++;i&&(e.selector=r.toString())}),{rewritten:t,carrying:n}}function f(e){let n=t.parse(e);return d(n),n.toString()}function p(){return{postcssPlugin:`wui-forced-states`,OnceExit(e){d(e)}}}p.postcss=!0;export{f as addForcedStates,p as forcedStatesPlugin,d as rewriteRoot};
@@ -1438,6 +1438,7 @@
1438
1438
  "wui-struct-card-no-check",
1439
1439
  "wui-struct-card-sm",
1440
1440
  "wui-struct-card-stacked",
1441
+ "wui-tab-label",
1441
1442
  "wui-tabbar",
1442
1443
  "wui-tabbar-badge",
1443
1444
  "wui-tabbar-icon",
@@ -0,0 +1 @@
1
+ var e=Object.freeze({hover:`wui-force-hover`,focus:`wui-force-focus`,active:`wui-force-active`});export{e as FORCED_STATE_CLASSES};