@misoto22/kioku-ui-theme-kioku 0.0.0 → 1.0.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 +195 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/theme.css +483 -9
- package/dist/themes.d.ts +1 -0
- package/dist/themes.js +9 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Kioku theme pack
|
|
2
2
|
|
|
3
|
-
`@misoto22/kioku-ui-theme-kioku` provides the Washi, Muji, and
|
|
4
|
-
identities as an external theme collection for `@misoto22/kioku-ui`.
|
|
3
|
+
`@misoto22/kioku-ui-theme-kioku` provides the Washi, Muji, Sumi, and Kasumi
|
|
4
|
+
visual identities as an external theme collection for `@misoto22/kioku-ui`.
|
|
5
5
|
|
|
6
6
|
```tsx
|
|
7
7
|
import {ThemeProvider} from '@misoto22/kioku-ui/theme';
|
|
@@ -22,12 +22,17 @@ CSS `light-dark()`, so they follow the host's inherited `color-scheme`. The
|
|
|
22
22
|
themes share the package's semantic spacing, radius, and control-size scales.
|
|
23
23
|
The stylesheet never targets `:root`, `html`, or `body`.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Washi, Muji, and Sumi carry Kioku Console's own palettes, geometry, and type
|
|
26
|
+
scale:
|
|
26
27
|
warm paper rather than white, one 3px corner for every element including
|
|
27
28
|
controls, a hairline rule instead of a drop shadow, and the console's compact
|
|
28
29
|
spacing. Where a role that this package holds to WCAG AA missed the threshold on
|
|
29
30
|
one of its backgrounds, it keeps the console's hue and loses only lightness.
|
|
30
31
|
|
|
32
|
+
Kasumi is the fourth skin and the one exception — see **Kasumi and the frost
|
|
33
|
+
lever** below. It shares the same geometry and type scale, and differs only in
|
|
34
|
+
that its field surfaces are translucent.
|
|
35
|
+
|
|
31
36
|
Each skin fulfills the spacing roles at both densities, so a reader selecting
|
|
32
37
|
`standard` widens the same rhythm rather than switching visual identity:
|
|
33
38
|
|
|
@@ -48,3 +53,190 @@ sets it transparent, which is how a skin declines the texture.
|
|
|
48
53
|
|
|
49
54
|
The initial theme release supports core `>=0.0.0 <0.2.0`. A later pre-1 core
|
|
50
55
|
minor must be compatibility-reviewed before this peer range is widened.
|
|
56
|
+
|
|
57
|
+
## Kasumi and the frost lever
|
|
58
|
+
|
|
59
|
+
霞 is mist, and the only skin here that expects something behind it. Its field
|
|
60
|
+
surfaces are translucent and it blurs whatever the host drew, so a backdrop
|
|
61
|
+
reads through the interface while type keeps its contrast.
|
|
62
|
+
|
|
63
|
+
The model is ported from [Hermes Desktop][hermes]'s glass mode. Worth knowing
|
|
64
|
+
before you reach for it: in Hermes the blur is **native macOS vibrancy
|
|
65
|
+
composited below the web contents**, not CSS — in a transparent window
|
|
66
|
+
`backdrop-filter` reaches nothing, because the backdrop root is the document and
|
|
67
|
+
the desktop was never in it. On the web the blur is ours to draw, and three
|
|
68
|
+
things separate glass from a coloured film.
|
|
69
|
+
|
|
70
|
+
### 1. The tint goes to an extreme
|
|
71
|
+
|
|
72
|
+
Near-white in light, near-black in dark — never the mid-tone a skin would
|
|
73
|
+
otherwise use. A mid-tone film greys out whatever is behind it. Solving [Radix
|
|
74
|
+
Themes][radix]' alpha equation for a panel that must composite to `#f1f4f8` over
|
|
75
|
+
this canvas returns `#fefeff` at 50%, and Apple's navigation glass is
|
|
76
|
+
`rgba(0,0,0,0.8)` rather than a dark grey — the same answer from two directions.
|
|
77
|
+
So the field and the surfaces carry a near-neutral tint, and the skin spends its
|
|
78
|
+
whole chromatic budget on the accent.
|
|
79
|
+
|
|
80
|
+
### 2. The blur lives on a pseudo-element
|
|
81
|
+
|
|
82
|
+
`backdrop-filter` on the theme root would make it the containing block for every
|
|
83
|
+
`position: fixed` descendant — Tooltip, Toast, ContextMenu, AppShell, Popover,
|
|
84
|
+
Overlay and MobileNav all position against the viewport. A pseudo-element has no
|
|
85
|
+
descendants, so it can never be a containing block for anything. The root gets
|
|
86
|
+
`isolation: isolate`, which opens a stacking context rather than a containing
|
|
87
|
+
block, and `[data-theme='kasumi']::before` carries the filter at `z-index: -1`.
|
|
88
|
+
|
|
89
|
+
One consequence to know about: that stacking context contains the app. If a host
|
|
90
|
+
renders its own UI as a **sibling** of the ThemeProvider, a Dialog or Toast
|
|
91
|
+
inside the provider can no longer paint above it whatever its z-index. Wrapping
|
|
92
|
+
the whole application, which is the normal arrangement, is unaffected.
|
|
93
|
+
|
|
94
|
+
### 3. Saturation comes back
|
|
95
|
+
|
|
96
|
+
Glass amplifies the colour behind it; macOS vibrancy and Apple's navigation bar
|
|
97
|
+
both lift saturation to 180%, and `--kioku-theme-kasumi-frost-saturate` does the
|
|
98
|
+
same here. Mixing a tint toward `transparent` does the opposite.
|
|
99
|
+
|
|
100
|
+
### The host draws the backdrop — sharp
|
|
101
|
+
|
|
102
|
+
Put something behind the provider and leave it unfiltered. The theme blurs it:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<div className="frost">
|
|
106
|
+
<div className="frost__backdrop" aria-hidden />
|
|
107
|
+
<ThemeProvider defaultThemeId={kasumiTheme.id} themes={kiokuThemes}>
|
|
108
|
+
{children}
|
|
109
|
+
</ThemeProvider>
|
|
110
|
+
</div>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```css
|
|
114
|
+
.frost {
|
|
115
|
+
/* So the backdrop's negative z-index stays inside it. */
|
|
116
|
+
isolation: isolate;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.frost__backdrop {
|
|
120
|
+
position: fixed;
|
|
121
|
+
inset: 0;
|
|
122
|
+
z-index: -1;
|
|
123
|
+
background: url('/wallpaper.avif') center / cover no-repeat;
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
With nothing back there the filter is a no-op and Kasumi is simply a clean
|
|
128
|
+
near-white — or near-black — theme.
|
|
129
|
+
|
|
130
|
+
### One lever
|
|
131
|
+
|
|
132
|
+
`--kioku-theme-kasumi-frost-keep` is the percent of its own tint the skin keeps:
|
|
133
|
+
`100%` is an ordinary opaque skin, `0%` is bare backdrop. It ships at `64%`. Set
|
|
134
|
+
it at the same specificity as the theme's own default and later in the cascade,
|
|
135
|
+
and yours wins:
|
|
136
|
+
|
|
137
|
+
```css
|
|
138
|
+
[data-theme='kasumi'] {
|
|
139
|
+
--kioku-theme-kasumi-frost-keep: 52%;
|
|
140
|
+
--kioku-theme-kasumi-frost-blur: 26px;
|
|
141
|
+
--kioku-theme-kasumi-frost-saturate: 180%;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Reduced transparency is a host policy, not a theme default. This package's
|
|
145
|
+
stylesheet may only ever write a theme root, so it ships no media query —
|
|
146
|
+
a host that honours the preference pins the lever back itself. */
|
|
147
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
148
|
+
[data-theme='kasumi'] {
|
|
149
|
+
--kioku-theme-kasumi-frost-keep: 100%;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### What thins and what does not
|
|
155
|
+
|
|
156
|
+
**Only the field thins.** `color.canvas` and `color.surfaceMuted` follow the
|
|
157
|
+
lever. Everything wearing `color.surface` or `color.surfaceRaised` — 47
|
|
158
|
+
components, every card, input, badge, tooltip and menu — clamps to
|
|
159
|
+
`max(84%, keep)` and is never thinner than the field beneath it. This is the
|
|
160
|
+
rule Hermes paid for: thinning nested surfaces stacks the tint once per layer,
|
|
161
|
+
so a deeply nested pane lands near-opaque while a shallow route reads clear, on
|
|
162
|
+
the same lever setting.
|
|
163
|
+
|
|
164
|
+
**Borders never thin.** The rim is drawn with alpha — dark in light mode, light
|
|
165
|
+
in dark mode — because an opaque line makes a thinned card read as a flat box
|
|
166
|
+
rather than a pane. But it does not follow the lever: whatever the host drew,
|
|
167
|
+
two regions still have to separate. `border.interactive` is the exception and
|
|
168
|
+
stays an exact colour, being the accent that carries focus and selected state.
|
|
169
|
+
|
|
170
|
+
**The grain stays.** It is what keeps a thinned fill reading as matte rather
|
|
171
|
+
than as a polished sheet, and it is the reason the mode is called matte
|
|
172
|
+
transparency rather than glass.
|
|
173
|
+
|
|
174
|
+
One thing to pass yourself: `Card` defaults to `elevation="none"`, which draws
|
|
175
|
+
the border and no shadow. Kasumi puts its specular edge — the bright inset
|
|
176
|
+
hairline that reads as a pane rather than a panel — in the elevation tokens, so
|
|
177
|
+
`<Card elevation="low">` is what shows it.
|
|
178
|
+
|
|
179
|
+
### Contrast, honestly
|
|
180
|
+
|
|
181
|
+
Under frost the real background is whatever the host drew, which no theme can
|
|
182
|
+
know. So the guarantee is stated against the extremes — a backdrop of pure black
|
|
183
|
+
and one of pure white bracket anything you can put back there — and the two
|
|
184
|
+
load-bearing numbers are asserted by the test suite rather than claimed.
|
|
185
|
+
|
|
186
|
+
**On a raised surface, muted text is AA against any backdrop at all, at every
|
|
187
|
+
setting of the lever.** That is what the `max(84%, keep)` clamp buys: no more
|
|
188
|
+
than 16% of the backdrop ever reaches a card, and the worst case across both
|
|
189
|
+
modes and both extremes is 5.02:1. Lower the clamp, or lighten muted text, and
|
|
190
|
+
the test notices.
|
|
191
|
+
|
|
192
|
+
**On the bare field the guarantee has an edge**, the field being the one thing
|
|
193
|
+
that is not clamped. Measured against those same extremes:
|
|
194
|
+
|
|
195
|
+
| Text sitting on the bare field | AA against any backdrop down to |
|
|
196
|
+
| ------------------------------ | ------------------------------- |
|
|
197
|
+
| `color.text` | keep 52% light, 60% dark |
|
|
198
|
+
| `color.textSecondary` | keep 64% light, 70% dark |
|
|
199
|
+
| `color.textMuted` | keep 74% light, 79% dark |
|
|
200
|
+
|
|
201
|
+
At the shipping 64% body text is covered and muted text is not. Two things
|
|
202
|
+
follow, and they are the whole of the guidance:
|
|
203
|
+
|
|
204
|
+
1. **Under frost, muted text belongs on a raised surface.** A caption or a
|
|
205
|
+
timestamp sitting directly on the canvas is the one combination the lever can
|
|
206
|
+
take below AA.
|
|
207
|
+
2. **Match the backdrop's luminance to the mode.** The binding case in that
|
|
208
|
+
table is always the mismatched one — a light skin over a near-black backdrop.
|
|
209
|
+
Pair light with a light image and dark with a dark one and the real ratios
|
|
210
|
+
sit well above the floor.
|
|
211
|
+
|
|
212
|
+
[hermes]: https://github.com/NousResearch/hermes-agent
|
|
213
|
+
[radix]: https://www.radix-ui.com/themes/docs/theme/color
|
|
214
|
+
|
|
215
|
+
## Fonts
|
|
216
|
+
|
|
217
|
+
These themes name font families in their typography tokens but ship no
|
|
218
|
+
`@font-face` of their own — delivering font files is a host application's
|
|
219
|
+
decision, not a theme pack's. **A host that does not load them silently gets
|
|
220
|
+
its system UI font instead**, which is not what any of these themes describe.
|
|
221
|
+
|
|
222
|
+
| Role | Family | Used by |
|
|
223
|
+
| ---------------------------------------- | ------------------------------- | ------------------- |
|
|
224
|
+
| Body, heading | `Zen Kaku Gothic New` | all four themes |
|
|
225
|
+
| Display | `Shippori Mincho` | Washi, Sumi, Kasumi |
|
|
226
|
+
| Display | `Zen Kaku Gothic New` | Muji |
|
|
227
|
+
| Mono | `IBM Plex Mono` | all four themes |
|
|
228
|
+
| Body, heading, display under `:lang(zh)` | `Noto Sans SC`, `Noto Serif SC` | all four themes |
|
|
229
|
+
|
|
230
|
+
Every stack falls back to a system family, so nothing breaks without them —
|
|
231
|
+
it simply stops looking like the theme. Load them however your application
|
|
232
|
+
already loads fonts; self-hosting is preferable to a third-party CDN if you
|
|
233
|
+
care about the request leaving your origin.
|
|
234
|
+
|
|
235
|
+
Request the weights `400`, `500`, and `700`. The themes ask for `600` as their
|
|
236
|
+
strong weight, but `Zen Kaku Gothic New` ships no 600 face, so the browser
|
|
237
|
+
resolves it to 700 — request 700 and it uses a real bold, omit it and it
|
|
238
|
+
synthesises one, which is visibly heavier and looser.
|
|
239
|
+
|
|
240
|
+
Chinese content resolves through `:lang(zh)`, so set the language on the
|
|
241
|
+
document or the subtree (`<html lang="zh">`) or the Latin families will be
|
|
242
|
+
asked to render glyphs they do not have.
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { kiokuThemes, mujiTheme, sumiTheme, washiTheme } from './themes.js';
|
|
1
|
+
export { kasumiTheme, kiokuThemes, mujiTheme, sumiTheme, washiTheme, } from './themes.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { kiokuThemes, mujiTheme, sumiTheme, washiTheme } from './themes.js';
|
|
1
|
+
export { kasumiTheme, kiokuThemes, mujiTheme, sumiTheme, washiTheme, } from './themes.js';
|
package/dist/theme.css
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
/* Ready-to-use theme CSS. Every selector targets a ThemeProvider data-theme root. */
|
|
2
2
|
[data-theme='washi'],
|
|
3
3
|
[data-theme='muji'],
|
|
4
|
-
[data-theme='sumi']
|
|
4
|
+
[data-theme='sumi'],
|
|
5
|
+
[data-theme='kasumi'] {
|
|
6
|
+
/*
|
|
7
|
+
* Declared here, in CSS, rather than left to the host to set inline. Two
|
|
8
|
+
* reasons, and the second is the one that bites. `light-dark()` resolves
|
|
9
|
+
* against the element's used color-scheme, so without this a theme root
|
|
10
|
+
* follows whatever an ancestor happened to declare. And a bundler that
|
|
11
|
+
* lowers `light-dark()` for older targets — lightningcss does — only emits
|
|
12
|
+
* the toggle custom properties when it can see a `color-scheme` declaration
|
|
13
|
+
* in the stylesheet. An inline style is invisible to it, so it rewrote every
|
|
14
|
+
* colour to `var(--lightningcss-light, …)` and emitted no definition: 104
|
|
15
|
+
* dead declarations in a built site that rendered correctly in dev.
|
|
16
|
+
*/
|
|
17
|
+
color-scheme: light dark;
|
|
5
18
|
--kioku-ui-color-canvas: var(--kioku-theme-color-canvas);
|
|
6
19
|
--kioku-ui-color-surface: var(--kioku-theme-color-surface);
|
|
7
20
|
--kioku-ui-color-surface-raised: var(--kioku-theme-color-surface-raised);
|
|
@@ -18,6 +31,7 @@
|
|
|
18
31
|
--kioku-ui-color-disabled-surface: var(--kioku-theme-color-disabled-surface);
|
|
19
32
|
--kioku-ui-color-disabled-text: var(--kioku-theme-color-disabled-text);
|
|
20
33
|
--kioku-ui-color-focus: var(--kioku-theme-color-focus);
|
|
34
|
+
--kioku-ui-color-scrim: var(--kioku-theme-color-scrim);
|
|
21
35
|
--kioku-ui-border-default: var(--kioku-theme-border-default);
|
|
22
36
|
--kioku-ui-border-strong: var(--kioku-theme-border-strong);
|
|
23
37
|
--kioku-ui-border-interactive: var(--kioku-theme-border-interactive);
|
|
@@ -64,6 +78,24 @@
|
|
|
64
78
|
--kioku-ui-typography-line-height-heading: var(
|
|
65
79
|
--kioku-theme-line-height-heading
|
|
66
80
|
);
|
|
81
|
+
--kioku-ui-typography-letter-spacing-title: var(
|
|
82
|
+
--kioku-theme-letter-spacing-title
|
|
83
|
+
);
|
|
84
|
+
--kioku-ui-typography-letter-spacing-heading: var(
|
|
85
|
+
--kioku-theme-letter-spacing-heading
|
|
86
|
+
);
|
|
87
|
+
--kioku-ui-typography-letter-spacing-body: var(
|
|
88
|
+
--kioku-theme-letter-spacing-body
|
|
89
|
+
);
|
|
90
|
+
--kioku-ui-typography-letter-spacing-label: var(
|
|
91
|
+
--kioku-theme-letter-spacing-label
|
|
92
|
+
);
|
|
93
|
+
--kioku-ui-typography-letter-spacing-eyebrow: var(
|
|
94
|
+
--kioku-theme-letter-spacing-eyebrow
|
|
95
|
+
);
|
|
96
|
+
--kioku-ui-typography-letter-spacing-mono: var(
|
|
97
|
+
--kioku-theme-letter-spacing-mono
|
|
98
|
+
);
|
|
67
99
|
--kioku-ui-spacing-xs: var(--kioku-theme-spacing-xs);
|
|
68
100
|
--kioku-ui-spacing-sm: var(--kioku-theme-spacing-sm);
|
|
69
101
|
--kioku-ui-spacing-md: var(--kioku-theme-spacing-md);
|
|
@@ -117,6 +149,16 @@
|
|
|
117
149
|
--kioku-theme-font-weight-strong: 600;
|
|
118
150
|
--kioku-theme-line-height-body: 1.62;
|
|
119
151
|
--kioku-theme-line-height-heading: 1.25;
|
|
152
|
+
|
|
153
|
+
/* Tracking runs inverse to size: the smaller the type, the further it is
|
|
154
|
+
opened. Mincho at 11px closes up into a smudge without it, and mono is
|
|
155
|
+
the one role that tightens because its figures are already too wide. */
|
|
156
|
+
--kioku-theme-letter-spacing-title: 0.01em;
|
|
157
|
+
--kioku-theme-letter-spacing-heading: 0.02em;
|
|
158
|
+
--kioku-theme-letter-spacing-body: 0;
|
|
159
|
+
--kioku-theme-letter-spacing-label: 0.04em;
|
|
160
|
+
--kioku-theme-letter-spacing-eyebrow: 0.1em;
|
|
161
|
+
--kioku-theme-letter-spacing-mono: -0.01em;
|
|
120
162
|
--kioku-theme-radius-inner: 3px;
|
|
121
163
|
--kioku-theme-radius-element: 3px;
|
|
122
164
|
--kioku-theme-radius-container: 3px;
|
|
@@ -144,7 +186,8 @@
|
|
|
144
186
|
/* Density is a matter of eyesight and screen size, so it stays a knob. */
|
|
145
187
|
[data-theme='washi'][data-density='standard'],
|
|
146
188
|
[data-theme='muji'][data-density='standard'],
|
|
147
|
-
[data-theme='sumi'][data-density='standard']
|
|
189
|
+
[data-theme='sumi'][data-density='standard'],
|
|
190
|
+
[data-theme='kasumi'][data-density='standard'] {
|
|
148
191
|
--kioku-theme-spacing-xs: 4px;
|
|
149
192
|
--kioku-theme-spacing-sm: 8px;
|
|
150
193
|
--kioku-theme-spacing-md: 13px;
|
|
@@ -157,7 +200,7 @@
|
|
|
157
200
|
[data-theme='washi'] {
|
|
158
201
|
--kioku-theme-color-canvas: light-dark(#efebe0, #191713);
|
|
159
202
|
--kioku-theme-color-surface: light-dark(#f6f3e9, #211e19);
|
|
160
|
-
--kioku-theme-color-surface-raised: light-dark(#f6f3e9, #
|
|
203
|
+
--kioku-theme-color-surface-raised: light-dark(#f6f3e9, #38342e);
|
|
161
204
|
--kioku-theme-color-surface-muted: light-dark(#e7e2d3, #2a2620);
|
|
162
205
|
--kioku-theme-color-text: light-dark(#26221c, #ece6d9);
|
|
163
206
|
--kioku-theme-color-text-secondary: light-dark(#5d574c, #a49c8c);
|
|
@@ -177,6 +220,7 @@
|
|
|
177
220
|
--kioku-theme-color-disabled-surface: light-dark(#e2dccb, #151310);
|
|
178
221
|
--kioku-theme-color-disabled-text: light-dark(#8a8375, #7d766a);
|
|
179
222
|
--kioku-theme-color-focus: light-dark(#2f5d8a, #7ba6cf);
|
|
223
|
+
--kioku-theme-color-scrim: light-dark(rgb(38 34 28 / 34%), rgb(0 0 0 / 62%));
|
|
180
224
|
--kioku-theme-border-default: light-dark(#ddd7c5, #302b24);
|
|
181
225
|
--kioku-theme-border-strong: light-dark(#c8c0aa, #423b31);
|
|
182
226
|
--kioku-theme-border-interactive: light-dark(#2f5d8a, #7ba6cf);
|
|
@@ -199,8 +243,13 @@
|
|
|
199
243
|
--kioku-theme-elevation-medium:
|
|
200
244
|
0 1px 0 light-dark(rgb(38 34 28 / 4%), rgb(0 0 0 / 22%)),
|
|
201
245
|
0 0 0 1px light-dark(#ddd7c5, #302b24);
|
|
246
|
+
/* `high` is still the top of the ladder, but it says so with a heavier
|
|
247
|
+
hard line rather than a softer one: nothing in this system blurs. Its
|
|
248
|
+
five consumers are all modal surfaces, and a modal is separated from
|
|
249
|
+
the page by the scrim — the shadow only has to say how far off the
|
|
250
|
+
desk the sheet sits. 霞 is the documented exception; see its block. */
|
|
202
251
|
--kioku-theme-elevation-high:
|
|
203
|
-
0 2px
|
|
252
|
+
0 2px 0 light-dark(rgb(38 34 28 / 7%), rgb(0 0 0 / 34%)),
|
|
204
253
|
0 0 0 1px light-dark(#ddd7c5, #302b24);
|
|
205
254
|
}
|
|
206
255
|
|
|
@@ -208,7 +257,7 @@
|
|
|
208
257
|
[data-theme='muji'] {
|
|
209
258
|
--kioku-theme-color-canvas: light-dark(#f2f2ef, #1a1c19);
|
|
210
259
|
--kioku-theme-color-surface: light-dark(#f9f9f7, #222420);
|
|
211
|
-
--kioku-theme-color-surface-raised: light-dark(#f9f9f7, #
|
|
260
|
+
--kioku-theme-color-surface-raised: light-dark(#f9f9f7, #393b35);
|
|
212
261
|
--kioku-theme-color-surface-muted: light-dark(#eae4d8, #2b2d27);
|
|
213
262
|
--kioku-theme-color-text: light-dark(#2f322c, #e7e8e2);
|
|
214
263
|
--kioku-theme-color-text-secondary: light-dark(#64675d, #9b9e95);
|
|
@@ -228,6 +277,7 @@
|
|
|
228
277
|
--kioku-theme-color-disabled-surface: light-dark(#e0d9ca, #141613);
|
|
229
278
|
--kioku-theme-color-disabled-text: light-dark(#93968b, #75786f);
|
|
230
279
|
--kioku-theme-color-focus: light-dark(#566b52, #9cb597);
|
|
280
|
+
--kioku-theme-color-scrim: light-dark(rgb(47 50 44 / 34%), rgb(0 0 0 / 62%));
|
|
231
281
|
--kioku-theme-border-default: light-dark(#dcdcd4, #31342d);
|
|
232
282
|
--kioku-theme-border-strong: light-dark(#c2c3b8, #43463d);
|
|
233
283
|
--kioku-theme-border-interactive: light-dark(#566b52, #9cb597);
|
|
@@ -252,7 +302,7 @@
|
|
|
252
302
|
0 1px 0 light-dark(rgb(47 50 44 / 4%), rgb(0 0 0 / 24%)),
|
|
253
303
|
0 0 0 1px light-dark(#dcdcd4, #31342d);
|
|
254
304
|
--kioku-theme-elevation-high:
|
|
255
|
-
0 2px
|
|
305
|
+
0 2px 0 light-dark(rgb(47 50 44 / 7%), rgb(0 0 0 / 36%)),
|
|
256
306
|
0 0 0 1px light-dark(#dcdcd4, #31342d);
|
|
257
307
|
}
|
|
258
308
|
|
|
@@ -260,7 +310,7 @@
|
|
|
260
310
|
[data-theme='sumi'] {
|
|
261
311
|
--kioku-theme-color-canvas: light-dark(#f5f5f3, #0f0f0e);
|
|
262
312
|
--kioku-theme-color-surface: light-dark(#ffffff, #191918);
|
|
263
|
-
--kioku-theme-color-surface-raised: light-dark(#ffffff, #
|
|
313
|
+
--kioku-theme-color-surface-raised: light-dark(#ffffff, #30302e);
|
|
264
314
|
--kioku-theme-color-surface-muted: light-dark(#edede9, #222220);
|
|
265
315
|
--kioku-theme-color-text: light-dark(#131311, #f2f2ee);
|
|
266
316
|
--kioku-theme-color-text-secondary: light-dark(#4a4a46, #a8a8a2);
|
|
@@ -280,6 +330,7 @@
|
|
|
280
330
|
--kioku-theme-color-disabled-surface: light-dark(#e4e4e0, #090908);
|
|
281
331
|
--kioku-theme-color-disabled-text: light-dark(#7c7c76, #7b7b75);
|
|
282
332
|
--kioku-theme-color-focus: light-dark(#1d4d7c, #79aade);
|
|
333
|
+
--kioku-theme-color-scrim: light-dark(rgb(19 19 17 / 36%), rgb(0 0 0 / 66%));
|
|
283
334
|
--kioku-theme-border-default: light-dark(#dcdcd8, #2a2a27);
|
|
284
335
|
--kioku-theme-border-strong: light-dark(#b4b4ae, #3d3d39);
|
|
285
336
|
--kioku-theme-border-interactive: light-dark(#1d4d7c, #79aade);
|
|
@@ -300,11 +351,197 @@
|
|
|
300
351
|
0 1px 0 light-dark(rgb(19 19 17 / 6%), rgb(0 0 0 / 40%)),
|
|
301
352
|
0 0 0 1px light-dark(#dcdcd8, #2a2a27);
|
|
302
353
|
--kioku-theme-elevation-high:
|
|
303
|
-
0 2px
|
|
354
|
+
0 2px 0 light-dark(rgb(19 19 17 / 10%), rgb(0 0 0 / 52%)),
|
|
304
355
|
0 0 0 1px light-dark(#dcdcd8, #2a2a27);
|
|
305
356
|
}
|
|
306
357
|
|
|
307
358
|
/* ThemeDefinition values resolve through a dictionary owned by each skin. */
|
|
359
|
+
/* 霞: mist, and the only skin that expects something behind it.
|
|
360
|
+
|
|
361
|
+
Ported from Hermes Desktop's glass mode by way of Apple's own recipe, and
|
|
362
|
+
the three things that separate glass from a coloured film are all here.
|
|
363
|
+
|
|
364
|
+
1. THE TINT GOES TO AN EXTREME. Near-white in light, near-black in dark —
|
|
365
|
+
never the mid-tone a skin would otherwise use. A mid-tone film greys out
|
|
366
|
+
whatever is behind it; an extreme reads as light passing through. Solving
|
|
367
|
+
Radix's alpha equation for a panel that must composite to #f1f4f8 over
|
|
368
|
+
this canvas returns #fefeff at 50%, which is the same answer, and Apple's
|
|
369
|
+
navigation glass is rgba(0,0,0,0.8) rather than a dark grey. So the field
|
|
370
|
+
and the surfaces carry a near-neutral tint and the skin spends its whole
|
|
371
|
+
chromatic budget on the accent.
|
|
372
|
+
|
|
373
|
+
2. THE BLUR IS REAL, and it lives on this root's ::before. A backdrop-filter
|
|
374
|
+
on the root ITSELF would make it the containing block for every
|
|
375
|
+
`position: fixed` descendant — Tooltip, Toast, ContextMenu, AppShell,
|
|
376
|
+
Popover, Overlay and MobileNav all position against the viewport. A
|
|
377
|
+
pseudo-element has no descendants, so it cannot be a containing block for
|
|
378
|
+
anything, and `isolation: isolate` keeps its negative z-index inside this
|
|
379
|
+
root instead of letting it fall behind the host's page. Isolation makes a
|
|
380
|
+
stacking context, which is not a containing block, so fixed positioning
|
|
381
|
+
is untouched.
|
|
382
|
+
|
|
383
|
+
3. SATURATION COMES BACK. Glass amplifies the colour behind it; macOS
|
|
384
|
+
vibrancy and Apple's navigation bar both lift saturation to 180%. Mixing
|
|
385
|
+
a tint toward `transparent` does the opposite, which is what made an
|
|
386
|
+
earlier pass of this skin read as plastic.
|
|
387
|
+
|
|
388
|
+
ONE PAINTER, which is the rule Hermes paid for. Thinning nested field
|
|
389
|
+
surfaces stacks the tint once per layer, so a deep pane lands near-opaque
|
|
390
|
+
while a shallow route reads clear on the same setting. The field here is
|
|
391
|
+
`color.canvas` — three painters in the whole library (Layout, Box's canvas
|
|
392
|
+
variant, the global sheet) — plus `color.surfaceMuted` for the recessed
|
|
393
|
+
band. The 47 components wearing `color.surface` are raised content and clamp
|
|
394
|
+
above it.
|
|
395
|
+
|
|
396
|
+
THE LEVER is `--kioku-theme-kasumi-frost-keep`: the percent of its own tint
|
|
397
|
+
the skin keeps. 100% is an ordinary near-white skin, 0% is bare backdrop.
|
|
398
|
+
Raised surfaces clamp to max(84%, keep), which is where muted text still
|
|
399
|
+
holds AA over a backdrop of pure black or pure white.
|
|
400
|
+
|
|
401
|
+
Reduced transparency is a host policy: this sheet may only write a theme
|
|
402
|
+
root, so it ships no media query and a host that honours the preference pins
|
|
403
|
+
the lever back to 100% itself. */
|
|
404
|
+
[data-theme='kasumi'] {
|
|
405
|
+
/* A stacking context so ::before's negative z-index stays in this root.
|
|
406
|
+
Deliberately not a filter or a transform — those would capture fixed
|
|
407
|
+
descendants; isolation does not. */
|
|
408
|
+
isolation: isolate;
|
|
409
|
+
/* And a containing block, so the frost's `inset: 0` resolves against this
|
|
410
|
+
root rather than against whatever positioned ancestor happens to be above
|
|
411
|
+
it. Isolation governs paint order, not geometry: without this the frost
|
|
412
|
+
escaped the skin and blurred everything up to the nearest positioned
|
|
413
|
+
ancestor, and a page showing several skins at once stacked one 180%
|
|
414
|
+
saturation per swatch until the whole document went yellow. `relative`
|
|
415
|
+
is safe where `transform` and `filter` are not — it does not become the
|
|
416
|
+
containing block for a fixed descendant. */
|
|
417
|
+
position: relative;
|
|
418
|
+
|
|
419
|
+
--kioku-theme-kasumi-frost-keep: 64%;
|
|
420
|
+
--kioku-theme-kasumi-frost-raised: max(
|
|
421
|
+
84%,
|
|
422
|
+
var(--kioku-theme-kasumi-frost-keep, 100%)
|
|
423
|
+
);
|
|
424
|
+
--kioku-theme-kasumi-frost-blur: 26px;
|
|
425
|
+
--kioku-theme-kasumi-frost-saturate: 180%;
|
|
426
|
+
|
|
427
|
+
--kioku-theme-color-canvas: color-mix(
|
|
428
|
+
in srgb,
|
|
429
|
+
light-dark(#fbfcfe, #0b0d12) var(--kioku-theme-kasumi-frost-keep, 100%),
|
|
430
|
+
transparent
|
|
431
|
+
);
|
|
432
|
+
--kioku-theme-color-surface: color-mix(
|
|
433
|
+
in srgb,
|
|
434
|
+
light-dark(#ffffff, #12151b) var(--kioku-theme-kasumi-frost-raised, 100%),
|
|
435
|
+
transparent
|
|
436
|
+
);
|
|
437
|
+
--kioku-theme-color-surface-raised: color-mix(
|
|
438
|
+
in srgb,
|
|
439
|
+
light-dark(#ffffff, #171a21) var(--kioku-theme-kasumi-frost-raised, 100%),
|
|
440
|
+
transparent
|
|
441
|
+
);
|
|
442
|
+
--kioku-theme-color-surface-muted: color-mix(
|
|
443
|
+
in srgb,
|
|
444
|
+
light-dark(#e9edf3, #06080b) var(--kioku-theme-kasumi-frost-keep, 100%),
|
|
445
|
+
transparent
|
|
446
|
+
);
|
|
447
|
+
--kioku-theme-color-text: light-dark(#161b22, #eef1f6);
|
|
448
|
+
--kioku-theme-color-text-secondary: light-dark(#2f3846, #c3cbd8);
|
|
449
|
+
--kioku-theme-color-text-muted: light-dark(#414b59, #a3adbc);
|
|
450
|
+
--kioku-theme-color-text-on-accent: light-dark(#ffffff, #10131a);
|
|
451
|
+
--kioku-theme-color-accent: light-dark(#4c4a86, #a99bdc);
|
|
452
|
+
--kioku-theme-color-accent-hover: light-dark(#3b3a6b, #c2b7e9);
|
|
453
|
+
--kioku-theme-color-accent-active: light-dark(#2e2d54, #d6cef3);
|
|
454
|
+
--kioku-theme-color-overlay-hover: light-dark(
|
|
455
|
+
rgb(22 27 34 / 6%),
|
|
456
|
+
rgb(238 241 246 / 8%)
|
|
457
|
+
);
|
|
458
|
+
--kioku-theme-color-overlay-active: light-dark(
|
|
459
|
+
rgb(22 27 34 / 11%),
|
|
460
|
+
rgb(238 241 246 / 13%)
|
|
461
|
+
);
|
|
462
|
+
--kioku-theme-color-disabled-surface: light-dark(#e4e8ee, #0d1014);
|
|
463
|
+
--kioku-theme-color-disabled-text: light-dark(#7c8695, #6e7887);
|
|
464
|
+
--kioku-theme-color-focus: light-dark(#4c4a86, #a99bdc);
|
|
465
|
+
/* Frosted glass already dims what is behind it, so the scrim only has to
|
|
466
|
+
separate the surface from the page rather than hide it: lighter than the
|
|
467
|
+
opaque skins in both modes. */
|
|
468
|
+
--kioku-theme-color-scrim: light-dark(rgb(22 27 34 / 28%), rgb(0 0 0 / 56%));
|
|
469
|
+
/* Structural borders are the rim, and on glass the rim is ALPHA — dark in
|
|
470
|
+
light mode, light in dark mode, both at low strength. An opaque line is
|
|
471
|
+
what makes a thinned card read as a flat box rather than a pane, which is
|
|
472
|
+
what an earlier pass of this skin got wrong; every glass UI worth copying
|
|
473
|
+
draws this edge with alpha instead. It stays legible over the field and
|
|
474
|
+
over the card alike because it straddles the two, and it never thins with
|
|
475
|
+
the lever, so a region always has an edge no matter what the host drew.
|
|
476
|
+
|
|
477
|
+
`interactive` is the exception and stays opaque: it is the accent, it
|
|
478
|
+
carries focus and selected state, and those must be the exact colour
|
|
479
|
+
rather than an approximation of it over an unknown backdrop. */
|
|
480
|
+
--kioku-theme-border-default: light-dark(
|
|
481
|
+
rgb(22 27 34 / 14%),
|
|
482
|
+
rgb(255 255 255 / 14%)
|
|
483
|
+
);
|
|
484
|
+
--kioku-theme-border-strong: light-dark(
|
|
485
|
+
rgb(22 27 34 / 28%),
|
|
486
|
+
rgb(255 255 255 / 26%)
|
|
487
|
+
);
|
|
488
|
+
--kioku-theme-border-interactive: light-dark(#4c4a86, #a99bdc);
|
|
489
|
+
--kioku-theme-border-disabled: light-dark(
|
|
490
|
+
rgb(22 27 34 / 7%),
|
|
491
|
+
rgb(255 255 255 / 7%)
|
|
492
|
+
);
|
|
493
|
+
--kioku-theme-status-info-surface: light-dark(#e2eaf6, #7ba6cf26);
|
|
494
|
+
--kioku-theme-status-info-text: light-dark(#28496e, #a3c4e2);
|
|
495
|
+
--kioku-theme-status-success-surface: light-dark(#e0ece5, #6fae9022);
|
|
496
|
+
--kioku-theme-status-success-text: light-dark(#39654c, #7fbf9d);
|
|
497
|
+
--kioku-theme-status-warning-surface: light-dark(#f4ecd9, #c9a45c22);
|
|
498
|
+
--kioku-theme-status-warning-text: light-dark(#775d13, #d8b46a);
|
|
499
|
+
--kioku-theme-status-danger-surface: light-dark(#f5e2e3, #cf737d22);
|
|
500
|
+
--kioku-theme-status-danger-text: light-dark(#973d45, #e08b93);
|
|
501
|
+
/* Matte, not gloss. The speckle is what stops a thinned fill reading as a
|
|
502
|
+
polished sheet, and it is the reason the mode is called matte
|
|
503
|
+
transparency rather than glass. */
|
|
504
|
+
--kioku-theme-texture-grain: light-dark(
|
|
505
|
+
rgb(22 27 34 / 3%),
|
|
506
|
+
rgb(238 241 246 / 5%)
|
|
507
|
+
);
|
|
508
|
+
--kioku-theme-font-family-display:
|
|
509
|
+
'Shippori Mincho', 'Hiragino Mincho ProN', serif;
|
|
510
|
+
/* The specular edge: a bright inset hairline along the top, which is the
|
|
511
|
+
single strongest cue that a surface is a pane rather than a panel. The
|
|
512
|
+
outer ring stays a neutral so a card still has an edge on a host that
|
|
513
|
+
drew nothing behind the app. `high` is the one place this skin spends a
|
|
514
|
+
drop shadow — glass needs the lift, and the pack's hairline rule is
|
|
515
|
+
already carried by the ring in front of it. */
|
|
516
|
+
--kioku-theme-elevation-low:
|
|
517
|
+
inset 0 1px 0 light-dark(rgb(255 255 255 / 85%), rgb(255 255 255 / 12%)),
|
|
518
|
+
0 0 0 1px light-dark(rgb(22 27 34 / 10%), rgb(255 255 255 / 10%));
|
|
519
|
+
--kioku-theme-elevation-medium:
|
|
520
|
+
inset 0 1px 0 light-dark(rgb(255 255 255 / 88%), rgb(255 255 255 / 14%)),
|
|
521
|
+
0 0 0 1px light-dark(rgb(22 27 34 / 11%), rgb(255 255 255 / 11%)),
|
|
522
|
+
0 1px 2px light-dark(rgb(22 27 34 / 6%), rgb(0 0 0 / 30%));
|
|
523
|
+
--kioku-theme-elevation-high:
|
|
524
|
+
inset 0 1px 0 light-dark(rgb(255 255 255 / 90%), rgb(255 255 255 / 16%)),
|
|
525
|
+
0 0 0 1px light-dark(rgb(22 27 34 / 12%), rgb(255 255 255 / 12%)),
|
|
526
|
+
0 8px 24px light-dark(rgb(22 27 34 / 14%), rgb(0 0 0 / 45%));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/* The frost itself. On the pseudo-element, never on the root — see (2) above.
|
|
530
|
+
The host draws whatever goes behind the app; this blurs it. With nothing
|
|
531
|
+
back there the filter is a no-op and the skin is simply a clean near-white
|
|
532
|
+
(or near-black) theme. */
|
|
533
|
+
[data-theme='kasumi']::before {
|
|
534
|
+
backdrop-filter: blur(var(--kioku-theme-kasumi-frost-blur, 26px))
|
|
535
|
+
saturate(var(--kioku-theme-kasumi-frost-saturate, 180%));
|
|
536
|
+
-webkit-backdrop-filter: blur(var(--kioku-theme-kasumi-frost-blur, 26px))
|
|
537
|
+
saturate(var(--kioku-theme-kasumi-frost-saturate, 180%));
|
|
538
|
+
content: '';
|
|
539
|
+
inset: 0;
|
|
540
|
+
pointer-events: none;
|
|
541
|
+
position: absolute;
|
|
542
|
+
z-index: -1;
|
|
543
|
+
}
|
|
544
|
+
|
|
308
545
|
[data-theme='washi'] {
|
|
309
546
|
--kioku-theme-washi-color-canvas: var(--kioku-theme-color-canvas);
|
|
310
547
|
--kioku-theme-washi-color-surface: var(--kioku-theme-color-surface);
|
|
@@ -340,6 +577,7 @@
|
|
|
340
577
|
--kioku-theme-color-disabled-text
|
|
341
578
|
);
|
|
342
579
|
--kioku-theme-washi-color-focus: var(--kioku-theme-color-focus);
|
|
580
|
+
--kioku-theme-washi-color-scrim: var(--kioku-theme-color-scrim);
|
|
343
581
|
--kioku-theme-washi-border-default: var(--kioku-theme-border-default);
|
|
344
582
|
--kioku-theme-washi-border-strong: var(--kioku-theme-border-strong);
|
|
345
583
|
--kioku-theme-washi-border-interactive: var(--kioku-theme-border-interactive);
|
|
@@ -394,6 +632,24 @@
|
|
|
394
632
|
--kioku-theme-washi-line-height-heading: var(
|
|
395
633
|
--kioku-theme-line-height-heading
|
|
396
634
|
);
|
|
635
|
+
--kioku-theme-washi-letter-spacing-title: var(
|
|
636
|
+
--kioku-theme-letter-spacing-title
|
|
637
|
+
);
|
|
638
|
+
--kioku-theme-washi-letter-spacing-heading: var(
|
|
639
|
+
--kioku-theme-letter-spacing-heading
|
|
640
|
+
);
|
|
641
|
+
--kioku-theme-washi-letter-spacing-body: var(
|
|
642
|
+
--kioku-theme-letter-spacing-body
|
|
643
|
+
);
|
|
644
|
+
--kioku-theme-washi-letter-spacing-label: var(
|
|
645
|
+
--kioku-theme-letter-spacing-label
|
|
646
|
+
);
|
|
647
|
+
--kioku-theme-washi-letter-spacing-eyebrow: var(
|
|
648
|
+
--kioku-theme-letter-spacing-eyebrow
|
|
649
|
+
);
|
|
650
|
+
--kioku-theme-washi-letter-spacing-mono: var(
|
|
651
|
+
--kioku-theme-letter-spacing-mono
|
|
652
|
+
);
|
|
397
653
|
--kioku-theme-washi-spacing-xs: var(--kioku-theme-spacing-xs);
|
|
398
654
|
--kioku-theme-washi-spacing-sm: var(--kioku-theme-spacing-sm);
|
|
399
655
|
--kioku-theme-washi-spacing-md: var(--kioku-theme-spacing-md);
|
|
@@ -465,6 +721,7 @@
|
|
|
465
721
|
--kioku-theme-color-disabled-text
|
|
466
722
|
);
|
|
467
723
|
--kioku-theme-muji-color-focus: var(--kioku-theme-color-focus);
|
|
724
|
+
--kioku-theme-muji-color-scrim: var(--kioku-theme-color-scrim);
|
|
468
725
|
--kioku-theme-muji-border-default: var(--kioku-theme-border-default);
|
|
469
726
|
--kioku-theme-muji-border-strong: var(--kioku-theme-border-strong);
|
|
470
727
|
--kioku-theme-muji-border-interactive: var(--kioku-theme-border-interactive);
|
|
@@ -519,6 +776,24 @@
|
|
|
519
776
|
--kioku-theme-muji-line-height-heading: var(
|
|
520
777
|
--kioku-theme-line-height-heading
|
|
521
778
|
);
|
|
779
|
+
--kioku-theme-muji-letter-spacing-title: var(
|
|
780
|
+
--kioku-theme-letter-spacing-title
|
|
781
|
+
);
|
|
782
|
+
--kioku-theme-muji-letter-spacing-heading: var(
|
|
783
|
+
--kioku-theme-letter-spacing-heading
|
|
784
|
+
);
|
|
785
|
+
--kioku-theme-muji-letter-spacing-body: var(
|
|
786
|
+
--kioku-theme-letter-spacing-body
|
|
787
|
+
);
|
|
788
|
+
--kioku-theme-muji-letter-spacing-label: var(
|
|
789
|
+
--kioku-theme-letter-spacing-label
|
|
790
|
+
);
|
|
791
|
+
--kioku-theme-muji-letter-spacing-eyebrow: var(
|
|
792
|
+
--kioku-theme-letter-spacing-eyebrow
|
|
793
|
+
);
|
|
794
|
+
--kioku-theme-muji-letter-spacing-mono: var(
|
|
795
|
+
--kioku-theme-letter-spacing-mono
|
|
796
|
+
);
|
|
522
797
|
--kioku-theme-muji-spacing-xs: var(--kioku-theme-spacing-xs);
|
|
523
798
|
--kioku-theme-muji-spacing-sm: var(--kioku-theme-spacing-sm);
|
|
524
799
|
--kioku-theme-muji-spacing-md: var(--kioku-theme-spacing-md);
|
|
@@ -590,6 +865,7 @@
|
|
|
590
865
|
--kioku-theme-color-disabled-text
|
|
591
866
|
);
|
|
592
867
|
--kioku-theme-sumi-color-focus: var(--kioku-theme-color-focus);
|
|
868
|
+
--kioku-theme-sumi-color-scrim: var(--kioku-theme-color-scrim);
|
|
593
869
|
--kioku-theme-sumi-border-default: var(--kioku-theme-border-default);
|
|
594
870
|
--kioku-theme-sumi-border-strong: var(--kioku-theme-border-strong);
|
|
595
871
|
--kioku-theme-sumi-border-interactive: var(--kioku-theme-border-interactive);
|
|
@@ -644,6 +920,24 @@
|
|
|
644
920
|
--kioku-theme-sumi-line-height-heading: var(
|
|
645
921
|
--kioku-theme-line-height-heading
|
|
646
922
|
);
|
|
923
|
+
--kioku-theme-sumi-letter-spacing-title: var(
|
|
924
|
+
--kioku-theme-letter-spacing-title
|
|
925
|
+
);
|
|
926
|
+
--kioku-theme-sumi-letter-spacing-heading: var(
|
|
927
|
+
--kioku-theme-letter-spacing-heading
|
|
928
|
+
);
|
|
929
|
+
--kioku-theme-sumi-letter-spacing-body: var(
|
|
930
|
+
--kioku-theme-letter-spacing-body
|
|
931
|
+
);
|
|
932
|
+
--kioku-theme-sumi-letter-spacing-label: var(
|
|
933
|
+
--kioku-theme-letter-spacing-label
|
|
934
|
+
);
|
|
935
|
+
--kioku-theme-sumi-letter-spacing-eyebrow: var(
|
|
936
|
+
--kioku-theme-letter-spacing-eyebrow
|
|
937
|
+
);
|
|
938
|
+
--kioku-theme-sumi-letter-spacing-mono: var(
|
|
939
|
+
--kioku-theme-letter-spacing-mono
|
|
940
|
+
);
|
|
647
941
|
--kioku-theme-sumi-spacing-xs: var(--kioku-theme-spacing-xs);
|
|
648
942
|
--kioku-theme-sumi-spacing-sm: var(--kioku-theme-spacing-sm);
|
|
649
943
|
--kioku-theme-sumi-spacing-md: var(--kioku-theme-spacing-md);
|
|
@@ -680,9 +974,164 @@
|
|
|
680
974
|
);
|
|
681
975
|
}
|
|
682
976
|
|
|
977
|
+
[data-theme='kasumi'] {
|
|
978
|
+
--kioku-theme-kasumi-color-canvas: var(--kioku-theme-color-canvas);
|
|
979
|
+
--kioku-theme-kasumi-color-surface: var(--kioku-theme-color-surface);
|
|
980
|
+
--kioku-theme-kasumi-color-surface-raised: var(
|
|
981
|
+
--kioku-theme-color-surface-raised
|
|
982
|
+
);
|
|
983
|
+
--kioku-theme-kasumi-color-surface-muted: var(
|
|
984
|
+
--kioku-theme-color-surface-muted
|
|
985
|
+
);
|
|
986
|
+
--kioku-theme-kasumi-color-text: var(--kioku-theme-color-text);
|
|
987
|
+
--kioku-theme-kasumi-color-text-secondary: var(
|
|
988
|
+
--kioku-theme-color-text-secondary
|
|
989
|
+
);
|
|
990
|
+
--kioku-theme-kasumi-color-text-muted: var(--kioku-theme-color-text-muted);
|
|
991
|
+
--kioku-theme-kasumi-color-text-on-accent: var(
|
|
992
|
+
--kioku-theme-color-text-on-accent
|
|
993
|
+
);
|
|
994
|
+
--kioku-theme-kasumi-color-accent: var(--kioku-theme-color-accent);
|
|
995
|
+
--kioku-theme-kasumi-color-accent-hover: var(
|
|
996
|
+
--kioku-theme-color-accent-hover
|
|
997
|
+
);
|
|
998
|
+
--kioku-theme-kasumi-color-accent-active: var(
|
|
999
|
+
--kioku-theme-color-accent-active
|
|
1000
|
+
);
|
|
1001
|
+
--kioku-theme-kasumi-color-overlay-hover: var(
|
|
1002
|
+
--kioku-theme-color-overlay-hover
|
|
1003
|
+
);
|
|
1004
|
+
--kioku-theme-kasumi-color-overlay-active: var(
|
|
1005
|
+
--kioku-theme-color-overlay-active
|
|
1006
|
+
);
|
|
1007
|
+
--kioku-theme-kasumi-color-disabled-surface: var(
|
|
1008
|
+
--kioku-theme-color-disabled-surface
|
|
1009
|
+
);
|
|
1010
|
+
--kioku-theme-kasumi-color-disabled-text: var(
|
|
1011
|
+
--kioku-theme-color-disabled-text
|
|
1012
|
+
);
|
|
1013
|
+
--kioku-theme-kasumi-color-focus: var(--kioku-theme-color-focus);
|
|
1014
|
+
--kioku-theme-kasumi-color-scrim: var(--kioku-theme-color-scrim);
|
|
1015
|
+
--kioku-theme-kasumi-border-default: var(--kioku-theme-border-default);
|
|
1016
|
+
--kioku-theme-kasumi-border-strong: var(--kioku-theme-border-strong);
|
|
1017
|
+
--kioku-theme-kasumi-border-interactive: var(
|
|
1018
|
+
--kioku-theme-border-interactive
|
|
1019
|
+
);
|
|
1020
|
+
--kioku-theme-kasumi-border-disabled: var(--kioku-theme-border-disabled);
|
|
1021
|
+
--kioku-theme-kasumi-border-width: var(--kioku-theme-border-width);
|
|
1022
|
+
--kioku-theme-kasumi-border-style: var(--kioku-theme-border-style);
|
|
1023
|
+
--kioku-theme-kasumi-status-info-surface: var(
|
|
1024
|
+
--kioku-theme-status-info-surface
|
|
1025
|
+
);
|
|
1026
|
+
--kioku-theme-kasumi-status-info-text: var(--kioku-theme-status-info-text);
|
|
1027
|
+
--kioku-theme-kasumi-status-success-surface: var(
|
|
1028
|
+
--kioku-theme-status-success-surface
|
|
1029
|
+
);
|
|
1030
|
+
--kioku-theme-kasumi-status-success-text: var(
|
|
1031
|
+
--kioku-theme-status-success-text
|
|
1032
|
+
);
|
|
1033
|
+
--kioku-theme-kasumi-status-warning-surface: var(
|
|
1034
|
+
--kioku-theme-status-warning-surface
|
|
1035
|
+
);
|
|
1036
|
+
--kioku-theme-kasumi-status-warning-text: var(
|
|
1037
|
+
--kioku-theme-status-warning-text
|
|
1038
|
+
);
|
|
1039
|
+
--kioku-theme-kasumi-status-danger-surface: var(
|
|
1040
|
+
--kioku-theme-status-danger-surface
|
|
1041
|
+
);
|
|
1042
|
+
--kioku-theme-kasumi-status-danger-text: var(
|
|
1043
|
+
--kioku-theme-status-danger-text
|
|
1044
|
+
);
|
|
1045
|
+
--kioku-theme-kasumi-focus-width: var(--kioku-theme-focus-width);
|
|
1046
|
+
--kioku-theme-kasumi-focus-offset: var(--kioku-theme-focus-offset);
|
|
1047
|
+
--kioku-theme-kasumi-font-family-body: var(--kioku-theme-font-family-body);
|
|
1048
|
+
--kioku-theme-kasumi-font-family-heading: var(
|
|
1049
|
+
--kioku-theme-font-family-heading
|
|
1050
|
+
);
|
|
1051
|
+
--kioku-theme-kasumi-font-family-display: var(
|
|
1052
|
+
--kioku-theme-font-family-display
|
|
1053
|
+
);
|
|
1054
|
+
--kioku-theme-kasumi-font-family-mono: var(--kioku-theme-font-family-mono);
|
|
1055
|
+
--kioku-theme-kasumi-font-feature-settings: var(
|
|
1056
|
+
--kioku-theme-font-feature-settings
|
|
1057
|
+
);
|
|
1058
|
+
--kioku-theme-kasumi-font-size-xs: var(--kioku-theme-font-size-xs);
|
|
1059
|
+
--kioku-theme-kasumi-font-size-sm: var(--kioku-theme-font-size-sm);
|
|
1060
|
+
--kioku-theme-kasumi-font-size-md: var(--kioku-theme-font-size-md);
|
|
1061
|
+
--kioku-theme-kasumi-font-size-lg: var(--kioku-theme-font-size-lg);
|
|
1062
|
+
--kioku-theme-kasumi-font-size-xl: var(--kioku-theme-font-size-xl);
|
|
1063
|
+
--kioku-theme-kasumi-font-size-2xl: var(--kioku-theme-font-size-2xl);
|
|
1064
|
+
--kioku-theme-kasumi-font-weight-regular: var(
|
|
1065
|
+
--kioku-theme-font-weight-regular
|
|
1066
|
+
);
|
|
1067
|
+
--kioku-theme-kasumi-font-weight-medium: var(
|
|
1068
|
+
--kioku-theme-font-weight-medium
|
|
1069
|
+
);
|
|
1070
|
+
--kioku-theme-kasumi-font-weight-strong: var(
|
|
1071
|
+
--kioku-theme-font-weight-strong
|
|
1072
|
+
);
|
|
1073
|
+
--kioku-theme-kasumi-line-height-body: var(--kioku-theme-line-height-body);
|
|
1074
|
+
--kioku-theme-kasumi-line-height-heading: var(
|
|
1075
|
+
--kioku-theme-line-height-heading
|
|
1076
|
+
);
|
|
1077
|
+
--kioku-theme-kasumi-letter-spacing-title: var(
|
|
1078
|
+
--kioku-theme-letter-spacing-title
|
|
1079
|
+
);
|
|
1080
|
+
--kioku-theme-kasumi-letter-spacing-heading: var(
|
|
1081
|
+
--kioku-theme-letter-spacing-heading
|
|
1082
|
+
);
|
|
1083
|
+
--kioku-theme-kasumi-letter-spacing-body: var(
|
|
1084
|
+
--kioku-theme-letter-spacing-body
|
|
1085
|
+
);
|
|
1086
|
+
--kioku-theme-kasumi-letter-spacing-label: var(
|
|
1087
|
+
--kioku-theme-letter-spacing-label
|
|
1088
|
+
);
|
|
1089
|
+
--kioku-theme-kasumi-letter-spacing-eyebrow: var(
|
|
1090
|
+
--kioku-theme-letter-spacing-eyebrow
|
|
1091
|
+
);
|
|
1092
|
+
--kioku-theme-kasumi-letter-spacing-mono: var(
|
|
1093
|
+
--kioku-theme-letter-spacing-mono
|
|
1094
|
+
);
|
|
1095
|
+
--kioku-theme-kasumi-spacing-xs: var(--kioku-theme-spacing-xs);
|
|
1096
|
+
--kioku-theme-kasumi-spacing-sm: var(--kioku-theme-spacing-sm);
|
|
1097
|
+
--kioku-theme-kasumi-spacing-md: var(--kioku-theme-spacing-md);
|
|
1098
|
+
--kioku-theme-kasumi-spacing-lg: var(--kioku-theme-spacing-lg);
|
|
1099
|
+
--kioku-theme-kasumi-spacing-xl: var(--kioku-theme-spacing-xl);
|
|
1100
|
+
--kioku-theme-kasumi-spacing-2xl: var(--kioku-theme-spacing-2xl);
|
|
1101
|
+
--kioku-theme-kasumi-radius-inner: var(--kioku-theme-radius-inner);
|
|
1102
|
+
--kioku-theme-kasumi-radius-element: var(--kioku-theme-radius-element);
|
|
1103
|
+
--kioku-theme-kasumi-radius-container: var(--kioku-theme-radius-container);
|
|
1104
|
+
--kioku-theme-kasumi-radius-page: var(--kioku-theme-radius-page);
|
|
1105
|
+
--kioku-theme-kasumi-radius-full: var(--kioku-theme-radius-full);
|
|
1106
|
+
--kioku-theme-kasumi-size-control-sm: var(--kioku-theme-size-control-sm);
|
|
1107
|
+
--kioku-theme-kasumi-size-control-md: var(--kioku-theme-size-control-md);
|
|
1108
|
+
--kioku-theme-kasumi-size-control-lg: var(--kioku-theme-size-control-lg);
|
|
1109
|
+
--kioku-theme-kasumi-size-hit-target: var(--kioku-theme-size-hit-target);
|
|
1110
|
+
--kioku-theme-kasumi-elevation-low: var(--kioku-theme-elevation-low);
|
|
1111
|
+
--kioku-theme-kasumi-elevation-medium: var(--kioku-theme-elevation-medium);
|
|
1112
|
+
--kioku-theme-kasumi-elevation-high: var(--kioku-theme-elevation-high);
|
|
1113
|
+
--kioku-theme-kasumi-texture-grain: var(--kioku-theme-texture-grain);
|
|
1114
|
+
--kioku-theme-kasumi-motion-duration-fast: var(
|
|
1115
|
+
--kioku-theme-motion-duration-fast
|
|
1116
|
+
);
|
|
1117
|
+
--kioku-theme-kasumi-motion-duration-moderate: var(
|
|
1118
|
+
--kioku-theme-motion-duration-moderate
|
|
1119
|
+
);
|
|
1120
|
+
--kioku-theme-kasumi-motion-duration-slow: var(
|
|
1121
|
+
--kioku-theme-motion-duration-slow
|
|
1122
|
+
);
|
|
1123
|
+
--kioku-theme-kasumi-motion-easing-standard: var(
|
|
1124
|
+
--kioku-theme-motion-easing-standard
|
|
1125
|
+
);
|
|
1126
|
+
--kioku-theme-kasumi-motion-easing-emphasized: var(
|
|
1127
|
+
--kioku-theme-motion-easing-emphasized
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
683
1131
|
/* Chinese uses complete SC families inside each selected theme. */
|
|
684
1132
|
[data-theme='washi']:lang(zh),
|
|
685
|
-
[data-theme='sumi']:lang(zh)
|
|
1133
|
+
[data-theme='sumi']:lang(zh),
|
|
1134
|
+
[data-theme='kasumi']:lang(zh) {
|
|
686
1135
|
--kioku-theme-font-family-body:
|
|
687
1136
|
'Noto Sans SC', 'PingFang SC', 'Hiragino Sans GB', sans-serif;
|
|
688
1137
|
--kioku-theme-font-family-heading:
|
|
@@ -699,3 +1148,28 @@
|
|
|
699
1148
|
--kioku-theme-font-family-display:
|
|
700
1149
|
'Noto Sans SC', 'PingFang SC', 'Hiragino Sans GB', sans-serif;
|
|
701
1150
|
}
|
|
1151
|
+
|
|
1152
|
+
/*
|
|
1153
|
+
* Chinese also needs more air between lines than Latin does. A Latin line is
|
|
1154
|
+
* opened by its own ascenders and descenders; hanzi are square, dense and full
|
|
1155
|
+
* height, so consecutive lines close up at the leading that suits English.
|
|
1156
|
+
* Leading is a property of the writing system rather than of the skin, so it
|
|
1157
|
+
* sits with the families rather than in each theme — and it reaches every page
|
|
1158
|
+
* through `lineHeightBody`, which is what `Text` already sets.
|
|
1159
|
+
*/
|
|
1160
|
+
[data-theme='washi']:lang(zh),
|
|
1161
|
+
[data-theme='muji']:lang(zh),
|
|
1162
|
+
[data-theme='sumi']:lang(zh),
|
|
1163
|
+
[data-theme='kasumi']:lang(zh) {
|
|
1164
|
+
--kioku-theme-line-height-body: 1.8;
|
|
1165
|
+
|
|
1166
|
+
/* And more air between the characters, at both ranks. A han character is a
|
|
1167
|
+
square that already fills its em; set solid, a run of them closes into a
|
|
1168
|
+
grey block with no word boundaries for the eye to catch, because there are
|
|
1169
|
+
no spaces and no ascenders to break the line. Latin body text is set at 0
|
|
1170
|
+
for the same reason it does not need it — its own letterforms do the
|
|
1171
|
+
spacing. An 11px eyebrow needs the most of all: at that size the strokes
|
|
1172
|
+
of a dense character merge before the characters do. */
|
|
1173
|
+
--kioku-theme-letter-spacing-body: 0.03em;
|
|
1174
|
+
--kioku-theme-letter-spacing-eyebrow: 0.14em;
|
|
1175
|
+
}
|
package/dist/themes.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ import type { ThemeDefinition } from '@misoto22/kioku-ui/theme';
|
|
|
2
2
|
export declare const washiTheme: ThemeDefinition;
|
|
3
3
|
export declare const mujiTheme: ThemeDefinition;
|
|
4
4
|
export declare const sumiTheme: ThemeDefinition;
|
|
5
|
+
export declare const kasumiTheme: ThemeDefinition;
|
|
5
6
|
export declare const kiokuThemes: readonly ThemeDefinition[];
|
package/dist/themes.js
CHANGED
|
@@ -17,6 +17,7 @@ function themeTokenReferences(id) {
|
|
|
17
17
|
'color.disabledSurface': variable('color-disabled-surface'),
|
|
18
18
|
'color.disabledText': variable('color-disabled-text'),
|
|
19
19
|
'color.focus': variable('color-focus'),
|
|
20
|
+
'color.scrim': variable('color-scrim'),
|
|
20
21
|
'border.default': variable('border-default'),
|
|
21
22
|
'border.strong': variable('border-strong'),
|
|
22
23
|
'border.interactive': variable('border-interactive'),
|
|
@@ -49,6 +50,12 @@ function themeTokenReferences(id) {
|
|
|
49
50
|
'typography.fontWeightStrong': variable('font-weight-strong'),
|
|
50
51
|
'typography.lineHeightBody': variable('line-height-body'),
|
|
51
52
|
'typography.lineHeightHeading': variable('line-height-heading'),
|
|
53
|
+
'typography.letterSpacingTitle': variable('letter-spacing-title'),
|
|
54
|
+
'typography.letterSpacingHeading': variable('letter-spacing-heading'),
|
|
55
|
+
'typography.letterSpacingBody': variable('letter-spacing-body'),
|
|
56
|
+
'typography.letterSpacingLabel': variable('letter-spacing-label'),
|
|
57
|
+
'typography.letterSpacingEyebrow': variable('letter-spacing-eyebrow'),
|
|
58
|
+
'typography.letterSpacingMono': variable('letter-spacing-mono'),
|
|
52
59
|
'spacing.xs': variable('spacing-xs'),
|
|
53
60
|
'spacing.sm': variable('spacing-sm'),
|
|
54
61
|
'spacing.md': variable('spacing-md'),
|
|
@@ -85,8 +92,10 @@ function defineTheme(id, label) {
|
|
|
85
92
|
export const washiTheme = defineTheme('washi', 'Washi');
|
|
86
93
|
export const mujiTheme = defineTheme('muji', 'Muji');
|
|
87
94
|
export const sumiTheme = defineTheme('sumi', 'Sumi');
|
|
95
|
+
export const kasumiTheme = defineTheme('kasumi', 'Kasumi');
|
|
88
96
|
export const kiokuThemes = Object.freeze([
|
|
89
97
|
washiTheme,
|
|
90
98
|
mujiTheme,
|
|
91
99
|
sumiTheme,
|
|
100
|
+
kasumiTheme,
|
|
92
101
|
]);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@misoto22/kioku-ui-theme-kioku",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Kioku Washi, Muji, and
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Kioku Washi, Muji, Sumi, and Kasumi themes for Kioku UI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"./theme.css": "./dist/theme.css"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@misoto22/kioku-ui": ">=0.
|
|
36
|
+
"@misoto22/kioku-ui": ">=0.2.0",
|
|
37
37
|
"react": "^19.0.0",
|
|
38
38
|
"react-dom": "^19.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@misoto22/kioku-ui": "0.
|
|
41
|
+
"@misoto22/kioku-ui": "0.2.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -p tsconfig.build.json && node build.mjs",
|