@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.2.38 → 0.2.39
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/CHANGELOG.md +1 -1
- package/dist/components/ui/theme-toggle.d.ts.map +1 -1
- package/dist/components/ui/theme-toggle.esm.js +12 -3
- package/dist/components/ui/theme-toggle.js +12 -3
- package/dist/styles.css +310 -10
- package/package.json +1 -1
- package/src/components/ui/theme-toggle.tsx +19 -4
- package/src/styles/components/base/button.css +1 -8
- package/src/styles/components/ui/index.css +4 -0
- package/src/styles/components/ui/theme-toggle.css +200 -0
- package/src/styles/layers/index.css +1 -0
- package/src/styles/utilities/design-system-utilities.css +95 -0
- package/src/styles/utilities/index.css +3 -0
package/package.json
CHANGED
|
@@ -9,9 +9,19 @@ export const ThemeToggle: React.FC = () => {
|
|
|
9
9
|
const [isDark, setIsDark] = useState(false);
|
|
10
10
|
|
|
11
11
|
useEffect(() => {
|
|
12
|
-
// Check initial theme
|
|
13
|
-
const
|
|
12
|
+
// Check initial theme from localStorage and DOM
|
|
13
|
+
const savedTheme = localStorage.getItem('theme');
|
|
14
|
+
const isDarkMode = savedTheme === 'dark' ||
|
|
15
|
+
(savedTheme === null && document.documentElement.classList.contains('dark'));
|
|
16
|
+
|
|
14
17
|
setIsDark(isDarkMode);
|
|
18
|
+
|
|
19
|
+
// Ensure DOM is in sync
|
|
20
|
+
if (isDarkMode) {
|
|
21
|
+
document.documentElement.classList.add('dark');
|
|
22
|
+
} else {
|
|
23
|
+
document.documentElement.classList.remove('dark');
|
|
24
|
+
}
|
|
15
25
|
}, []);
|
|
16
26
|
|
|
17
27
|
const toggleTheme = () => {
|
|
@@ -32,10 +42,15 @@ export const ThemeToggle: React.FC = () => {
|
|
|
32
42
|
variant="ghost"
|
|
33
43
|
size="sm"
|
|
34
44
|
onClick={toggleTheme}
|
|
35
|
-
className="h-8 w-8 px-0"
|
|
45
|
+
className="theme-toggle h-8 w-8 px-0"
|
|
36
46
|
aria-label={`Switch to ${isDark ? 'light' : 'dark'} mode`}
|
|
47
|
+
aria-pressed={isDark}
|
|
37
48
|
>
|
|
38
|
-
{isDark ?
|
|
49
|
+
{isDark ? (
|
|
50
|
+
<Sun className="h-4 w-4 sun-icon" />
|
|
51
|
+
) : (
|
|
52
|
+
<Moon className="h-4 w-4 moon-icon" />
|
|
53
|
+
)}
|
|
39
54
|
</Button>
|
|
40
55
|
);
|
|
41
56
|
};
|
|
@@ -529,14 +529,7 @@
|
|
|
529
529
|
border-color: var(--cs-modes-dark-colors-border);
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
-
|
|
533
|
-
color: var(--cs-modes-dark-colors-text-secondary);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
.dark .button--variant-ghost:hover {
|
|
537
|
-
background-color: var(--cs-modes-dark-colors-interactive-hover);
|
|
538
|
-
color: var(--cs-modes-dark-colors-text-primary);
|
|
539
|
-
}
|
|
532
|
+
/* Ghost variant automatically adapts to theme via CSS variables */
|
|
540
533
|
|
|
541
534
|
.dark .button--variant-destructive {
|
|
542
535
|
background-color: var(--cs-modes-dark-colors-semantic-error);
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/* ThemeToggle Component Styles */
|
|
2
|
+
/* Using semantic CSS architecture with CSS variables and BEM methodology */
|
|
3
|
+
|
|
4
|
+
/* ThemeToggle Component CSS Variables */
|
|
5
|
+
:root {
|
|
6
|
+
/* ThemeToggle Base Variables */
|
|
7
|
+
--theme-toggle-transition: var(--cs-transitions-properties-colors);
|
|
8
|
+
--theme-toggle-icon-size: var(--cs-spacing-scale-md);
|
|
9
|
+
--theme-toggle-background: transparent;
|
|
10
|
+
|
|
11
|
+
/* ThemeToggle Color Variables - using theme-aware design system variables */
|
|
12
|
+
--theme-toggle-text: var(--cs-colors-text-secondary);
|
|
13
|
+
--theme-toggle-text-hover: var(--cs-colors-text-primary);
|
|
14
|
+
--theme-toggle-background-hover: var(--cs-colors-interactive-hover);
|
|
15
|
+
--theme-toggle-focus-ring: var(--cs-colors-primary);
|
|
16
|
+
|
|
17
|
+
/* ThemeToggle State Variables */
|
|
18
|
+
--theme-toggle-active-background: var(--cs-colors-interactive-active);
|
|
19
|
+
--theme-toggle-active-text: var(--cs-colors-primary);
|
|
20
|
+
|
|
21
|
+
/* ThemeToggle Animation Variables */
|
|
22
|
+
--theme-toggle-animation-duration: var(--cs-animation-duration-fast);
|
|
23
|
+
--theme-toggle-animation-easing: var(--cs-animation-easing-ease-out);
|
|
24
|
+
--theme-toggle-transform-scale: var(--cs-animation-transforms-scale);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Base ThemeToggle Styles */
|
|
28
|
+
@layer components {
|
|
29
|
+
|
|
30
|
+
.theme-toggle {
|
|
31
|
+
position: relative;
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
color: var(--theme-toggle-text);
|
|
36
|
+
background-color: var(--theme-toggle-background);
|
|
37
|
+
transition: var(--theme-toggle-transition);
|
|
38
|
+
border-radius: var(--cs-border-radius-sm);
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* ThemeToggle Icon Styles */
|
|
44
|
+
.theme-toggle svg {
|
|
45
|
+
width: var(--theme-toggle-icon-size);
|
|
46
|
+
height: var(--theme-toggle-icon-size);
|
|
47
|
+
transition: var(--theme-toggle-transition);
|
|
48
|
+
stroke-width: 1.5;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* ThemeToggle Hover State */
|
|
52
|
+
.theme-toggle:hover {
|
|
53
|
+
color: var(--theme-toggle-text-hover);
|
|
54
|
+
background-color: var(--theme-toggle-background-hover);
|
|
55
|
+
transform: var(--theme-toggle-transform-scale);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.theme-toggle:hover svg {
|
|
59
|
+
color: var(--theme-toggle-text-hover);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* ThemeToggle Focus State */
|
|
63
|
+
.theme-toggle:focus-visible {
|
|
64
|
+
outline: var(--cs-accessibility-focus-ring-width) solid var(--theme-toggle-focus-ring);
|
|
65
|
+
outline-offset: var(--cs-accessibility-focus-ring-offset);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ThemeToggle Active State */
|
|
69
|
+
.theme-toggle:active {
|
|
70
|
+
background-color: var(--theme-toggle-active-background);
|
|
71
|
+
color: var(--theme-toggle-active-text);
|
|
72
|
+
transform: translateY(1px);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ThemeToggle Icon Animation */
|
|
76
|
+
.theme-toggle svg {
|
|
77
|
+
transition: transform var(--theme-toggle-animation-duration) var(--theme-toggle-animation-easing);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.theme-toggle:hover svg {
|
|
81
|
+
transform: rotate(180deg);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Light Mode Icon (Moon) Animation */
|
|
85
|
+
.theme-toggle .moon-icon {
|
|
86
|
+
transform: rotate(0deg);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.theme-toggle:hover .moon-icon {
|
|
90
|
+
transform: rotate(-30deg) scale(1.1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Dark Mode Icon (Sun) Animation */
|
|
94
|
+
.theme-toggle .sun-icon {
|
|
95
|
+
transform: rotate(0deg);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.theme-toggle:hover .sun-icon {
|
|
99
|
+
transform: rotate(180deg) scale(1.1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Theme transition effects */
|
|
103
|
+
.theme-toggle::before {
|
|
104
|
+
content: '';
|
|
105
|
+
position: absolute;
|
|
106
|
+
top: 0;
|
|
107
|
+
left: 0;
|
|
108
|
+
right: 0;
|
|
109
|
+
bottom: 0;
|
|
110
|
+
background: linear-gradient(45deg, var(--cs-colors-primary), var(--cs-colors-primary-hover));
|
|
111
|
+
opacity: 0;
|
|
112
|
+
transition: opacity var(--theme-toggle-animation-duration) var(--theme-toggle-animation-easing);
|
|
113
|
+
border-radius: inherit;
|
|
114
|
+
z-index: -1;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.theme-toggle:hover::before {
|
|
118
|
+
opacity: 0.1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Dark mode specific adjustments (these automatically switch via CSS variables) */
|
|
122
|
+
/* No explicit .dark selectors needed - the design system variables handle this */
|
|
123
|
+
|
|
124
|
+
/* Responsive adjustments */
|
|
125
|
+
@media (max-width: 768px) {
|
|
126
|
+
.theme-toggle {
|
|
127
|
+
min-height: 44px;
|
|
128
|
+
min-width: 44px;
|
|
129
|
+
touch-action: manipulation;
|
|
130
|
+
-webkit-tap-highlight-color: transparent;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.theme-toggle svg {
|
|
134
|
+
width: var(--cs-spacing-scale-lg);
|
|
135
|
+
height: var(--cs-spacing-scale-lg);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* High contrast mode support */
|
|
140
|
+
@media (prefers-contrast: high) {
|
|
141
|
+
.theme-toggle {
|
|
142
|
+
border: var(--cs-accessibility-high-contrast-border-width) solid var(--theme-toggle-text);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.theme-toggle:focus-visible {
|
|
146
|
+
outline-width: var(--cs-accessibility-high-contrast-outline-width);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* Reduced motion support */
|
|
151
|
+
@media (prefers-reduced-motion: reduce) {
|
|
152
|
+
.theme-toggle,
|
|
153
|
+
.theme-toggle svg,
|
|
154
|
+
.theme-toggle::before {
|
|
155
|
+
transition: none;
|
|
156
|
+
animation: none;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.theme-toggle:hover svg {
|
|
160
|
+
transform: none;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Print styles */
|
|
165
|
+
@media print {
|
|
166
|
+
.theme-toggle {
|
|
167
|
+
display: none; /* Hide theme toggle in print */
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* ThemeToggle accessibility enhancements */
|
|
172
|
+
.theme-toggle[aria-pressed="true"] {
|
|
173
|
+
background-color: var(--theme-toggle-active-background);
|
|
174
|
+
color: var(--theme-toggle-active-text);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.theme-toggle[aria-pressed="true"]::before {
|
|
178
|
+
opacity: 0.15;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* Loading state */
|
|
182
|
+
.theme-toggle[data-loading="true"] {
|
|
183
|
+
pointer-events: none;
|
|
184
|
+
opacity: 0.7;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.theme-toggle[data-loading="true"] svg {
|
|
188
|
+
animation: spin var(--cs-animation-duration-slow) linear infinite;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@keyframes spin {
|
|
192
|
+
from {
|
|
193
|
+
transform: rotate(0deg);
|
|
194
|
+
}
|
|
195
|
+
to {
|
|
196
|
+
transform: rotate(360deg);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
} /* End @layer components */
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
@import '../base/variables.css' layer(base);
|
|
19
19
|
@import '../themes/index.css' layer(themes);
|
|
20
20
|
@import '../components/base/index.css' layer(components);
|
|
21
|
+
@import '../components/ui/index.css' layer(components);
|
|
21
22
|
@import '../components/navigation/index.css' layer(components);
|
|
22
23
|
@import '../components/data-display/index.css' layer(components);
|
|
23
24
|
@import '../components/feedback/index.css' layer(components);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* Design System Utilities */
|
|
2
|
+
/* Custom utility classes for design system integration */
|
|
3
|
+
|
|
4
|
+
@layer utilities {
|
|
5
|
+
/* Custom Focus Ring Utilities */
|
|
6
|
+
.focus\:ring-cs-primary {
|
|
7
|
+
--tw-ring-color: var(--cs-colors-primary);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.focus\:ring-cs-secondary {
|
|
11
|
+
--tw-ring-color: var(--cs-colors-secondary-500);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.focus\:ring-cs-info {
|
|
15
|
+
--tw-ring-color: var(--cs-colors-semantic-info);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.focus\:ring-cs-success {
|
|
19
|
+
--tw-ring-color: var(--cs-colors-semantic-success);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.focus\:ring-cs-warning {
|
|
23
|
+
--tw-ring-color: var(--cs-colors-semantic-warning);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.focus\:ring-cs-error {
|
|
27
|
+
--tw-ring-color: var(--cs-colors-semantic-error);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Custom Border Color Utilities */
|
|
31
|
+
.focus\:border-cs-primary {
|
|
32
|
+
--tw-border-opacity: 1;
|
|
33
|
+
border-color: rgb(var(--cs-colors-primary-500-rgb) / var(--tw-border-opacity));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.focus\:border-cs-secondary {
|
|
37
|
+
--tw-border-opacity: 1;
|
|
38
|
+
border-color: rgb(var(--cs-colors-secondary-500-rgb) / var(--tw-border-opacity));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Custom Background Color Utilities */
|
|
42
|
+
.bg-cs-primary {
|
|
43
|
+
--tw-bg-opacity: 1;
|
|
44
|
+
background-color: var(--cs-colors-primary);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.bg-cs-secondary {
|
|
48
|
+
--tw-bg-opacity: 1;
|
|
49
|
+
background-color: var(--cs-colors-secondary-500);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.bg-cs-surface-bg {
|
|
53
|
+
--tw-bg-opacity: 1;
|
|
54
|
+
background-color: var(--cs-colors-surface-background);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Custom Text Color Utilities */
|
|
58
|
+
.text-cs-text-primary {
|
|
59
|
+
--tw-text-opacity: 1;
|
|
60
|
+
color: var(--cs-colors-text-primary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.text-cs-text-secondary {
|
|
64
|
+
--tw-text-opacity: 1;
|
|
65
|
+
color: var(--cs-colors-text-secondary);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Custom Border Utilities */
|
|
69
|
+
.border-cs-border {
|
|
70
|
+
--tw-border-opacity: 1;
|
|
71
|
+
border-color: var(--cs-colors-border);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Custom Hover State Utilities */
|
|
75
|
+
.hover\:bg-cs-secondary-hover:hover {
|
|
76
|
+
--tw-bg-opacity: 1;
|
|
77
|
+
background-color: var(--cs-colors-secondary-400);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.hover\:bg-cs-primary-hover:hover {
|
|
81
|
+
--tw-bg-opacity: 1;
|
|
82
|
+
background-color: var(--cs-colors-primary-hover);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Custom Active State Utilities */
|
|
86
|
+
.active\:bg-cs-secondary-active:active {
|
|
87
|
+
--tw-bg-opacity: 1;
|
|
88
|
+
background-color: var(--cs-colors-secondary-600);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.active\:bg-cs-primary-active:active {
|
|
92
|
+
--tw-bg-opacity: 1;
|
|
93
|
+
background-color: var(--cs-colors-primary-active);
|
|
94
|
+
}
|
|
95
|
+
}
|