canny-ui 1.0.0 → 3.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/dist/canny-ui.min.css +1 -1
- package/package.json +1 -1
- package/src/_utilities.scss +16 -0
- package/src/canny-ui.scss +17 -0
- package/src/components/_accordion.scss +113 -0
- package/src/components/_alerts.scss +107 -32
- package/src/components/_autocomplete.scss +188 -0
- package/src/components/_breadcrumb.scss +56 -0
- package/src/components/_chip.scss +122 -0
- package/src/components/_command-palette.scss +251 -0
- package/src/components/_datepicker.scss +511 -0
- package/src/components/_dialog.scss +113 -0
- package/src/components/_drawer.scss +133 -0
- package/src/components/_forms.scss +107 -21
- package/src/components/_list.scss +129 -0
- package/src/components/_menu.scss +115 -0
- package/src/components/_navbar.scss +3 -3
- package/src/components/_pagination.scss +62 -0
- package/src/components/_popover.scss +39 -0
- package/src/components/_sidebar.scss +56 -11
- package/src/components/_slider.scss +95 -0
- package/src/components/_stepper.scss +125 -0
- package/src/components/_tabs.scss +148 -0
- package/src/components/_toast.scss +271 -0
- package/src/components/_tooltip-radix.scss +37 -0
- package/src/tokens/_semantic.scss +3 -1
- package/dist/canny-ui.css +0 -887
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
@use '../tokens/primitives' as *;
|
|
2
|
+
|
|
3
|
+
// Toast / Snackbar — clean white card with a wavy SVG decoration peeking
|
|
4
|
+
// from the left edge in the variant accent color. Body stays neutral
|
|
5
|
+
// for readability; variant signal lives in the wave + icon chip + title.
|
|
6
|
+
|
|
7
|
+
@keyframes cny-toast-in-right {
|
|
8
|
+
from { opacity: 0; transform: translate(8px, 0); }
|
|
9
|
+
to { opacity: 1; transform: translate(0, 0); }
|
|
10
|
+
}
|
|
11
|
+
@keyframes cny-toast-in-left {
|
|
12
|
+
from { opacity: 0; transform: translate(-8px, 0); }
|
|
13
|
+
to { opacity: 1; transform: translate(0, 0); }
|
|
14
|
+
}
|
|
15
|
+
@keyframes cny-toast-in-top {
|
|
16
|
+
from { opacity: 0; transform: translate(0, -8px); }
|
|
17
|
+
to { opacity: 1; transform: translate(0, 0); }
|
|
18
|
+
}
|
|
19
|
+
@keyframes cny-toast-in-bottom {
|
|
20
|
+
from { opacity: 0; transform: translate(0, 10px) scale(0.985); }
|
|
21
|
+
to { opacity: 1; transform: translate(0, 0) scale(1); }
|
|
22
|
+
}
|
|
23
|
+
@keyframes cny-toast-out {
|
|
24
|
+
from { opacity: 1; transform: translate(0, 0); }
|
|
25
|
+
to { opacity: 0; transform: translate(0, -6px) scale(0.97); }
|
|
26
|
+
}
|
|
27
|
+
@keyframes cny-toast-spin {
|
|
28
|
+
to { transform: rotate(360deg); }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── Viewport ────────────────────────────────────────────────────
|
|
32
|
+
.cny-toast-viewport {
|
|
33
|
+
--cny-toast-offset: 1rem;
|
|
34
|
+
position: fixed;
|
|
35
|
+
z-index: 1100;
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
gap: 12px;
|
|
39
|
+
padding: 0;
|
|
40
|
+
margin: 0;
|
|
41
|
+
list-style: none;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
width: min(360px, calc(100vw - var(--cny-toast-offset) * 2));
|
|
44
|
+
|
|
45
|
+
> * { pointer-events: auto; }
|
|
46
|
+
|
|
47
|
+
&.pos-bottom-right { right: var(--cny-toast-offset); bottom: var(--cny-toast-offset); align-items: flex-end; }
|
|
48
|
+
&.pos-bottom-left { left: var(--cny-toast-offset); bottom: var(--cny-toast-offset); align-items: flex-start; }
|
|
49
|
+
&.pos-bottom-center {
|
|
50
|
+
left: 50%; bottom: var(--cny-toast-offset);
|
|
51
|
+
transform: translateX(-50%); align-items: center;
|
|
52
|
+
}
|
|
53
|
+
&.pos-top-right { right: var(--cny-toast-offset); top: var(--cny-toast-offset); align-items: flex-end; }
|
|
54
|
+
&.pos-top-left { left: var(--cny-toast-offset); top: var(--cny-toast-offset); align-items: flex-start; }
|
|
55
|
+
&.pos-top-center {
|
|
56
|
+
left: 50%; top: var(--cny-toast-offset);
|
|
57
|
+
transform: translateX(-50%); align-items: center;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── Toast surface — flat white card ─────────────────────────────
|
|
62
|
+
.cny-toast {
|
|
63
|
+
--toast-accent: var(--color-primary);
|
|
64
|
+
|
|
65
|
+
position: relative;
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: 14px;
|
|
69
|
+
width: min(360px, 100%);
|
|
70
|
+
// 80 px = one full wave cycle. Tall toasts repeat the wave, so this is
|
|
71
|
+
// a floor, not a clamp.
|
|
72
|
+
min-height: 80px;
|
|
73
|
+
padding: 14px 16px 14px 28px; // extra left to clear the tiled wave
|
|
74
|
+
background: var(--bg-surface-lowest);
|
|
75
|
+
color: var(--text-primary);
|
|
76
|
+
border: 1px solid color-mix(in srgb, var(--border-color) 60%, transparent);
|
|
77
|
+
border-radius: 10px;
|
|
78
|
+
box-shadow:
|
|
79
|
+
0 1px 2px rgba(15, 23, 42, 0.04),
|
|
80
|
+
0 8px 24px rgba(149, 157, 165, 0.18);
|
|
81
|
+
font-family: var(--font-body);
|
|
82
|
+
font-size: 0.875rem;
|
|
83
|
+
line-height: 1.5;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
pointer-events: auto;
|
|
86
|
+
transition: transform 200ms cubic-bezier(0.2, 0.8, 0.2, 1),
|
|
87
|
+
box-shadow 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
88
|
+
animation: cny-toast-in-bottom 220ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
|
|
89
|
+
|
|
90
|
+
&:hover {
|
|
91
|
+
transform: translateY(-2px);
|
|
92
|
+
box-shadow:
|
|
93
|
+
0 1px 2px rgba(15, 23, 42, 0.04),
|
|
94
|
+
0 14px 32px rgba(149, 157, 165, 0.24);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Direction-aware entrance
|
|
98
|
+
.cny-toast-viewport.pos-bottom-right &,
|
|
99
|
+
.cny-toast-viewport.pos-top-right & { animation-name: cny-toast-in-right; }
|
|
100
|
+
.cny-toast-viewport.pos-bottom-left &,
|
|
101
|
+
.cny-toast-viewport.pos-top-left & { animation-name: cny-toast-in-left; }
|
|
102
|
+
.cny-toast-viewport.pos-top-center &,
|
|
103
|
+
.cny-toast-viewport.pos-top-right &,
|
|
104
|
+
.cny-toast-viewport.pos-top-left & { animation-name: cny-toast-in-top; }
|
|
105
|
+
|
|
106
|
+
&.is-exiting {
|
|
107
|
+
animation: cny-toast-out 200ms cubic-bezier(0.4, 0, 1, 1) both;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@media (prefers-reduced-motion: reduce) {
|
|
111
|
+
animation: none;
|
|
112
|
+
&.is-exiting { animation: none; opacity: 0; }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ── Variants — only --toast-accent shifts ──
|
|
116
|
+
&.success { --toast-accent: var(--color-success); }
|
|
117
|
+
&.info { --toast-accent: var(--color-info); }
|
|
118
|
+
&.warning { --toast-accent: var(--color-warning); }
|
|
119
|
+
&.danger { --toast-accent: var(--color-danger); }
|
|
120
|
+
&.loading { --toast-accent: var(--color-primary); }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── Wave decoration on the left edge ─────────────────────────────
|
|
124
|
+
// Seamless vertical tile: full width at y=0 and y=80, single cubic dip in
|
|
125
|
+
// the middle. Both tile boundaries match at the right edge (x=80) so
|
|
126
|
+
// repeat-y has no discontinuity even on tall toasts. Path is filled (left
|
|
127
|
+
// half) for the colored strip, with the wave shape forming the inner edge.
|
|
128
|
+
.cny-toast::before {
|
|
129
|
+
content: '';
|
|
130
|
+
position: absolute;
|
|
131
|
+
left: 0;
|
|
132
|
+
top: 0;
|
|
133
|
+
bottom: 0;
|
|
134
|
+
width: 18px;
|
|
135
|
+
background-color: color-mix(in srgb, var(--toast-accent) 23%, transparent);
|
|
136
|
+
mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80' preserveAspectRatio='none'><path d='M0,0 L80,0 C20,20 20,60 80,80 L0,80 Z'/></svg>");
|
|
137
|
+
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80' preserveAspectRatio='none'><path d='M0,0 L80,0 C20,20 20,60 80,80 L0,80 Z'/></svg>");
|
|
138
|
+
mask-repeat: repeat-y;
|
|
139
|
+
-webkit-mask-repeat: repeat-y;
|
|
140
|
+
mask-size: 18px 80px;
|
|
141
|
+
-webkit-mask-size: 18px 80px;
|
|
142
|
+
pointer-events: none;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ── Icon chip — circular, filled tonal ──
|
|
146
|
+
.cny-toast-icon {
|
|
147
|
+
flex: none;
|
|
148
|
+
display: inline-flex;
|
|
149
|
+
align-items: center;
|
|
150
|
+
justify-content: center;
|
|
151
|
+
width: 36px;
|
|
152
|
+
height: 36px;
|
|
153
|
+
border-radius: 50%;
|
|
154
|
+
background: color-mix(in srgb, var(--toast-accent) 26%, transparent);
|
|
155
|
+
color: var(--toast-accent);
|
|
156
|
+
position: relative;
|
|
157
|
+
z-index: 1;
|
|
158
|
+
|
|
159
|
+
> svg {
|
|
160
|
+
width: 18px;
|
|
161
|
+
height: 18px;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.cny-toast-spin { animation: cny-toast-spin 1s linear infinite; }
|
|
166
|
+
@media (prefers-reduced-motion: reduce) { .cny-toast-spin { animation: none; } }
|
|
167
|
+
|
|
168
|
+
// ── Body ───────────────────────────────────────────────────────
|
|
169
|
+
.cny-toast-body {
|
|
170
|
+
flex: 1 1 auto;
|
|
171
|
+
min-width: 0;
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
align-items: center;
|
|
176
|
+
text-align: center;
|
|
177
|
+
position: relative;
|
|
178
|
+
z-index: 1;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.cny-toast-title {
|
|
182
|
+
font-weight: 700;
|
|
183
|
+
letter-spacing: -0.01em;
|
|
184
|
+
line-height: 1.25;
|
|
185
|
+
margin: 0;
|
|
186
|
+
color: var(--toast-accent);
|
|
187
|
+
font-size: 16px;
|
|
188
|
+
text-align: center;
|
|
189
|
+
cursor: default;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.cny-toast-description {
|
|
193
|
+
margin: 4px 0 0;
|
|
194
|
+
color: var(--text-muted);
|
|
195
|
+
font-size: 13.5px;
|
|
196
|
+
line-height: 1.45;
|
|
197
|
+
text-align: center;
|
|
198
|
+
cursor: default;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ── Action slot ────────────────────────────────────────────────
|
|
202
|
+
.cny-toast-action {
|
|
203
|
+
flex: none;
|
|
204
|
+
display: inline-flex;
|
|
205
|
+
align-items: center;
|
|
206
|
+
align-self: center;
|
|
207
|
+
position: relative;
|
|
208
|
+
z-index: 1;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ── Close button ───────────────────────────────────────────────
|
|
212
|
+
.cny-toast-close {
|
|
213
|
+
flex: none;
|
|
214
|
+
display: inline-flex;
|
|
215
|
+
align-items: center;
|
|
216
|
+
justify-content: center;
|
|
217
|
+
width: 26px;
|
|
218
|
+
height: 26px;
|
|
219
|
+
padding: 0;
|
|
220
|
+
background: transparent;
|
|
221
|
+
border: 0;
|
|
222
|
+
color: var(--text-muted);
|
|
223
|
+
cursor: pointer;
|
|
224
|
+
border-radius: var(--radius-sm);
|
|
225
|
+
transition: color 140ms ease, background-color 140ms ease, transform 140ms ease;
|
|
226
|
+
position: relative;
|
|
227
|
+
z-index: 1;
|
|
228
|
+
|
|
229
|
+
> svg { width: 16px; height: 16px; }
|
|
230
|
+
|
|
231
|
+
&:hover {
|
|
232
|
+
color: var(--text-primary);
|
|
233
|
+
background: color-mix(in srgb, var(--toast-accent) 8%, var(--bg-surface-low));
|
|
234
|
+
transform: scale(1.04);
|
|
235
|
+
}
|
|
236
|
+
&:active {
|
|
237
|
+
transform: scale(0.96);
|
|
238
|
+
}
|
|
239
|
+
&:focus-visible {
|
|
240
|
+
outline: 2px solid var(--toast-accent);
|
|
241
|
+
outline-offset: 2px;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ── Mobile ─────────────────────────────────────────────────────
|
|
246
|
+
@media (max-width: 480px) {
|
|
247
|
+
.cny-toast-viewport {
|
|
248
|
+
--cny-toast-offset: 12px;
|
|
249
|
+
width: calc(100vw - var(--cny-toast-offset) * 2);
|
|
250
|
+
}
|
|
251
|
+
.cny-toast {
|
|
252
|
+
width: 100%;
|
|
253
|
+
min-height: 64px;
|
|
254
|
+
padding: 12px 14px 12px 26px;
|
|
255
|
+
gap: 12px;
|
|
256
|
+
border-radius: 9px;
|
|
257
|
+
}
|
|
258
|
+
.cny-toast::before {
|
|
259
|
+
width: 14px;
|
|
260
|
+
mask-size: 14px 64px;
|
|
261
|
+
-webkit-mask-size: 14px 64px;
|
|
262
|
+
}
|
|
263
|
+
.cny-toast-icon {
|
|
264
|
+
width: 32px;
|
|
265
|
+
height: 32px;
|
|
266
|
+
> svg { width: 16px; height: 16px; }
|
|
267
|
+
}
|
|
268
|
+
.cny-toast-title { font-size: 15px; }
|
|
269
|
+
.cny-toast-description { font-size: 12.5px; }
|
|
270
|
+
.cny-toast-close { width: 24px; height: 24px; > svg { width: 14px; height: 14px; } }
|
|
271
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
@use '../tokens/primitives' as *;
|
|
2
|
+
|
|
3
|
+
// Radix Tooltip — distinct from the legacy CSS-only [data-tooltip] pattern.
|
|
4
|
+
|
|
5
|
+
@keyframes cny-tooltip-in {
|
|
6
|
+
from { opacity: 0; transform: scale(0.96); }
|
|
7
|
+
to { opacity: 1; transform: scale(1); }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.cny-tooltip-content {
|
|
11
|
+
z-index: 1020;
|
|
12
|
+
padding: 5px 9px;
|
|
13
|
+
background: var(--text-primary);
|
|
14
|
+
color: var(--bg-surface-lowest);
|
|
15
|
+
border-radius: var(--radius-xs);
|
|
16
|
+
font-family: var(--font-body);
|
|
17
|
+
font-size: 0.75rem;
|
|
18
|
+
font-weight: 500;
|
|
19
|
+
line-height: 1.35;
|
|
20
|
+
letter-spacing: -0.005em;
|
|
21
|
+
max-width: 240px;
|
|
22
|
+
box-shadow: 0 6px 18px -6px rgba(0, 0, 0, 0.25);
|
|
23
|
+
animation: cny-tooltip-in 120ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
24
|
+
user-select: none;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
|
|
27
|
+
&[data-side='top'] { transform-origin: bottom center; }
|
|
28
|
+
&[data-side='bottom'] { transform-origin: top center; }
|
|
29
|
+
&[data-side='left'] { transform-origin: right center; }
|
|
30
|
+
&[data-side='right'] { transform-origin: left center; }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.cny-tooltip-arrow { fill: var(--text-primary); }
|
|
34
|
+
|
|
35
|
+
@media (prefers-reduced-motion: reduce) {
|
|
36
|
+
.cny-tooltip-content { animation: none; }
|
|
37
|
+
}
|
|
@@ -112,8 +112,10 @@
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
// ── Dark theme ──────────────────────────────────────────────────────────
|
|
115
|
+
// Auto-dark when the OS prefers dark, UNLESS .cny-light is explicitly set.
|
|
116
|
+
// Manual toggle classes (.cny-dark / .cny-light) always win over system preference.
|
|
115
117
|
@media (prefers-color-scheme: dark) {
|
|
116
|
-
:root {
|
|
118
|
+
:root:not(.cny-light) {
|
|
117
119
|
--bg-base: #{$zinc-950};
|
|
118
120
|
--bg-surface-low: #{$zinc-900};
|
|
119
121
|
--bg-surface-lowest: #{$zinc-800};
|