@riebeckite/plugin-color-mode 0.0.12 → 0.0.13
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 +165 -165
- package/README_ja.md +135 -135
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
# @riebeckite/plugin-color-mode
|
|
2
|
-
|
|
3
|
-
Light / dark / system color-mode switching for Riebeckite sites. The control
|
|
4
|
-
writes to `data-theme` on `<html>` at runtime, exactly the attribute the
|
|
5
|
-
themes' CSS uses to pick a palette — so it works with every built-in theme and
|
|
6
|
-
needs no JavaScript in the theme itself.
|
|
7
|
-
|
|
8
|
-
[日本語](./README_ja.md)
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
Themes derive their palette from three CSS states (see
|
|
13
|
-
[theme-system.md](../../../docs/en/theme-
|
|
14
|
-
|
|
15
|
-
- `:root` — light
|
|
16
|
-
- `:root[data-theme="dark"]` — dark
|
|
17
|
-
- `@media (prefers-color-scheme: dark) { :root:not([data-theme]) }` — follow the OS ("system")
|
|
18
|
-
|
|
19
|
-
The plugin is a thin runtime switch over that contract:
|
|
20
|
-
|
|
21
|
-
- `ColorModeScript` — a one-line inline script for `<head>` that applies the
|
|
22
|
-
saved mode **before first paint**, preventing a flash of the wrong theme.
|
|
23
|
-
- `ColorModeToggle` — a segmented control with light / dark / system buttons.
|
|
24
|
-
- `initColorMode` — the client entry that binds the buttons, persists the
|
|
25
|
-
choice in `localStorage` and keeps the document in sync.
|
|
26
|
-
|
|
27
|
-
`colorModePlugin()` itself only registers the stylesheet and the client entry;
|
|
28
|
-
everything else is delivered through the two components you render in your site
|
|
29
|
-
shell.
|
|
30
|
-
|
|
31
|
-
## Usage
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
import { defineConfig } from "@riebeckite/core";
|
|
35
|
-
import { colorModePlugin } from "@riebeckite/plugin-color-mode";
|
|
36
|
-
|
|
37
|
-
export default defineConfig({
|
|
38
|
-
// ...
|
|
39
|
-
plugins: [colorModePlugin()],
|
|
40
|
-
});
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
`colorModePlugin()` bundles `style.css` and declares `initColorMode` as a client
|
|
44
|
-
entry.
|
|
45
|
-
|
|
46
|
-
### Render the components
|
|
47
|
-
|
|
48
|
-
```tsx
|
|
49
|
-
import { ColorModeScript, ColorModeToggle } from "@riebeckite/plugin-color-mode";
|
|
50
|
-
|
|
51
|
-
// ...in your renderer
|
|
52
|
-
return (
|
|
53
|
-
<html {...themeAttributes()}>
|
|
54
|
-
<head>
|
|
55
|
-
<ColorModeScript />
|
|
56
|
-
{/* stylesheets, ... */}
|
|
57
|
-
</head>
|
|
58
|
-
<body>
|
|
59
|
-
<header>
|
|
60
|
-
<ColorModeToggle />
|
|
61
|
-
</header>
|
|
62
|
-
{children}
|
|
63
|
-
</body>
|
|
64
|
-
</html>
|
|
65
|
-
);
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
`<ColorModeScript />` must be rendered in `<head>` ahead of the stylesheets so
|
|
69
|
-
the mode is set before CSS is applied. `<ColorModeToggle />` can go anywhere;
|
|
70
|
-
positions in headers and navbars are typical.
|
|
71
|
-
|
|
72
|
-
### Props
|
|
73
|
-
|
|
74
|
-
`ColorModeScript`
|
|
75
|
-
|
|
76
|
-
| Prop | Description |
|
|
77
|
-
| ---- | ----------- |
|
|
78
|
-
| `storageKey` | localStorage key to read from. Defaults to `riebeckite-color-mode`. |
|
|
79
|
-
|
|
80
|
-
`ColorModeToggle`
|
|
81
|
-
|
|
82
|
-
| Prop | Description |
|
|
83
|
-
| ---- | ----------- |
|
|
84
|
-
| `storageKey` | localStorage key to persist under. Defaults to `riebeckite-color-mode`. |
|
|
85
|
-
| `modes` | Modes to offer, in order. Defaults to `["light", "dark", "system"]`. |
|
|
86
|
-
| `labels` | Per-mode `aria-label` overrides: `{ light?, dark?, system? }`. |
|
|
87
|
-
| `label` | Group `aria-label`. Defaults to `"Color mode"`. |
|
|
88
|
-
|
|
89
|
-
Anything you configure here must be reflected on both components if you change
|
|
90
|
-
the storage key.
|
|
91
|
-
|
|
92
|
-
## How the mode is decided
|
|
93
|
-
|
|
94
|
-
1. On first paint, `ColorModeScript` applies the persisted value if it is a
|
|
95
|
-
valid mode (`light`, `dark` or `system`); otherwise it leaves the
|
|
96
|
-
`data-theme` the server already emitted (from your theme's `colorMode`).
|
|
97
|
-
2. On load, `initColorMode` repeats the same logic and syncs the buttons'
|
|
98
|
-
`aria-pressed` state.
|
|
99
|
-
3. Clicking a button persists the choice and re-applies it immediately.
|
|
100
|
-
`"system"` **removes** the `data-theme` attribute, so the OS preference CSS
|
|
101
|
-
takes over.
|
|
102
|
-
|
|
103
|
-
Since themes are presentation-only, the SSRed `data-theme` comes from your
|
|
104
|
-
theme's `colorMode`. The plugin only overrides it when the visitor has chosen
|
|
105
|
-
otherwise.
|
|
106
|
-
|
|
107
|
-
## CSS hooks
|
|
108
|
-
|
|
109
|
-
| Hook | Purpose |
|
|
110
|
-
| ---- | ------- |
|
|
111
|
-
| `rr-color-mode` | Root container of the toggle. |
|
|
112
|
-
| `rr-color-mode__button` | A single mode button. |
|
|
113
|
-
| `rr-color-mode__icon` | The inline SVG icon. |
|
|
114
|
-
|
|
115
|
-
The stylesheet uses `--rb-color-*` tokens, so the control follows the active
|
|
116
|
-
theme. The root is `display: none` until `initColorMode` (or the inline script)
|
|
117
|
-
sets `data-rb-color-mode="ready"` on `<html>`: with JavaScript disabled the
|
|
118
|
-
control never appears.
|
|
119
|
-
|
|
120
|
-
## Accessibility
|
|
121
|
-
|
|
122
|
-
- The container is a `<fieldset>` whose `<legend>` names the group (rendered
|
|
123
|
-
visually hidden).
|
|
124
|
-
- Each button is `type="button"` with an `aria-label` naming its mode; the
|
|
125
|
-
active one carries `aria-pressed="true"` set by the runtime.
|
|
126
|
-
- Icons are decorative (`aria-hidden`); labels come from the buttons.
|
|
127
|
-
- Transitions are disabled under `prefers-reduced-motion`.
|
|
128
|
-
|
|
129
|
-
## Events
|
|
130
|
-
|
|
131
|
-
`initColorMode` dispatches a `CustomEvent` on `document`:
|
|
132
|
-
|
|
133
|
-
```ts
|
|
134
|
-
document.addEventListener("riebeckite:color-mode", (event) => {
|
|
135
|
-
event.detail.mode; // "light" | "dark" | "system"
|
|
136
|
-
});
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
Nothing consumes it yet. It exists so integrations (for example re-rendering
|
|
140
|
-
diagrams) can follow mode changes in the future.
|
|
141
|
-
|
|
142
|
-
## Limitations
|
|
143
|
-
|
|
144
|
-
- Diagram plugins (`d2`, `mermaid`, `vega-lite`) read `data-theme` once at
|
|
145
|
-
initialization. After switching modes they keep their previous palette until
|
|
146
|
-
the page is reloaded. Listening for `riebeckite:color-mode` is the hook for a
|
|
147
|
-
future re-render.
|
|
148
|
-
- The inline script is subject to Content-Security-Policy. If your `script-src`
|
|
149
|
-
forbids inline scripts, allow it by nonce or hash.
|
|
150
|
-
- `localStorage` access is wrapped in `try/catch`; when storage is unavailable
|
|
151
|
-
the switch still works for the current page but is not persisted.
|
|
152
|
-
- Multiple toggles on one page should share the same `storageKey`.
|
|
153
|
-
|
|
154
|
-
## Exports
|
|
155
|
-
|
|
156
|
-
- `colorModePlugin()` — plugin factory
|
|
157
|
-
- `ColorModeToggle` — the switch component
|
|
158
|
-
- `ColorModeScript` — the before-paint inline script component
|
|
159
|
-
- `initColorMode` — browser init (also exported by `@riebeckite/plugin-color-mode/client`)
|
|
160
|
-
- Constants: `COLOR_MODES`, `COLOR_MODE_STORAGE_KEY`, `COLOR_MODE_EVENT` (and friends)
|
|
161
|
-
- Type: `ColorMode`
|
|
162
|
-
|
|
163
|
-
## See also
|
|
164
|
-
|
|
165
|
-
- [Theme system](../../../docs/en/theme-
|
|
1
|
+
# @riebeckite/plugin-color-mode
|
|
2
|
+
|
|
3
|
+
Light / dark / system color-mode switching for Riebeckite sites. The control
|
|
4
|
+
writes to `data-theme` on `<html>` at runtime, exactly the attribute the
|
|
5
|
+
themes' CSS uses to pick a palette — so it works with every built-in theme and
|
|
6
|
+
needs no JavaScript in the theme itself.
|
|
7
|
+
|
|
8
|
+
[日本語](./README_ja.md)
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Themes derive their palette from three CSS states (see
|
|
13
|
+
[theme-system.md](../../../docs/en/reference/theme-api.md)):
|
|
14
|
+
|
|
15
|
+
- `:root` — light
|
|
16
|
+
- `:root[data-theme="dark"]` — dark
|
|
17
|
+
- `@media (prefers-color-scheme: dark) { :root:not([data-theme]) }` — follow the OS ("system")
|
|
18
|
+
|
|
19
|
+
The plugin is a thin runtime switch over that contract:
|
|
20
|
+
|
|
21
|
+
- `ColorModeScript` — a one-line inline script for `<head>` that applies the
|
|
22
|
+
saved mode **before first paint**, preventing a flash of the wrong theme.
|
|
23
|
+
- `ColorModeToggle` — a segmented control with light / dark / system buttons.
|
|
24
|
+
- `initColorMode` — the client entry that binds the buttons, persists the
|
|
25
|
+
choice in `localStorage` and keeps the document in sync.
|
|
26
|
+
|
|
27
|
+
`colorModePlugin()` itself only registers the stylesheet and the client entry;
|
|
28
|
+
everything else is delivered through the two components you render in your site
|
|
29
|
+
shell.
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { defineConfig } from "@riebeckite/core";
|
|
35
|
+
import { colorModePlugin } from "@riebeckite/plugin-color-mode";
|
|
36
|
+
|
|
37
|
+
export default defineConfig({
|
|
38
|
+
// ...
|
|
39
|
+
plugins: [colorModePlugin()],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`colorModePlugin()` bundles `style.css` and declares `initColorMode` as a client
|
|
44
|
+
entry.
|
|
45
|
+
|
|
46
|
+
### Render the components
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { ColorModeScript, ColorModeToggle } from "@riebeckite/plugin-color-mode";
|
|
50
|
+
|
|
51
|
+
// ...in your renderer
|
|
52
|
+
return (
|
|
53
|
+
<html {...themeAttributes()}>
|
|
54
|
+
<head>
|
|
55
|
+
<ColorModeScript />
|
|
56
|
+
{/* stylesheets, ... */}
|
|
57
|
+
</head>
|
|
58
|
+
<body>
|
|
59
|
+
<header>
|
|
60
|
+
<ColorModeToggle />
|
|
61
|
+
</header>
|
|
62
|
+
{children}
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`<ColorModeScript />` must be rendered in `<head>` ahead of the stylesheets so
|
|
69
|
+
the mode is set before CSS is applied. `<ColorModeToggle />` can go anywhere;
|
|
70
|
+
positions in headers and navbars are typical.
|
|
71
|
+
|
|
72
|
+
### Props
|
|
73
|
+
|
|
74
|
+
`ColorModeScript`
|
|
75
|
+
|
|
76
|
+
| Prop | Description |
|
|
77
|
+
| ---- | ----------- |
|
|
78
|
+
| `storageKey` | localStorage key to read from. Defaults to `riebeckite-color-mode`. |
|
|
79
|
+
|
|
80
|
+
`ColorModeToggle`
|
|
81
|
+
|
|
82
|
+
| Prop | Description |
|
|
83
|
+
| ---- | ----------- |
|
|
84
|
+
| `storageKey` | localStorage key to persist under. Defaults to `riebeckite-color-mode`. |
|
|
85
|
+
| `modes` | Modes to offer, in order. Defaults to `["light", "dark", "system"]`. |
|
|
86
|
+
| `labels` | Per-mode `aria-label` overrides: `{ light?, dark?, system? }`. |
|
|
87
|
+
| `label` | Group `aria-label`. Defaults to `"Color mode"`. |
|
|
88
|
+
|
|
89
|
+
Anything you configure here must be reflected on both components if you change
|
|
90
|
+
the storage key.
|
|
91
|
+
|
|
92
|
+
## How the mode is decided
|
|
93
|
+
|
|
94
|
+
1. On first paint, `ColorModeScript` applies the persisted value if it is a
|
|
95
|
+
valid mode (`light`, `dark` or `system`); otherwise it leaves the
|
|
96
|
+
`data-theme` the server already emitted (from your theme's `colorMode`).
|
|
97
|
+
2. On load, `initColorMode` repeats the same logic and syncs the buttons'
|
|
98
|
+
`aria-pressed` state.
|
|
99
|
+
3. Clicking a button persists the choice and re-applies it immediately.
|
|
100
|
+
`"system"` **removes** the `data-theme` attribute, so the OS preference CSS
|
|
101
|
+
takes over.
|
|
102
|
+
|
|
103
|
+
Since themes are presentation-only, the SSRed `data-theme` comes from your
|
|
104
|
+
theme's `colorMode`. The plugin only overrides it when the visitor has chosen
|
|
105
|
+
otherwise.
|
|
106
|
+
|
|
107
|
+
## CSS hooks
|
|
108
|
+
|
|
109
|
+
| Hook | Purpose |
|
|
110
|
+
| ---- | ------- |
|
|
111
|
+
| `rr-color-mode` | Root container of the toggle. |
|
|
112
|
+
| `rr-color-mode__button` | A single mode button. |
|
|
113
|
+
| `rr-color-mode__icon` | The inline SVG icon. |
|
|
114
|
+
|
|
115
|
+
The stylesheet uses `--rb-color-*` tokens, so the control follows the active
|
|
116
|
+
theme. The root is `display: none` until `initColorMode` (or the inline script)
|
|
117
|
+
sets `data-rb-color-mode="ready"` on `<html>`: with JavaScript disabled the
|
|
118
|
+
control never appears.
|
|
119
|
+
|
|
120
|
+
## Accessibility
|
|
121
|
+
|
|
122
|
+
- The container is a `<fieldset>` whose `<legend>` names the group (rendered
|
|
123
|
+
visually hidden).
|
|
124
|
+
- Each button is `type="button"` with an `aria-label` naming its mode; the
|
|
125
|
+
active one carries `aria-pressed="true"` set by the runtime.
|
|
126
|
+
- Icons are decorative (`aria-hidden`); labels come from the buttons.
|
|
127
|
+
- Transitions are disabled under `prefers-reduced-motion`.
|
|
128
|
+
|
|
129
|
+
## Events
|
|
130
|
+
|
|
131
|
+
`initColorMode` dispatches a `CustomEvent` on `document`:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
document.addEventListener("riebeckite:color-mode", (event) => {
|
|
135
|
+
event.detail.mode; // "light" | "dark" | "system"
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Nothing consumes it yet. It exists so integrations (for example re-rendering
|
|
140
|
+
diagrams) can follow mode changes in the future.
|
|
141
|
+
|
|
142
|
+
## Limitations
|
|
143
|
+
|
|
144
|
+
- Diagram plugins (`d2`, `mermaid`, `vega-lite`) read `data-theme` once at
|
|
145
|
+
initialization. After switching modes they keep their previous palette until
|
|
146
|
+
the page is reloaded. Listening for `riebeckite:color-mode` is the hook for a
|
|
147
|
+
future re-render.
|
|
148
|
+
- The inline script is subject to Content-Security-Policy. If your `script-src`
|
|
149
|
+
forbids inline scripts, allow it by nonce or hash.
|
|
150
|
+
- `localStorage` access is wrapped in `try/catch`; when storage is unavailable
|
|
151
|
+
the switch still works for the current page but is not persisted.
|
|
152
|
+
- Multiple toggles on one page should share the same `storageKey`.
|
|
153
|
+
|
|
154
|
+
## Exports
|
|
155
|
+
|
|
156
|
+
- `colorModePlugin()` — plugin factory
|
|
157
|
+
- `ColorModeToggle` — the switch component
|
|
158
|
+
- `ColorModeScript` — the before-paint inline script component
|
|
159
|
+
- `initColorMode` — browser init (also exported by `@riebeckite/plugin-color-mode/client`)
|
|
160
|
+
- Constants: `COLOR_MODES`, `COLOR_MODE_STORAGE_KEY`, `COLOR_MODE_EVENT` (and friends)
|
|
161
|
+
- Type: `ColorMode`
|
|
162
|
+
|
|
163
|
+
## See also
|
|
164
|
+
|
|
165
|
+
- [Theme system](../../../docs/en/reference/theme-api.md)
|
|
166
166
|
- [`@riebeckite/plugin-ux`](../ux/README.md)
|
package/README_ja.md
CHANGED
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
# @riebeckite/plugin-color-mode
|
|
2
|
-
|
|
3
|
-
Riebeckite サイト向けのライト / ダーク / システム連動のカラーモード切替プラグインです。実行時に `<html>` の `data-theme` 属性へ書き込みます。これはテーマが配色を選ぶのに使う属性そのものなので、組み込みの全テーマで動作し、テーマ側に JavaScript は一切必要ありません。
|
|
4
|
-
|
|
5
|
-
[English](./README.md)
|
|
6
|
-
|
|
7
|
-
## 概要
|
|
8
|
-
|
|
9
|
-
テーマの配色は次の 3 つの CSS 状態で決まります([theme-system.md](../../../docs/ja/theme-
|
|
10
|
-
|
|
11
|
-
- `:root` — ライト
|
|
12
|
-
- `:root[data-theme="dark"]` — ダーク
|
|
13
|
-
- `@media (prefers-color-scheme: dark) { :root:not([data-theme]) }` — OS に追随(system)
|
|
14
|
-
|
|
15
|
-
プラグインはこの契約に対する薄い実行時スイッチです:
|
|
16
|
-
|
|
17
|
-
- `ColorModeScript` — `<head>` に置く 1 行のインラインスクリプト。**最初の描画の前に**保存済みモードを適用し、テーマのちらつき(FOUC)を防ぎます。
|
|
18
|
-
- `ColorModeToggle` — ライト / ダーク / システムのセグメント型コントロール。
|
|
19
|
-
- `initColorMode` — クライアントエントリ。ボタンの結線、`localStorage` への保存、ドキュメントの状態同期を行います。
|
|
20
|
-
|
|
21
|
-
`colorModePlugin()` はスタイルシートとクライアントエントリの登録だけを行います。UI はサイトシェルで描画する 2 つのコンポーネントから届きます。
|
|
22
|
-
|
|
23
|
-
## 使い方
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
import { defineConfig } from "@riebeckite/core";
|
|
27
|
-
import { colorModePlugin } from "@riebeckite/plugin-color-mode";
|
|
28
|
-
|
|
29
|
-
export default defineConfig({
|
|
30
|
-
// ...
|
|
31
|
-
plugins: [colorModePlugin()],
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
`colorModePlugin()` は `style.css` をバンドルし、`initColorMode` をクライアントエントリとして宣言します。
|
|
36
|
-
|
|
37
|
-
### コンポーネントの描画
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
import { ColorModeScript, ColorModeToggle } from "@riebeckite/plugin-color-mode";
|
|
41
|
-
|
|
42
|
-
// ...レンダラー内
|
|
43
|
-
return (
|
|
44
|
-
<html {...themeAttributes()}>
|
|
45
|
-
<head>
|
|
46
|
-
<ColorModeScript />
|
|
47
|
-
{/* スタイルシート, ... */}
|
|
48
|
-
</head>
|
|
49
|
-
<body>
|
|
50
|
-
<header>
|
|
51
|
-
<ColorModeToggle />
|
|
52
|
-
</header>
|
|
53
|
-
{children}
|
|
54
|
-
</body>
|
|
55
|
-
</html>
|
|
56
|
-
);
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
`<ColorModeScript />` は CSS が適用される前にモードが確定するよう、スタイルシートより先に `<head>` へ置いてください。`<ColorModeToggle />` はヘッダーやナビバーなど任意の場所に配置できます。
|
|
60
|
-
|
|
61
|
-
### Props
|
|
62
|
-
|
|
63
|
-
`ColorModeScript`
|
|
64
|
-
|
|
65
|
-
| Prop | 説明 |
|
|
66
|
-
| ---- | ---- |
|
|
67
|
-
| `storageKey` | 読み取り元の localStorage キー。既定値は `riebeckite-color-mode`。 |
|
|
68
|
-
|
|
69
|
-
`ColorModeToggle`
|
|
70
|
-
|
|
71
|
-
| Prop | 説明 |
|
|
72
|
-
| ---- | ---- |
|
|
73
|
-
| `storageKey` | 保存先の localStorage キー。既定値は `riebeckite-color-mode`。 |
|
|
74
|
-
| `modes` | 表示するモード(順序付き)。既定値は `["light", "dark", "system"]`。 |
|
|
75
|
-
| `labels` | モードごとの `aria-label` 上書き: `{ light?, dark?, system? }`。 |
|
|
76
|
-
| `label` | グループの先頭に置く可視非表示の `<legend>` として使われます。既定値は `"Color mode"`。 |
|
|
77
|
-
|
|
78
|
-
ストレージキーを変更する場合は、両コンポーネントで同じ値を指定してください。
|
|
79
|
-
|
|
80
|
-
## モードの決定方法
|
|
81
|
-
|
|
82
|
-
1. `ColorModeScript` が最初の描画時に保存値を適用します。値が有効なモード(`light` / `dark` / `system`)の場合のみ上書きし、それ以外はサーバーが出力した `data-theme`(テーマの `colorMode` 由来)をそのまま残します。
|
|
83
|
-
2. 読み込み時に `initColorMode` が同じ判定を行い、ボタンの `aria-pressed` を同期します。
|
|
84
|
-
3. ボタンを押すと選択を保存して即時に再適用します。`"system"` は `data-theme` 属性を**削除**し、OS の設定 CSS に委ねます。
|
|
85
|
-
|
|
86
|
-
テーマは表示のみを担当するため、SSR 時の `data-theme` はテーマの `colorMode` から生成されます。プラグインは訪問者が別のモードを選んだときだけ上書きします。
|
|
87
|
-
|
|
88
|
-
## CSS フック
|
|
89
|
-
|
|
90
|
-
| フック | 用途 |
|
|
91
|
-
| ---- | ---- |
|
|
92
|
-
| `rr-color-mode` | トグルのルートコンテナ。 |
|
|
93
|
-
| `rr-color-mode__button` | 個々のモードボタン。 |
|
|
94
|
-
| `rr-color-mode__icon` | インライン SVG アイコン。 |
|
|
95
|
-
|
|
96
|
-
スタイルシートは `--rb-color-*` トークンを使うため、アクティブなテーマに追従します。ルートは `display: none` で、`initColorMode`(またはインラインスクリプト)が `<html>` に `data-rb-color-mode="ready"` を付けるまで非表示です。JavaScript が無効なページではコントロールそのものが現れません。
|
|
97
|
-
|
|
98
|
-
## アクセシビリティ
|
|
99
|
-
|
|
100
|
-
- コンテナは `<fieldset>` で、グループ名は可視非表示の `<legend>`(`label` props)が提供します。
|
|
101
|
-
- 各ボタンは `type="button"` でモード名の `aria-label` を持ち、アクティブなボタンには実行時設定の `aria-pressed="true"` が付きます。
|
|
102
|
-
- アイコンは装飾(`aria-hidden`)。ラベルはボタンから提供されます。
|
|
103
|
-
- `prefers-reduced-motion` ではトランジションを無効化します。
|
|
104
|
-
|
|
105
|
-
## イベント
|
|
106
|
-
|
|
107
|
-
`initColorMode` は `document` 上で `CustomEvent` を発火します:
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
document.addEventListener("riebeckite:color-mode", (event) => {
|
|
111
|
-
event.detail.mode; // "light" | "dark" | "system"
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
現時点で消費するものはありません。図の再描画などの連携のための拡張ポイントです。
|
|
116
|
-
|
|
117
|
-
## 制約
|
|
118
|
-
|
|
119
|
-
- 図関連プラグイン(`d2` / `mermaid` / `vega-lite`)は初期化時にしか `data-theme` を読みません。モード切替後、リロードまでは前の配色のままです。将来の再描画のためのフックが `riebeckite:color-mode` イベントです。
|
|
120
|
-
- インラインスクリプトは Content-Security-Policy の影響を受けます。`script-src` がインラインを禁止している場合は nonce や hash で許可してください。
|
|
121
|
-
- `localStorage` へのアクセスは `try/catch` で保護しています。ストレージが使えない環境でも、そのページでは切替が機能します(永続化のみされません)。
|
|
122
|
-
- 1 ページに複数のトグルを置く場合は、同じ `storageKey` を共有してください。
|
|
123
|
-
|
|
124
|
-
## Exports
|
|
125
|
-
|
|
126
|
-
- `colorModePlugin()` — プラグインファクトリ
|
|
127
|
-
- `ColorModeToggle` — 切替コンポーネント
|
|
128
|
-
- `ColorModeScript` — 描画前インラインスクリプトのコンポーネント
|
|
129
|
-
- `initColorMode` — ブラウザ初期化関数(`@riebeckite/plugin-color-mode/client` からも export)
|
|
130
|
-
- 定数: `COLOR_MODES` / `COLOR_MODE_STORAGE_KEY` / `COLOR_MODE_EVENT` ほか
|
|
131
|
-
- 型: `ColorMode`
|
|
132
|
-
|
|
133
|
-
## 関連
|
|
134
|
-
|
|
135
|
-
- [テーマシステム](../../../docs/ja/theme-
|
|
1
|
+
# @riebeckite/plugin-color-mode
|
|
2
|
+
|
|
3
|
+
Riebeckite サイト向けのライト / ダーク / システム連動のカラーモード切替プラグインです。実行時に `<html>` の `data-theme` 属性へ書き込みます。これはテーマが配色を選ぶのに使う属性そのものなので、組み込みの全テーマで動作し、テーマ側に JavaScript は一切必要ありません。
|
|
4
|
+
|
|
5
|
+
[English](./README.md)
|
|
6
|
+
|
|
7
|
+
## 概要
|
|
8
|
+
|
|
9
|
+
テーマの配色は次の 3 つの CSS 状態で決まります([theme-system.md](../../../docs/ja/reference/theme-api.md) 参照):
|
|
10
|
+
|
|
11
|
+
- `:root` — ライト
|
|
12
|
+
- `:root[data-theme="dark"]` — ダーク
|
|
13
|
+
- `@media (prefers-color-scheme: dark) { :root:not([data-theme]) }` — OS に追随(system)
|
|
14
|
+
|
|
15
|
+
プラグインはこの契約に対する薄い実行時スイッチです:
|
|
16
|
+
|
|
17
|
+
- `ColorModeScript` — `<head>` に置く 1 行のインラインスクリプト。**最初の描画の前に**保存済みモードを適用し、テーマのちらつき(FOUC)を防ぎます。
|
|
18
|
+
- `ColorModeToggle` — ライト / ダーク / システムのセグメント型コントロール。
|
|
19
|
+
- `initColorMode` — クライアントエントリ。ボタンの結線、`localStorage` への保存、ドキュメントの状態同期を行います。
|
|
20
|
+
|
|
21
|
+
`colorModePlugin()` はスタイルシートとクライアントエントリの登録だけを行います。UI はサイトシェルで描画する 2 つのコンポーネントから届きます。
|
|
22
|
+
|
|
23
|
+
## 使い方
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { defineConfig } from "@riebeckite/core";
|
|
27
|
+
import { colorModePlugin } from "@riebeckite/plugin-color-mode";
|
|
28
|
+
|
|
29
|
+
export default defineConfig({
|
|
30
|
+
// ...
|
|
31
|
+
plugins: [colorModePlugin()],
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`colorModePlugin()` は `style.css` をバンドルし、`initColorMode` をクライアントエントリとして宣言します。
|
|
36
|
+
|
|
37
|
+
### コンポーネントの描画
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { ColorModeScript, ColorModeToggle } from "@riebeckite/plugin-color-mode";
|
|
41
|
+
|
|
42
|
+
// ...レンダラー内
|
|
43
|
+
return (
|
|
44
|
+
<html {...themeAttributes()}>
|
|
45
|
+
<head>
|
|
46
|
+
<ColorModeScript />
|
|
47
|
+
{/* スタイルシート, ... */}
|
|
48
|
+
</head>
|
|
49
|
+
<body>
|
|
50
|
+
<header>
|
|
51
|
+
<ColorModeToggle />
|
|
52
|
+
</header>
|
|
53
|
+
{children}
|
|
54
|
+
</body>
|
|
55
|
+
</html>
|
|
56
|
+
);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`<ColorModeScript />` は CSS が適用される前にモードが確定するよう、スタイルシートより先に `<head>` へ置いてください。`<ColorModeToggle />` はヘッダーやナビバーなど任意の場所に配置できます。
|
|
60
|
+
|
|
61
|
+
### Props
|
|
62
|
+
|
|
63
|
+
`ColorModeScript`
|
|
64
|
+
|
|
65
|
+
| Prop | 説明 |
|
|
66
|
+
| ---- | ---- |
|
|
67
|
+
| `storageKey` | 読み取り元の localStorage キー。既定値は `riebeckite-color-mode`。 |
|
|
68
|
+
|
|
69
|
+
`ColorModeToggle`
|
|
70
|
+
|
|
71
|
+
| Prop | 説明 |
|
|
72
|
+
| ---- | ---- |
|
|
73
|
+
| `storageKey` | 保存先の localStorage キー。既定値は `riebeckite-color-mode`。 |
|
|
74
|
+
| `modes` | 表示するモード(順序付き)。既定値は `["light", "dark", "system"]`。 |
|
|
75
|
+
| `labels` | モードごとの `aria-label` 上書き: `{ light?, dark?, system? }`。 |
|
|
76
|
+
| `label` | グループの先頭に置く可視非表示の `<legend>` として使われます。既定値は `"Color mode"`。 |
|
|
77
|
+
|
|
78
|
+
ストレージキーを変更する場合は、両コンポーネントで同じ値を指定してください。
|
|
79
|
+
|
|
80
|
+
## モードの決定方法
|
|
81
|
+
|
|
82
|
+
1. `ColorModeScript` が最初の描画時に保存値を適用します。値が有効なモード(`light` / `dark` / `system`)の場合のみ上書きし、それ以外はサーバーが出力した `data-theme`(テーマの `colorMode` 由来)をそのまま残します。
|
|
83
|
+
2. 読み込み時に `initColorMode` が同じ判定を行い、ボタンの `aria-pressed` を同期します。
|
|
84
|
+
3. ボタンを押すと選択を保存して即時に再適用します。`"system"` は `data-theme` 属性を**削除**し、OS の設定 CSS に委ねます。
|
|
85
|
+
|
|
86
|
+
テーマは表示のみを担当するため、SSR 時の `data-theme` はテーマの `colorMode` から生成されます。プラグインは訪問者が別のモードを選んだときだけ上書きします。
|
|
87
|
+
|
|
88
|
+
## CSS フック
|
|
89
|
+
|
|
90
|
+
| フック | 用途 |
|
|
91
|
+
| ---- | ---- |
|
|
92
|
+
| `rr-color-mode` | トグルのルートコンテナ。 |
|
|
93
|
+
| `rr-color-mode__button` | 個々のモードボタン。 |
|
|
94
|
+
| `rr-color-mode__icon` | インライン SVG アイコン。 |
|
|
95
|
+
|
|
96
|
+
スタイルシートは `--rb-color-*` トークンを使うため、アクティブなテーマに追従します。ルートは `display: none` で、`initColorMode`(またはインラインスクリプト)が `<html>` に `data-rb-color-mode="ready"` を付けるまで非表示です。JavaScript が無効なページではコントロールそのものが現れません。
|
|
97
|
+
|
|
98
|
+
## アクセシビリティ
|
|
99
|
+
|
|
100
|
+
- コンテナは `<fieldset>` で、グループ名は可視非表示の `<legend>`(`label` props)が提供します。
|
|
101
|
+
- 各ボタンは `type="button"` でモード名の `aria-label` を持ち、アクティブなボタンには実行時設定の `aria-pressed="true"` が付きます。
|
|
102
|
+
- アイコンは装飾(`aria-hidden`)。ラベルはボタンから提供されます。
|
|
103
|
+
- `prefers-reduced-motion` ではトランジションを無効化します。
|
|
104
|
+
|
|
105
|
+
## イベント
|
|
106
|
+
|
|
107
|
+
`initColorMode` は `document` 上で `CustomEvent` を発火します:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
document.addEventListener("riebeckite:color-mode", (event) => {
|
|
111
|
+
event.detail.mode; // "light" | "dark" | "system"
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
現時点で消費するものはありません。図の再描画などの連携のための拡張ポイントです。
|
|
116
|
+
|
|
117
|
+
## 制約
|
|
118
|
+
|
|
119
|
+
- 図関連プラグイン(`d2` / `mermaid` / `vega-lite`)は初期化時にしか `data-theme` を読みません。モード切替後、リロードまでは前の配色のままです。将来の再描画のためのフックが `riebeckite:color-mode` イベントです。
|
|
120
|
+
- インラインスクリプトは Content-Security-Policy の影響を受けます。`script-src` がインラインを禁止している場合は nonce や hash で許可してください。
|
|
121
|
+
- `localStorage` へのアクセスは `try/catch` で保護しています。ストレージが使えない環境でも、そのページでは切替が機能します(永続化のみされません)。
|
|
122
|
+
- 1 ページに複数のトグルを置く場合は、同じ `storageKey` を共有してください。
|
|
123
|
+
|
|
124
|
+
## Exports
|
|
125
|
+
|
|
126
|
+
- `colorModePlugin()` — プラグインファクトリ
|
|
127
|
+
- `ColorModeToggle` — 切替コンポーネント
|
|
128
|
+
- `ColorModeScript` — 描画前インラインスクリプトのコンポーネント
|
|
129
|
+
- `initColorMode` — ブラウザ初期化関数(`@riebeckite/plugin-color-mode/client` からも export)
|
|
130
|
+
- 定数: `COLOR_MODES` / `COLOR_MODE_STORAGE_KEY` / `COLOR_MODE_EVENT` ほか
|
|
131
|
+
- 型: `ColorMode`
|
|
132
|
+
|
|
133
|
+
## 関連
|
|
134
|
+
|
|
135
|
+
- [テーマシステム](../../../docs/ja/reference/theme-api.md)
|
|
136
136
|
- [`@riebeckite/plugin-ux`](../ux/README_ja.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-color-mode",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"hono": "^4.12.25",
|
|
25
|
-
"@riebeckite/core": "0.0.
|
|
25
|
+
"@riebeckite/core": "0.0.13"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|