@kolkrabbi/kol-framework 0.5.10 → 0.5.11
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/package.json +4 -4
- package/src/ThemeToggle.jsx +37 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-framework",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.11",
|
|
4
4
|
"description": "KOL app shell — sidenav, layout, theme toggle, footer, heroes + brand color layer. SideNav takes nav data as props so the tree stays app-local.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"app-shell"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@kolkrabbi/kol-component": "
|
|
31
|
-
"@kolkrabbi/kol-icons": "
|
|
30
|
+
"@kolkrabbi/kol-component": "workspace:*",
|
|
31
|
+
"@kolkrabbi/kol-icons": "workspace:*"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": "^18.3.0 || ^19.0.0",
|
|
@@ -43,4 +43,4 @@
|
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|
|
45
45
|
}
|
|
46
|
-
}
|
|
46
|
+
}
|
package/src/ThemeToggle.jsx
CHANGED
|
@@ -9,6 +9,11 @@ import { useTheme } from './theme.js'
|
|
|
9
9
|
* → 14/16/18px glyph, square box + quiet states from the
|
|
10
10
|
* .kol-btn-nav chrome (theme ≥0.11.4), so the toggle sits flush
|
|
11
11
|
* with sibling navigation buttons in a bar.
|
|
12
|
+
* button — a REAL ladder button (2026-07-29, user-ordered): glyph + label
|
|
13
|
+
* inside plain `.kol-btn .kol-btn-primary .kol-btn-{size}` with
|
|
14
|
+
* the rung's mono type and pairing-law glyph (16/20/24) — no
|
|
15
|
+
* width/justify overrides, so it measures exactly like any
|
|
16
|
+
* other kol-btn on the rung.
|
|
12
17
|
* hop — full-width labeled Button-primary-styled sidenav row
|
|
13
18
|
* (bg-fg-04, on-primary text). For sidenav rows where it pairs
|
|
14
19
|
* with other Button-primary "hop" entries.
|
|
@@ -19,9 +24,10 @@ import { useTheme } from './theme.js'
|
|
|
19
24
|
* Theme state lives in useTheme (./theme.js) — the exported machinery
|
|
20
25
|
* (initial-state resolution, saved-choice re-stamp, system-follow, cross-
|
|
21
26
|
* instance sync). This component is only the icon-swap UI on top of it.
|
|
22
|
-
* The icon-swap
|
|
23
|
-
*
|
|
24
|
-
*
|
|
27
|
+
* The icon-swap slides a doubled `mode-toggle-01` (v1 set) horizontally
|
|
28
|
+
* while both glyphs spin 180° in the same clock — the split-circle rolls
|
|
29
|
+
* forward (>>) on dark→light and rolls back (<<) on light→dark (the
|
|
30
|
+
* original roll behavior, restored 2026-07-29).
|
|
25
31
|
*/
|
|
26
32
|
export default function ThemeToggle({ variant = 'icon', size = 'md', className = '' }) {
|
|
27
33
|
const { isDark, toggle } = useTheme()
|
|
@@ -29,6 +35,12 @@ export default function ThemeToggle({ variant = 'icon', size = 'md', className =
|
|
|
29
35
|
const next = isDark ? 'light' : 'dark'
|
|
30
36
|
const handleToggle = toggle
|
|
31
37
|
|
|
38
|
+
/* The roll: the strip slides one glyph-width while each glyph spins 180° in
|
|
39
|
+
* the same clock — dark→light rolls forward (>>), light→dark rolls back (<<). */
|
|
40
|
+
const glyphSpin = {
|
|
41
|
+
transform: isDark ? 'rotate(0deg)' : 'rotate(180deg)',
|
|
42
|
+
lineHeight: 0,
|
|
43
|
+
}
|
|
32
44
|
const iconSwap = (size) => (
|
|
33
45
|
<span
|
|
34
46
|
className="relative inline-block overflow-hidden"
|
|
@@ -39,12 +51,32 @@ export default function ThemeToggle({ variant = 'icon', size = 'md', className =
|
|
|
39
51
|
className="flex transition-transform duration-500 ease-in-out"
|
|
40
52
|
style={{ width: size * 2, transform: isDark ? 'translateX(0)' : `translateX(-${size}px)` }}
|
|
41
53
|
>
|
|
42
|
-
<
|
|
43
|
-
|
|
54
|
+
<span className="inline-flex transition-transform duration-500 ease-in-out" style={glyphSpin}>
|
|
55
|
+
<Icon name="mode-toggle-01" size={size} />
|
|
56
|
+
</span>
|
|
57
|
+
<span className="inline-flex transition-transform duration-500 ease-in-out" style={glyphSpin}>
|
|
58
|
+
<Icon name="mode-toggle-01" size={size} />
|
|
59
|
+
</span>
|
|
44
60
|
</span>
|
|
45
61
|
</span>
|
|
46
62
|
)
|
|
47
63
|
|
|
64
|
+
if (variant === 'button') {
|
|
65
|
+
const mono = size === 'sm' ? 'kol-mono-12' : size === 'lg' ? 'kol-mono-16' : 'kol-mono-14'
|
|
66
|
+
const glyph = size === 'sm' ? 16 : size === 'lg' ? 24 : 20
|
|
67
|
+
return (
|
|
68
|
+
<button
|
|
69
|
+
type="button"
|
|
70
|
+
onClick={handleToggle}
|
|
71
|
+
aria-label={`Switch to ${next} mode`}
|
|
72
|
+
className={`kol-btn kol-btn-primary kol-btn-${size} ${mono} gap-2 ${className}`.trim()}
|
|
73
|
+
>
|
|
74
|
+
{iconSwap(glyph)}
|
|
75
|
+
<span>{isDark ? 'Dark mode' : 'Light mode'}</span>
|
|
76
|
+
</button>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
48
80
|
if (variant === 'hop' || variant === 'hop-bare') {
|
|
49
81
|
const bare = variant === 'hop-bare'
|
|
50
82
|
const chromeCls = bare
|