@hadoku/task-ui-components 0.0.0-stage → 4.20.3
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/LICENSE +21 -0
- package/README.md +917 -2
- package/dist/app-header.css +288 -0
- package/dist/bento.css +143 -0
- package/dist/button.css +227 -0
- package/dist/components/AppHeader.d.ts +61 -0
- package/dist/components/AppHeader.d.ts.map +1 -0
- package/dist/components/AppHeader.js +23 -0
- package/dist/components/AppHeader.js.map +1 -0
- package/dist/components/BentoCard.d.ts +23 -0
- package/dist/components/BentoCard.d.ts.map +1 -0
- package/dist/components/BentoCard.js +49 -0
- package/dist/components/BentoCard.js.map +1 -0
- package/dist/components/BentoGrid.d.ts +24 -0
- package/dist/components/BentoGrid.d.ts.map +1 -0
- package/dist/components/BentoGrid.js +22 -0
- package/dist/components/BentoGrid.js.map +1 -0
- package/dist/components/Button.d.ts +28 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +51 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/ConnectedSettings.d.ts +53 -0
- package/dist/components/ConnectedSettings.d.ts.map +1 -0
- package/dist/components/ConnectedSettings.js +302 -0
- package/dist/components/ConnectedSettings.js.map +1 -0
- package/dist/components/ConnectedThemePicker.d.ts +52 -0
- package/dist/components/ConnectedThemePicker.d.ts.map +1 -0
- package/dist/components/ConnectedThemePicker.js +32 -0
- package/dist/components/ConnectedThemePicker.js.map +1 -0
- package/dist/components/ContextMenu.d.ts +22 -0
- package/dist/components/ContextMenu.d.ts.map +1 -0
- package/dist/components/ContextMenu.js +23 -0
- package/dist/components/ContextMenu.js.map +1 -0
- package/dist/components/HadokuThemePicker.d.ts +27 -0
- package/dist/components/HadokuThemePicker.d.ts.map +1 -0
- package/dist/components/HadokuThemePicker.js +19 -0
- package/dist/components/HadokuThemePicker.js.map +1 -0
- package/dist/components/LoadingSkeleton.d.ts +14 -0
- package/dist/components/LoadingSkeleton.d.ts.map +1 -0
- package/dist/components/LoadingSkeleton.js +62 -0
- package/dist/components/LoadingSkeleton.js.map +1 -0
- package/dist/components/Modal.d.ts +39 -0
- package/dist/components/Modal.d.ts.map +1 -0
- package/dist/components/Modal.js +106 -0
- package/dist/components/Modal.js.map +1 -0
- package/dist/components/NumberInput.d.ts +26 -0
- package/dist/components/NumberInput.d.ts.map +1 -0
- package/dist/components/NumberInput.js +131 -0
- package/dist/components/NumberInput.js.map +1 -0
- package/dist/components/Select.d.ts +52 -0
- package/dist/components/Select.d.ts.map +1 -0
- package/dist/components/Select.js +281 -0
- package/dist/components/Select.js.map +1 -0
- package/dist/components/SettingsModal.d.ts +69 -0
- package/dist/components/SettingsModal.d.ts.map +1 -0
- package/dist/components/SettingsModal.js +141 -0
- package/dist/components/SettingsModal.js.map +1 -0
- package/dist/components/ThemeIcons.d.ts +26 -0
- package/dist/components/ThemeIcons.d.ts.map +1 -0
- package/dist/components/ThemeIcons.js +74 -0
- package/dist/components/ThemeIcons.js.map +1 -0
- package/dist/components/ThemePicker.d.ts +28 -0
- package/dist/components/ThemePicker.d.ts.map +1 -0
- package/dist/components/ThemePicker.js +101 -0
- package/dist/components/ThemePicker.js.map +1 -0
- package/dist/components/Toast.d.ts +13 -0
- package/dist/components/Toast.d.ts.map +1 -0
- package/dist/components/Toast.js +70 -0
- package/dist/components/Toast.js.map +1 -0
- package/dist/components/Toaster.d.ts +19 -0
- package/dist/components/Toaster.d.ts.map +1 -0
- package/dist/components/Toaster.js +19 -0
- package/dist/components/Toaster.js.map +1 -0
- package/dist/components/Tooltip.d.ts +49 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +143 -0
- package/dist/components/Tooltip.js.map +1 -0
- package/dist/context-menu.css +11 -0
- package/dist/controls.css +137 -0
- package/dist/hooks/useReducedMotion.d.ts +7 -0
- package/dist/hooks/useReducedMotion.d.ts.map +1 -0
- package/dist/hooks/useReducedMotion.js +25 -0
- package/dist/hooks/useReducedMotion.js.map +1 -0
- package/dist/hooks/useToast.d.ts +18 -0
- package/dist/hooks/useToast.d.ts.map +1 -0
- package/dist/hooks/useToast.js +28 -0
- package/dist/hooks/useToast.js.map +1 -0
- package/dist/icon-btn.css +64 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/menuPlacement.d.ts +16 -0
- package/dist/lib/menuPlacement.d.ts.map +1 -0
- package/dist/lib/menuPlacement.js +19 -0
- package/dist/lib/menuPlacement.js.map +1 -0
- package/dist/lib/selectMenus.d.ts +30 -0
- package/dist/lib/selectMenus.d.ts.map +1 -0
- package/dist/lib/selectMenus.js +236 -0
- package/dist/lib/selectMenus.js.map +1 -0
- package/dist/lib/settingsClient.d.ts +120 -0
- package/dist/lib/settingsClient.d.ts.map +1 -0
- package/dist/lib/settingsClient.js +140 -0
- package/dist/lib/settingsClient.js.map +1 -0
- package/dist/lib/themeScope.d.ts +19 -0
- package/dist/lib/themeScope.d.ts.map +1 -0
- package/dist/lib/themeScope.js +10 -0
- package/dist/lib/themeScope.js.map +1 -0
- package/dist/lib/titleTooltips.d.ts +38 -0
- package/dist/lib/titleTooltips.d.ts.map +1 -0
- package/dist/lib/titleTooltips.js +166 -0
- package/dist/lib/titleTooltips.js.map +1 -0
- package/dist/lib/tooltipPlacement.d.ts +14 -0
- package/dist/lib/tooltipPlacement.d.ts.map +1 -0
- package/dist/lib/tooltipPlacement.js +34 -0
- package/dist/lib/tooltipPlacement.js.map +1 -0
- package/dist/modal.css +129 -0
- package/dist/number-input.css +131 -0
- package/dist/scrollbar.css +165 -0
- package/dist/select.css +251 -0
- package/dist/styles.css +1866 -0
- package/dist/task-ui-components.css +1866 -0
- package/dist/theme-picker.css +219 -0
- package/dist/toaster.css +159 -0
- package/dist/tooltip.css +103 -0
- package/dist/types/index.d.ts +37 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +60 -4
- package/src/app-header.css +288 -0
- package/src/bento.css +143 -0
- package/src/button.css +227 -0
- package/src/components/AppHeader.tsx +87 -0
- package/src/components/BentoCard.tsx +72 -0
- package/src/components/BentoGrid.tsx +48 -0
- package/src/components/Button.tsx +81 -0
- package/src/components/ConnectedSettings.tsx +465 -0
- package/src/components/ConnectedThemePicker.tsx +79 -0
- package/src/components/ContextMenu.tsx +48 -0
- package/src/components/HadokuThemePicker.tsx +39 -0
- package/src/components/LoadingSkeleton.tsx +84 -0
- package/src/components/Modal.tsx +171 -0
- package/src/components/NumberInput.tsx +161 -0
- package/src/components/Select.tsx +359 -0
- package/src/components/SettingsModal.tsx +235 -0
- package/src/components/ThemeIcons.tsx +127 -0
- package/src/components/ThemePicker.tsx +149 -0
- package/src/components/Toast.tsx +92 -0
- package/src/components/Toaster.tsx +43 -0
- package/src/components/Tooltip.tsx +212 -0
- package/src/context-menu.css +11 -0
- package/src/controls.css +137 -0
- package/src/hooks/useReducedMotion.ts +36 -0
- package/src/hooks/useToast.ts +57 -0
- package/src/icon-btn.css +64 -0
- package/src/index.ts +140 -0
- package/src/lib/menuPlacement.ts +31 -0
- package/src/lib/selectMenus.ts +303 -0
- package/src/lib/settingsClient.ts +377 -0
- package/src/lib/themeScope.ts +23 -0
- package/src/lib/titleTooltips.ts +236 -0
- package/src/lib/tooltipPlacement.ts +59 -0
- package/src/modal.css +129 -0
- package/src/number-input.css +131 -0
- package/src/scrollbar.css +165 -0
- package/src/select.css +251 -0
- package/src/theme-picker.css +219 -0
- package/src/toaster.css +159 -0
- package/src/tooltip.css +103 -0
- package/src/types/index.ts +43 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/* Themed scrollbars for @wolffm/task-ui-components.
|
|
2
|
+
*
|
|
3
|
+
* Without this, every scroller renders the platform's bar: a grey Windows
|
|
4
|
+
* gutter on a coffee or cyberpunk surface. `color-scheme` (set per theme in
|
|
5
|
+
* @wolffm/themes) only gets the bar to the right light/dark mode, not the
|
|
6
|
+
* theme's colours.
|
|
7
|
+
*
|
|
8
|
+
* import '@wolffm/task-ui-components/scrollbar.css'
|
|
9
|
+
* <div className="task-app-container hdk-scroll">…</div>
|
|
10
|
+
*
|
|
11
|
+
* `.hdk-scroll` styles the element it is on AND every scroller inside it, so
|
|
12
|
+
* one class on an app's root covers the whole app — hadoku_site puts it on
|
|
13
|
+
* <html>, which covers every micro-frontend at once. The thumb is the theme's
|
|
14
|
+
* primary colour.
|
|
15
|
+
*
|
|
16
|
+
* Every selector is wrapped in `:where()`, so all of this has ZERO
|
|
17
|
+
* specificity: it is a fallback for scrollers nobody styled. Any rule an app
|
|
18
|
+
* writes for a scroller — `scrollbar-width: none` on a carousel, its own
|
|
19
|
+
* `::-webkit-scrollbar` thumb — wins, whatever order the sheets load in.
|
|
20
|
+
* Modifiers sit on the same element:
|
|
21
|
+
*
|
|
22
|
+
* --subtle neutral thumb instead of the accent
|
|
23
|
+
* --thin narrower bar (WebKit/Chromium only; see Firefox below)
|
|
24
|
+
* --rail visible track, so the scroll extent reads at a glance
|
|
25
|
+
* --autohide thumb appears only while that scroller is hovered or focused
|
|
26
|
+
*
|
|
27
|
+
* The colours are declared on EVERY element under the root (`.hdk-scroll *`),
|
|
28
|
+
* not once on it. A custom property inherits its RESOLVED value, so a thumb
|
|
29
|
+
* colour set only on the root would carry the root's theme down into a nested
|
|
30
|
+
* `[data-theme]` scope: a cyberpunk preview inside a coffee app would scroll
|
|
31
|
+
* with coffee's accent. Declared per element, each scroller resolves the
|
|
32
|
+
* tokens of the theme it actually sits in. Sizes are theme-independent and
|
|
33
|
+
* simply inherit.
|
|
34
|
+
*
|
|
35
|
+
* Two engines, two mechanisms. Firefox only knows the standard
|
|
36
|
+
* `scrollbar-color`/`scrollbar-width`, and only ever gets `auto` width —
|
|
37
|
+
* `--thin` included. Under overlay scrollbars (GTK's default on Linux)
|
|
38
|
+
* `thin` draws the idle thumb as a ~1px hairline that antialiases
|
|
39
|
+
* unevenly along its length and only widens on hover; `auto` idles at a solid
|
|
40
|
+
* 2px and hovers at 6px, and with classic scrollbars it is a 6px thumb, the
|
|
41
|
+
* same as the WebKit default below. Chromium and Safari support the
|
|
42
|
+
* `::-webkit-scrollbar` pseudo-elements, which are the only way to get a
|
|
43
|
+
* rounded, inset thumb — but Chromium 121+ IGNORES them whenever
|
|
44
|
+
* `scrollbar-color` or `scrollbar-width` is non-auto, and `scrollbar-color`
|
|
45
|
+
* inherits. So the WebKit branch resets both to `auto`, or a host page that
|
|
46
|
+
* sets `scrollbar-color` on <html> would silently switch all of this off.
|
|
47
|
+
*
|
|
48
|
+
* Everything sits in `@layer hdk-fallbacks`. A rule in a cascade layer loses
|
|
49
|
+
* to every unlayered rule and to every layer declared after it — whatever
|
|
50
|
+
* either's specificity — and Tailwind ships its utilities in layers. Unlayered,
|
|
51
|
+
* even a zero-specificity rule here would beat `bg-primary`. The page must
|
|
52
|
+
* declare the layer FIRST, before any other, so it ranks lowest:
|
|
53
|
+
*
|
|
54
|
+
* @layer hdk-fallbacks, base, theme, utilities;
|
|
55
|
+
*
|
|
56
|
+
* hadoku_site's global.css does that. A sheet that never names it just gets
|
|
57
|
+
* these rules below its own unlayered ones, which is also correct.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
@layer hdk-fallbacks {
|
|
61
|
+
:where(.hdk-scroll) {
|
|
62
|
+
--hdk-scrollbar-size: 10px;
|
|
63
|
+
--hdk-scrollbar-pad: 2px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
:where(.hdk-scroll),
|
|
67
|
+
:where(.hdk-scroll *) {
|
|
68
|
+
--hdk-scrollbar-thumb: var(--color-primary);
|
|
69
|
+
--hdk-scrollbar-thumb-hover: var(--color-primary-dark);
|
|
70
|
+
--hdk-scrollbar-track: transparent;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:where(.hdk-scroll--thin) {
|
|
74
|
+
--hdk-scrollbar-size: 6px;
|
|
75
|
+
--hdk-scrollbar-pad: 1px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:where(.hdk-scroll--subtle),
|
|
79
|
+
:where(.hdk-scroll--subtle *) {
|
|
80
|
+
--hdk-scrollbar-thumb: var(--color-border);
|
|
81
|
+
--hdk-scrollbar-thumb-hover: var(--color-text-muted);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
:where(.hdk-scroll--rail) {
|
|
85
|
+
--hdk-scrollbar-size: 12px;
|
|
86
|
+
--hdk-scrollbar-pad: 3px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:where(.hdk-scroll--rail),
|
|
90
|
+
:where(.hdk-scroll--rail *) {
|
|
91
|
+
--hdk-scrollbar-track: var(--color-bg-hover);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:where(.hdk-scroll--autohide),
|
|
95
|
+
:where(.hdk-scroll--autohide *) {
|
|
96
|
+
--hdk-scrollbar-thumb: transparent;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* On the hovered/focused element itself, so only that scroller's thumb shows —
|
|
100
|
+
* not every scroller inside an autohide root at once. */
|
|
101
|
+
:where(.hdk-scroll--autohide:hover),
|
|
102
|
+
:where(.hdk-scroll--autohide:focus-within),
|
|
103
|
+
:where(.hdk-scroll--autohide :hover),
|
|
104
|
+
:where(.hdk-scroll--autohide :focus-within) {
|
|
105
|
+
--hdk-scrollbar-thumb: var(--color-primary);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@supports not selector(::-webkit-scrollbar) {
|
|
109
|
+
:where(.hdk-scroll),
|
|
110
|
+
:where(.hdk-scroll *) {
|
|
111
|
+
scrollbar-width: auto;
|
|
112
|
+
scrollbar-color: var(--hdk-scrollbar-thumb) var(--hdk-scrollbar-track);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@supports selector(::-webkit-scrollbar) {
|
|
117
|
+
:where(.hdk-scroll),
|
|
118
|
+
:where(.hdk-scroll *) {
|
|
119
|
+
scrollbar-width: auto;
|
|
120
|
+
scrollbar-color: auto;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
:where(.hdk-scroll)::-webkit-scrollbar,
|
|
124
|
+
:where(.hdk-scroll *)::-webkit-scrollbar {
|
|
125
|
+
width: var(--hdk-scrollbar-size);
|
|
126
|
+
height: var(--hdk-scrollbar-size);
|
|
127
|
+
background-color: var(--hdk-scrollbar-track);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
:where(.hdk-scroll)::-webkit-scrollbar-track,
|
|
131
|
+
:where(.hdk-scroll *)::-webkit-scrollbar-track {
|
|
132
|
+
background-color: var(--hdk-scrollbar-track);
|
|
133
|
+
border-radius: 999px;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* The transparent border plus padding-box clip is what insets the thumb
|
|
137
|
+
* from the track edge — a margin does nothing on a scrollbar part. */
|
|
138
|
+
:where(.hdk-scroll)::-webkit-scrollbar-thumb,
|
|
139
|
+
:where(.hdk-scroll *)::-webkit-scrollbar-thumb {
|
|
140
|
+
background-color: var(--hdk-scrollbar-thumb);
|
|
141
|
+
background-clip: padding-box;
|
|
142
|
+
border: var(--hdk-scrollbar-pad) solid transparent;
|
|
143
|
+
border-radius: 999px;
|
|
144
|
+
min-height: 32px;
|
|
145
|
+
min-width: 32px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
:where(.hdk-scroll)::-webkit-scrollbar-thumb:hover,
|
|
149
|
+
:where(.hdk-scroll *)::-webkit-scrollbar-thumb:hover,
|
|
150
|
+
:where(.hdk-scroll)::-webkit-scrollbar-thumb:active,
|
|
151
|
+
:where(.hdk-scroll *)::-webkit-scrollbar-thumb:active {
|
|
152
|
+
background-color: var(--hdk-scrollbar-thumb-hover);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
:where(.hdk-scroll)::-webkit-scrollbar-corner,
|
|
156
|
+
:where(.hdk-scroll *)::-webkit-scrollbar-corner {
|
|
157
|
+
background-color: transparent;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
:where(.hdk-scroll)::-webkit-scrollbar-button,
|
|
161
|
+
:where(.hdk-scroll *)::-webkit-scrollbar-button {
|
|
162
|
+
display: none;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
package/src/select.css
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/* Select / dropdown styles for @wolffm/task-ui-components.
|
|
2
|
+
*
|
|
3
|
+
* import '@wolffm/task-ui-components/select.css'
|
|
4
|
+
* import '@wolffm/task-ui-components/scrollbar.css' (the open list uses it)
|
|
5
|
+
*
|
|
6
|
+
* The trigger variants differ only in their resting surface; the open list
|
|
7
|
+
* is one look everywhere, so a page mixing variants still has one menu.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.hdk-select {
|
|
11
|
+
position: relative;
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
min-width: 0;
|
|
14
|
+
vertical-align: middle;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.hdk-select__trigger {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: 8px;
|
|
21
|
+
width: 100%;
|
|
22
|
+
min-width: 0;
|
|
23
|
+
font: inherit;
|
|
24
|
+
color: var(--color-text);
|
|
25
|
+
text-align: left;
|
|
26
|
+
background-color: var(--color-bg-card);
|
|
27
|
+
border: 1px solid var(--color-border);
|
|
28
|
+
border-radius: var(--hdk-radius);
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
transition:
|
|
31
|
+
border-color var(--transition-fast),
|
|
32
|
+
background-color var(--transition-fast),
|
|
33
|
+
box-shadow var(--transition-fast);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.hdk-select__trigger:hover:not(:disabled) {
|
|
37
|
+
border-color: var(--color-text-muted);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.hdk-select__trigger:focus-visible,
|
|
41
|
+
.hdk-select--open .hdk-select__trigger {
|
|
42
|
+
outline: none;
|
|
43
|
+
border-color: var(--color-primary);
|
|
44
|
+
box-shadow: var(--hdk-shadow-focus-sm);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.hdk-select__trigger:disabled {
|
|
48
|
+
opacity: 0.5;
|
|
49
|
+
cursor: not-allowed;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.hdk-select__value {
|
|
53
|
+
flex: 1;
|
|
54
|
+
min-width: 0;
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
text-overflow: ellipsis;
|
|
57
|
+
white-space: nowrap;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.hdk-select__value--placeholder {
|
|
61
|
+
color: var(--color-text-tertiary);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.hdk-select__chevron {
|
|
65
|
+
flex-shrink: 0;
|
|
66
|
+
color: var(--color-text-tertiary);
|
|
67
|
+
transition: transform var(--transition-fast);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.hdk-select--open .hdk-select__chevron {
|
|
71
|
+
transform: rotate(180deg);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ── trigger variants ─────────────────────────────────────────────────── */
|
|
75
|
+
|
|
76
|
+
.hdk-select--filled .hdk-select__trigger {
|
|
77
|
+
background-color: var(--color-bg-hover);
|
|
78
|
+
border-color: transparent;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.hdk-select--filled .hdk-select__trigger:hover:not(:disabled) {
|
|
82
|
+
border-color: var(--color-border);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.hdk-select--ghost .hdk-select__trigger {
|
|
86
|
+
background-color: transparent;
|
|
87
|
+
border-color: transparent;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.hdk-select--ghost .hdk-select__trigger:hover:not(:disabled) {
|
|
91
|
+
background-color: var(--color-bg-hover);
|
|
92
|
+
border-color: transparent;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.hdk-select--underline .hdk-select__trigger {
|
|
96
|
+
background-color: transparent;
|
|
97
|
+
border-color: transparent;
|
|
98
|
+
border-bottom-color: var(--color-border);
|
|
99
|
+
border-radius: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.hdk-select--underline .hdk-select__trigger:focus-visible,
|
|
103
|
+
.hdk-select--underline.hdk-select--open .hdk-select__trigger {
|
|
104
|
+
border-color: transparent;
|
|
105
|
+
border-bottom-color: var(--color-primary);
|
|
106
|
+
box-shadow: 0 1px 0 0 var(--color-primary);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ── sizes ────────────────────────────────────────────────────────────── */
|
|
110
|
+
|
|
111
|
+
.hdk-select--sm .hdk-select__trigger {
|
|
112
|
+
font-size: var(--hdk-text-xs);
|
|
113
|
+
padding: 4px 8px;
|
|
114
|
+
min-height: 28px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.hdk-select--md .hdk-select__trigger {
|
|
118
|
+
font-size: var(--hdk-text-sm);
|
|
119
|
+
padding: 7px 10px;
|
|
120
|
+
min-height: 34px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.hdk-select--lg .hdk-select__trigger {
|
|
124
|
+
font-size: var(--hdk-text-base);
|
|
125
|
+
padding: 10px 12px;
|
|
126
|
+
min-height: 42px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* ── open list ────────────────────────────────────────────────────────── */
|
|
130
|
+
|
|
131
|
+
.hdk-select__menu {
|
|
132
|
+
position: fixed;
|
|
133
|
+
z-index: 1000;
|
|
134
|
+
margin: 0;
|
|
135
|
+
padding: 4px;
|
|
136
|
+
list-style: none;
|
|
137
|
+
overflow-y: auto;
|
|
138
|
+
max-width: min(420px, calc(100vw - 16px));
|
|
139
|
+
background-color: var(--color-bg-card);
|
|
140
|
+
color: var(--color-text);
|
|
141
|
+
border: 1px solid var(--color-border);
|
|
142
|
+
border-radius: var(--hdk-radius-lg);
|
|
143
|
+
box-shadow: var(--hdk-shadow-lg);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.hdk-select__menu:focus {
|
|
147
|
+
outline: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.hdk-select--sm .hdk-select__menu {
|
|
151
|
+
font-size: var(--hdk-text-xs);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.hdk-select--md .hdk-select__menu {
|
|
155
|
+
font-size: var(--hdk-text-sm);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.hdk-select--lg .hdk-select__menu {
|
|
159
|
+
font-size: var(--hdk-text-base);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.hdk-select__option {
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: center;
|
|
165
|
+
gap: 8px;
|
|
166
|
+
padding: 7px 10px;
|
|
167
|
+
border-radius: var(--hdk-radius);
|
|
168
|
+
cursor: pointer;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.hdk-select__option--active {
|
|
172
|
+
background-color: var(--color-bg-hover);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.hdk-select__option--selected {
|
|
176
|
+
background-color: var(--color-primary-bg);
|
|
177
|
+
color: var(--color-on-primary-bg);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.hdk-select__option--selected.hdk-select__option--active {
|
|
181
|
+
box-shadow: inset 0 0 0 1px var(--color-primary);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* An <optgroup> label in a list installSelectMenus builds from a native select. */
|
|
185
|
+
.hdk-select__group {
|
|
186
|
+
padding: 8px 10px 2px;
|
|
187
|
+
font-size: 0.85em;
|
|
188
|
+
font-weight: var(--font-weight-semibold);
|
|
189
|
+
color: var(--color-text-secondary);
|
|
190
|
+
cursor: default;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.hdk-select__option[aria-disabled='true'] {
|
|
194
|
+
opacity: 0.45;
|
|
195
|
+
cursor: not-allowed;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.hdk-select__option-text {
|
|
199
|
+
display: flex;
|
|
200
|
+
flex-direction: column;
|
|
201
|
+
flex: 1;
|
|
202
|
+
min-width: 0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.hdk-select__option-label {
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
text-overflow: ellipsis;
|
|
208
|
+
white-space: nowrap;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.hdk-select__option-desc {
|
|
212
|
+
font-size: 0.85em;
|
|
213
|
+
color: var(--color-text-tertiary);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.hdk-select__option--selected .hdk-select__option-desc {
|
|
217
|
+
color: inherit;
|
|
218
|
+
opacity: 0.85;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.hdk-select__check {
|
|
222
|
+
flex-shrink: 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* ── native ───────────────────────────────────────────────────────────── */
|
|
226
|
+
|
|
227
|
+
/* Doubled class so the room for the chevron beats each size's `padding`
|
|
228
|
+
* shorthand above, which would otherwise draw the chevron over the text. */
|
|
229
|
+
.hdk-select__trigger.hdk-select__native {
|
|
230
|
+
appearance: none;
|
|
231
|
+
padding-right: 32px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.hdk-select--sm .hdk-select__trigger.hdk-select__native {
|
|
235
|
+
padding-right: 26px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.hdk-select__chevron--native {
|
|
239
|
+
position: absolute;
|
|
240
|
+
right: 10px;
|
|
241
|
+
top: 50%;
|
|
242
|
+
translate: 0 -50%;
|
|
243
|
+
pointer-events: none;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* The OS popup takes option colours from the <select>; without these, a dark
|
|
247
|
+
* theme can render dark-on-dark options in Chromium on Windows. */
|
|
248
|
+
.hdk-select__native option {
|
|
249
|
+
background-color: var(--color-bg-card);
|
|
250
|
+
color: var(--color-text);
|
|
251
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThemePicker Component Styles
|
|
3
|
+
* Beautiful theme picker with light/dark pill design
|
|
4
|
+
*
|
|
5
|
+
* Required CSS Variables (should be defined by @wolffm/themes):
|
|
6
|
+
* --color-text
|
|
7
|
+
* --color-primary
|
|
8
|
+
* --color-primary-hover
|
|
9
|
+
* --color-primary-bg
|
|
10
|
+
* --color-bg-card
|
|
11
|
+
* --color-text-secondary
|
|
12
|
+
* --hdk-shadow-focus-sm
|
|
13
|
+
* --hdk-shadow-md
|
|
14
|
+
* --hdk-shadow-lg
|
|
15
|
+
* --transition-fast (e.g., 0.15s ease)
|
|
16
|
+
* --hdk-space-sm (e.g., 8px)
|
|
17
|
+
* --hdk-space-md (e.g., 12px)
|
|
18
|
+
* --hdk-space-lg (e.g., 16px)
|
|
19
|
+
* --hdk-text-lg (e.g., 18px)
|
|
20
|
+
* --font-weight-semibold (e.g., 600)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
@import './icon-btn.css';
|
|
24
|
+
|
|
25
|
+
.theme-picker {
|
|
26
|
+
position: relative;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Theme toggle button: styled by the shared .app-header__icon-btn
|
|
30
|
+
* (icon-btn.css). `.theme-toggle-btn` stays on the element as a hook only —
|
|
31
|
+
* giving it values again would be the second copy that drifts. */
|
|
32
|
+
|
|
33
|
+
/* Theme picker overlay - covers entire viewport for click-outside detection */
|
|
34
|
+
.theme-picker__overlay {
|
|
35
|
+
position: fixed;
|
|
36
|
+
top: 0;
|
|
37
|
+
left: 0;
|
|
38
|
+
right: 0;
|
|
39
|
+
bottom: 0;
|
|
40
|
+
z-index: 99;
|
|
41
|
+
background: transparent;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Theme picker dropdown - positioned relative to picker button */
|
|
45
|
+
.theme-picker__dropdown {
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 0;
|
|
48
|
+
left: calc(100% + var(--hdk-space-md));
|
|
49
|
+
z-index: 100;
|
|
50
|
+
display: flex;
|
|
51
|
+
flex-direction: column;
|
|
52
|
+
align-items: flex-start;
|
|
53
|
+
gap: var(--hdk-space-sm);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Inner row: pill tower + settings icon side-by-side */
|
|
57
|
+
.theme-picker__main {
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: flex-start;
|
|
60
|
+
gap: var(--hdk-space-md);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Open-left modifier: dropdown opens to the left of the toggle */
|
|
64
|
+
.theme-picker--open-left .theme-picker__dropdown {
|
|
65
|
+
left: auto;
|
|
66
|
+
right: calc(100% + var(--hdk-space-md));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.theme-picker--open-left .theme-picker__main {
|
|
70
|
+
flex-direction: row-reverse;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Theme pill tower - has the shadow */
|
|
74
|
+
.theme-picker__pills {
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
gap: 0; /* No gap - pancake stack */
|
|
78
|
+
border-radius: 12px;
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
box-shadow: var(--hdk-shadow-lg); /* Shadow on pill tower only */
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Theme pill - contains light and dark buttons */
|
|
84
|
+
.theme-pill {
|
|
85
|
+
display: flex;
|
|
86
|
+
gap: 0;
|
|
87
|
+
background: transparent;
|
|
88
|
+
border: none;
|
|
89
|
+
transition: all var(--transition-fast, 0.15s ease);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Separator line between pills */
|
|
93
|
+
.theme-pill:not(:last-child) {
|
|
94
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Theme pill buttons */
|
|
98
|
+
.theme-pill__btn {
|
|
99
|
+
flex: 1;
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
padding: calc(var(--hdk-space-lg) * 1.2); /* 20% bigger total (10% + 10%) */
|
|
104
|
+
border: none;
|
|
105
|
+
background: transparent;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
transition: all var(--transition-fast, 0.15s ease);
|
|
108
|
+
position: relative;
|
|
109
|
+
overflow: visible; /* Allow border to show */
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* The light/dark pills are the mode toggle itself: they must always LOOK light
|
|
113
|
+
and dark so the control reads correctly whichever theme is active. These
|
|
114
|
+
literals are deliberate and are the one place theme tokens must not be used. */
|
|
115
|
+
|
|
116
|
+
/* Light button default style */
|
|
117
|
+
.theme-pill__btn--light {
|
|
118
|
+
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
|
119
|
+
color: #1e293b;
|
|
120
|
+
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Dark button default style - more cyber with darker background and blue tint */
|
|
124
|
+
.theme-pill__btn--dark {
|
|
125
|
+
background: linear-gradient(135deg, #0f172a 0%, #020617 100%);
|
|
126
|
+
color: #64748b;
|
|
127
|
+
border-left: 1px solid rgba(100, 116, 139, 0.1);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* First pill top-left corner rounding - rounded corner instead of full circle */
|
|
131
|
+
.theme-pill:first-child .theme-pill__btn--light {
|
|
132
|
+
border-top-left-radius: 12px;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* First pill top-right corner rounding */
|
|
136
|
+
.theme-pill:first-child .theme-pill__btn--dark {
|
|
137
|
+
border-top-right-radius: 12px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* Last pill bottom-left corner rounding */
|
|
141
|
+
.theme-pill:last-child .theme-pill__btn--light {
|
|
142
|
+
border-bottom-left-radius: 12px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Last pill bottom-right corner rounding */
|
|
146
|
+
.theme-pill:last-child .theme-pill__btn--dark {
|
|
147
|
+
border-bottom-right-radius: 12px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.theme-pill__btn--light:hover {
|
|
151
|
+
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
|
|
152
|
+
color: var(--color-primary);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.theme-pill__btn--dark:hover {
|
|
156
|
+
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
|
|
157
|
+
color: #cbd5e1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* Active states - with proper border radius that doesn't clip, 10% bigger border */
|
|
161
|
+
.theme-pill__btn--light.active {
|
|
162
|
+
background: linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%);
|
|
163
|
+
color: var(--color-primary);
|
|
164
|
+
box-shadow: inset 0 0 0 2.2px var(--color-primary); /* Uses theme primary color */
|
|
165
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.theme-pill__btn--dark.active {
|
|
169
|
+
background: linear-gradient(135deg, #020617 0%, #000000 100%);
|
|
170
|
+
color: var(--color-primary); /* Use theme primary color */
|
|
171
|
+
box-shadow: inset 0 0 0 2.2px var(--color-primary); /* Use theme primary color */
|
|
172
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
173
|
+
/* Add glow effect for cyber look */
|
|
174
|
+
filter: brightness(1.1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Icon container - reduced by ~15% (24px -> 20px) */
|
|
178
|
+
.theme-pill__icon {
|
|
179
|
+
display: flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
justify-content: center;
|
|
182
|
+
width: 20px;
|
|
183
|
+
height: 20px;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.theme-pill__icon svg {
|
|
187
|
+
width: 100%;
|
|
188
|
+
height: 100%;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Settings icon button - circular, separate from pill tower */
|
|
192
|
+
.theme-picker__settings-icon {
|
|
193
|
+
display: flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
justify-content: center;
|
|
196
|
+
width: 44px;
|
|
197
|
+
height: 44px;
|
|
198
|
+
padding: 0;
|
|
199
|
+
border: none;
|
|
200
|
+
background: var(--color-bg-card);
|
|
201
|
+
color: var(--color-text-secondary);
|
|
202
|
+
cursor: pointer;
|
|
203
|
+
transition: all var(--transition-fast, 0.15s ease);
|
|
204
|
+
border-radius: 50%; /* Circular */
|
|
205
|
+
box-shadow: var(--hdk-shadow-md);
|
|
206
|
+
flex-shrink: 0;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.theme-picker__settings-icon:hover {
|
|
210
|
+
background: var(--color-primary-bg);
|
|
211
|
+
color: var(--color-on-primary-bg);
|
|
212
|
+
transform: rotate(45deg);
|
|
213
|
+
box-shadow: var(--hdk-shadow-lg);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.theme-picker__settings-icon svg {
|
|
217
|
+
width: 20px;
|
|
218
|
+
height: 20px;
|
|
219
|
+
}
|