ciderui 0.1.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/README.md +106 -0
- package/js/carousel.js +77 -0
- package/js/combobox.js +125 -0
- package/js/command.js +91 -0
- package/js/context-menu.js +49 -0
- package/js/dialog.js +18 -0
- package/js/dropdown-menu.js +39 -0
- package/js/otp.js +92 -0
- package/js/popover.js +35 -0
- package/js/select.js +56 -0
- package/js/sheet.js +17 -0
- package/js/tabs.js +34 -0
- package/js/toast.js +60 -0
- package/js/toggle.js +26 -0
- package/package.json +53 -0
- package/src/css/ciderui.cdn.css +11 -0
- package/src/css/ciderui.css +324 -0
- package/src/css/components/accordion.css +31 -0
- package/src/css/components/alert.css +18 -0
- package/src/css/components/aspect-ratio.css +7 -0
- package/src/css/components/avatar.css +17 -0
- package/src/css/components/badge.css +20 -0
- package/src/css/components/breadcrumb.css +16 -0
- package/src/css/components/button-group.css +20 -0
- package/src/css/components/button.css +59 -0
- package/src/css/components/card.css +37 -0
- package/src/css/components/carousel.css +60 -0
- package/src/css/components/checkbox.css +16 -0
- package/src/css/components/collapsible.css +25 -0
- package/src/css/components/combobox.css +69 -0
- package/src/css/components/command.css +64 -0
- package/src/css/components/context-menu.css +28 -0
- package/src/css/components/dialog.css +23 -0
- package/src/css/components/drawer.css +69 -0
- package/src/css/components/dropdown-menu.css +28 -0
- package/src/css/components/empty.css +12 -0
- package/src/css/components/field.css +7 -0
- package/src/css/components/file-tree.css +53 -0
- package/src/css/components/form-controls.css +57 -0
- package/src/css/components/form.css +15 -0
- package/src/css/components/hover-card.css +25 -0
- package/src/css/components/input-group.css +48 -0
- package/src/css/components/input-otp.css +22 -0
- package/src/css/components/item.css +43 -0
- package/src/css/components/kbd.css +7 -0
- package/src/css/components/label.css +4 -0
- package/src/css/components/pagination.css +15 -0
- package/src/css/components/popover.css +19 -0
- package/src/css/components/progress.css +18 -0
- package/src/css/components/radio.css +13 -0
- package/src/css/components/scroll-area.css +24 -0
- package/src/css/components/separator.css +19 -0
- package/src/css/components/sheet.css +46 -0
- package/src/css/components/sidebar.css +32 -0
- package/src/css/components/skeleton.css +9 -0
- package/src/css/components/slider.css +48 -0
- package/src/css/components/spinner.css +12 -0
- package/src/css/components/switch.css +28 -0
- package/src/css/components/table.css +39 -0
- package/src/css/components/tabs.css +44 -0
- package/src/css/components/theme-switcher.css +17 -0
- package/src/css/components/toast.css +22 -0
- package/src/css/components/toggle.css +34 -0
- package/src/css/components/tooltip.css +66 -0
- package/src/css/components/typography.css +84 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* ========== BUTTON ========== */
|
|
2
|
+
.btn,
|
|
3
|
+
.btn-primary,
|
|
4
|
+
.btn-secondary,
|
|
5
|
+
.btn-outline,
|
|
6
|
+
.btn-ghost,
|
|
7
|
+
.btn-destructive {
|
|
8
|
+
@apply inline-flex items-center justify-center gap-2 rounded-[12px] px-4 py-2.5 text-[13px] font-medium disabled:pointer-events-none disabled:opacity-50 cursor-pointer;
|
|
9
|
+
transition: all 0.25s var(--apple-spring);
|
|
10
|
+
letter-spacing: -0.01em;
|
|
11
|
+
&:active { transform: scale(var(--apple-press-scale)); }
|
|
12
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: 2px; }
|
|
13
|
+
}
|
|
14
|
+
.btn-primary {
|
|
15
|
+
@apply bg-primary text-primary-foreground;
|
|
16
|
+
box-shadow: var(--shadow-sm), inset 0 1px 0 oklch(1 0 0 / 0.1);
|
|
17
|
+
&:hover { @apply bg-primary-hover; box-shadow: var(--shadow), inset 0 1px 0 oklch(1 0 0 / 0.1); }
|
|
18
|
+
&:active { @apply bg-primary-active; transform: scale(var(--apple-press-scale)); }
|
|
19
|
+
}
|
|
20
|
+
/* Default .btn alone = primary style (exclude color variants, not size/shape modifiers) */
|
|
21
|
+
.btn:not(.btn-primary, .btn-secondary, .btn-outline, .btn-ghost, .btn-destructive, .btn-icon) {
|
|
22
|
+
@apply bg-primary text-primary-foreground;
|
|
23
|
+
box-shadow: var(--shadow-sm), inset 0 1px 0 oklch(1 0 0 / 0.1);
|
|
24
|
+
&:hover { @apply bg-primary-hover; box-shadow: var(--shadow), inset 0 1px 0 oklch(1 0 0 / 0.1); }
|
|
25
|
+
&:active { @apply bg-primary-active; }
|
|
26
|
+
}
|
|
27
|
+
.btn-secondary {
|
|
28
|
+
@apply bg-secondary text-secondary-foreground;
|
|
29
|
+
&:hover { background: var(--secondary-hover); }
|
|
30
|
+
}
|
|
31
|
+
.btn-outline {
|
|
32
|
+
@apply border bg-card text-card-foreground;
|
|
33
|
+
border-color: var(--border-solid);
|
|
34
|
+
box-shadow: var(--shadow-sm);
|
|
35
|
+
&:hover { background: var(--surface-2); box-shadow: var(--shadow); }
|
|
36
|
+
}
|
|
37
|
+
.btn-ghost {
|
|
38
|
+
@apply text-foreground;
|
|
39
|
+
&:hover { @apply bg-secondary; }
|
|
40
|
+
}
|
|
41
|
+
.btn-destructive {
|
|
42
|
+
@apply bg-destructive text-destructive-foreground;
|
|
43
|
+
box-shadow: var(--shadow-sm);
|
|
44
|
+
&:hover { @apply bg-destructive-hover; box-shadow: var(--shadow); }
|
|
45
|
+
&:active { @apply bg-destructive-active; transform: scale(var(--apple-press-scale)); }
|
|
46
|
+
}
|
|
47
|
+
.btn-pill {
|
|
48
|
+
@apply rounded-full px-5;
|
|
49
|
+
}
|
|
50
|
+
.btn-sm {
|
|
51
|
+
@apply px-3.5 py-1.5 text-xs gap-1.5;
|
|
52
|
+
}
|
|
53
|
+
.btn-lg {
|
|
54
|
+
@apply px-6 py-3 text-base;
|
|
55
|
+
}
|
|
56
|
+
.btn-icon {
|
|
57
|
+
@apply size-9 p-0 rounded-full bg-secondary text-muted-foreground;
|
|
58
|
+
&:hover { background: var(--secondary-hover); }
|
|
59
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* ========== CARD ========== */
|
|
2
|
+
.card {
|
|
3
|
+
@apply rounded-2xl bg-card text-card-foreground;
|
|
4
|
+
box-shadow: var(--shadow), var(--panel-ring);
|
|
5
|
+
& > header {
|
|
6
|
+
@apply px-6 py-5;
|
|
7
|
+
&:not(:last-child) { border-bottom: 1px solid var(--panel-border); }
|
|
8
|
+
& h2, & h3 { @apply text-[20px] font-semibold tracking-tight; }
|
|
9
|
+
& p { @apply mt-1 text-[13px] text-muted-foreground; }
|
|
10
|
+
}
|
|
11
|
+
& > section {
|
|
12
|
+
@apply px-6 py-5;
|
|
13
|
+
}
|
|
14
|
+
& > footer {
|
|
15
|
+
@apply px-6 py-4;
|
|
16
|
+
border-top: 1px solid var(--panel-border);
|
|
17
|
+
}
|
|
18
|
+
/* Basic card without header/section/footer = padded */
|
|
19
|
+
&:not(:has(header)):not(:has(section)) {
|
|
20
|
+
@apply p-6;
|
|
21
|
+
& h2, & h3 { @apply text-[20px] font-semibold tracking-tight; }
|
|
22
|
+
& p { @apply mt-2 text-[13px] text-muted-foreground; }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
.card-interactive {
|
|
26
|
+
@apply rounded-2xl bg-card p-6 text-card-foreground cursor-pointer;
|
|
27
|
+
box-shadow: var(--shadow), var(--panel-ring);
|
|
28
|
+
transition: all 0.3s var(--apple-spring);
|
|
29
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: 2px; }
|
|
30
|
+
& h2, & h3 { @apply text-[20px] font-semibold tracking-tight; }
|
|
31
|
+
& p { @apply mt-2 text-[13px] text-muted-foreground; }
|
|
32
|
+
&:hover {
|
|
33
|
+
box-shadow: var(--shadow-md), var(--float-ring);
|
|
34
|
+
transform: translateY(-1px);
|
|
35
|
+
}
|
|
36
|
+
&:active { transform: translateY(0) scale(var(--apple-press-scale)); }
|
|
37
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* ========== CAROUSEL ========== */
|
|
2
|
+
.carousel {
|
|
3
|
+
@apply relative w-full;
|
|
4
|
+
padding-inline: 3rem;
|
|
5
|
+
}
|
|
6
|
+
.carousel-content {
|
|
7
|
+
@apply flex gap-4 overflow-x-auto scroll-smooth;
|
|
8
|
+
scroll-snap-type: x mandatory;
|
|
9
|
+
scrollbar-width: none;
|
|
10
|
+
/* overflow-x:auto forces overflow-y:auto per CSS spec, clipping shadows/borders.
|
|
11
|
+
Padding creates breathing room; negative margin keeps layout stable. */
|
|
12
|
+
padding-block: 8px;
|
|
13
|
+
margin-block: -8px;
|
|
14
|
+
&::-webkit-scrollbar { display: none; }
|
|
15
|
+
}
|
|
16
|
+
.carousel-item {
|
|
17
|
+
@apply shrink-0;
|
|
18
|
+
scroll-snap-align: start;
|
|
19
|
+
width: calc(100% - 2rem);
|
|
20
|
+
}
|
|
21
|
+
.carousel-item-half {
|
|
22
|
+
@apply shrink-0;
|
|
23
|
+
scroll-snap-align: start;
|
|
24
|
+
width: calc(50% - 0.5rem);
|
|
25
|
+
}
|
|
26
|
+
.carousel-item-third {
|
|
27
|
+
@apply shrink-0;
|
|
28
|
+
scroll-snap-align: start;
|
|
29
|
+
width: calc(33.333% - 0.75rem);
|
|
30
|
+
}
|
|
31
|
+
.carousel-prev,
|
|
32
|
+
.carousel-next {
|
|
33
|
+
@apply absolute top-1/2 z-10 flex size-9 -translate-y-1/2 items-center justify-center rounded-full text-foreground cursor-pointer;
|
|
34
|
+
background: var(--glass-bg);
|
|
35
|
+
backdrop-filter: blur(12px);
|
|
36
|
+
-webkit-backdrop-filter: blur(12px);
|
|
37
|
+
box-shadow: var(--shadow), var(--float-ring);
|
|
38
|
+
transition: all 0.2s var(--apple-ease);
|
|
39
|
+
&:hover { box-shadow: var(--shadow-md), var(--float-ring); }
|
|
40
|
+
&:active { transform: translateY(-50%) scale(var(--apple-press-scale)); }
|
|
41
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: 2px; }
|
|
42
|
+
&:disabled { @apply pointer-events-none opacity-30; }
|
|
43
|
+
& svg { @apply size-4; }
|
|
44
|
+
}
|
|
45
|
+
.carousel-prev { @apply -left-3; }
|
|
46
|
+
.carousel-next { @apply -right-3; }
|
|
47
|
+
.carousel-indicators {
|
|
48
|
+
@apply mt-4 flex items-center justify-center gap-1.5;
|
|
49
|
+
}
|
|
50
|
+
.carousel-indicator {
|
|
51
|
+
@apply rounded-full cursor-pointer;
|
|
52
|
+
width: 6px;
|
|
53
|
+
height: 6px;
|
|
54
|
+
background: oklch(from var(--foreground) l c h / 0.2);
|
|
55
|
+
transition: all 0.3s var(--apple-spring);
|
|
56
|
+
&[data-active] {
|
|
57
|
+
background: oklch(from var(--foreground) l c h / 0.6);
|
|
58
|
+
width: 1.5rem;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* ========== CHECKBOX ========== */
|
|
2
|
+
.checkbox {
|
|
3
|
+
@apply appearance-none size-[18px] shrink-0 rounded-[5px] border bg-card cursor-pointer;
|
|
4
|
+
border-color: var(--input-border);
|
|
5
|
+
transition: all 0.2s var(--apple-ease);
|
|
6
|
+
&:checked {
|
|
7
|
+
@apply bg-primary border-primary;
|
|
8
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='white' stroke-width='3'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
|
|
9
|
+
background-size: 12px;
|
|
10
|
+
background-position: center;
|
|
11
|
+
background-repeat: no-repeat;
|
|
12
|
+
}
|
|
13
|
+
&:hover:not(:focus-visible):not(:checked) { border-color: var(--input-border-hover); }
|
|
14
|
+
&:focus-visible { box-shadow: 0 0 0 4px oklch(from var(--primary) l c h / 0.15); }
|
|
15
|
+
&:disabled { @apply cursor-not-allowed opacity-50; }
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* ========== COLLAPSIBLE ========== */
|
|
2
|
+
.collapsible {
|
|
3
|
+
@apply rounded-2xl bg-card;
|
|
4
|
+
box-shadow: var(--shadow-sm), var(--panel-ring);
|
|
5
|
+
& summary {
|
|
6
|
+
@apply flex cursor-pointer list-none items-center justify-between rounded-2xl px-5 py-4 text-[13px] font-medium text-foreground;
|
|
7
|
+
transition: background-color 0.15s var(--apple-ease);
|
|
8
|
+
&:hover { background: var(--surface-1); }
|
|
9
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
10
|
+
&::-webkit-details-marker { display: none; }
|
|
11
|
+
& svg:last-child {
|
|
12
|
+
@apply size-4 shrink-0 text-muted-foreground;
|
|
13
|
+
transition: transform 0.25s var(--apple-spring);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
&[open] > summary {
|
|
17
|
+
@apply rounded-b-none;
|
|
18
|
+
}
|
|
19
|
+
&[open] > summary svg:last-child {
|
|
20
|
+
transform: rotate(180deg);
|
|
21
|
+
}
|
|
22
|
+
& > div, & > p {
|
|
23
|
+
@apply px-5 pb-4 text-[13px] text-muted-foreground;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* ========== COMBOBOX ========== */
|
|
2
|
+
.combobox {
|
|
3
|
+
@apply relative inline-block;
|
|
4
|
+
& > button {
|
|
5
|
+
@apply flex h-11 items-center justify-between gap-2 rounded-[12px] border px-3.5 text-[13px] transition-all duration-200 cursor-pointer;
|
|
6
|
+
background-color: var(--card);
|
|
7
|
+
border-color: var(--input);
|
|
8
|
+
&:hover:not(:focus) { border-color: var(--border-solid); }
|
|
9
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: 2px; }
|
|
10
|
+
& span { @apply flex-1 truncate text-left; }
|
|
11
|
+
& span[data-placeholder] { @apply text-muted-foreground; opacity: 0.5; }
|
|
12
|
+
& svg { @apply size-4 shrink-0 text-muted-foreground opacity-50; }
|
|
13
|
+
}
|
|
14
|
+
& [data-combobox-content] {
|
|
15
|
+
@apply absolute z-50 mt-1.5 w-full min-w-[200px] rounded-xl overflow-hidden;
|
|
16
|
+
display: none;
|
|
17
|
+
background: var(--glass-bg-opaque);
|
|
18
|
+
backdrop-filter: var(--glass-blur);
|
|
19
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
20
|
+
box-shadow: var(--shadow-lg), var(--float-ring);
|
|
21
|
+
animation: slideUp 0.2s var(--apple-spring);
|
|
22
|
+
& > header {
|
|
23
|
+
@apply flex items-center gap-2 border-b px-3;
|
|
24
|
+
& svg { @apply size-4 shrink-0 text-muted-foreground; }
|
|
25
|
+
& input {
|
|
26
|
+
@apply h-10 flex-1 bg-transparent text-[13px] text-foreground outline-none;
|
|
27
|
+
&::placeholder { @apply text-muted-foreground; opacity: 0.5; }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
& [role="listbox"] {
|
|
31
|
+
@apply max-h-56 overflow-y-auto p-1;
|
|
32
|
+
& [role="group"] {
|
|
33
|
+
& > [role="heading"] {
|
|
34
|
+
@apply block px-2 py-1.5 text-xs font-medium text-muted-foreground;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
& [role="option"] {
|
|
38
|
+
@apply flex items-center gap-2 rounded-lg px-2 py-2 text-[13px] text-foreground cursor-pointer transition-colors;
|
|
39
|
+
& svg { @apply size-4 shrink-0 text-muted-foreground; }
|
|
40
|
+
&:hover { @apply bg-accent; }
|
|
41
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
42
|
+
&[data-active] { @apply bg-accent; }
|
|
43
|
+
&[data-selected] {
|
|
44
|
+
@apply bg-accent font-medium;
|
|
45
|
+
&::after {
|
|
46
|
+
content: "";
|
|
47
|
+
display: inline-block;
|
|
48
|
+
width: 1rem; height: 1rem; margin-left: auto;
|
|
49
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor' stroke-width='2.5'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
|
|
50
|
+
background-size: contain;
|
|
51
|
+
background-repeat: no-repeat;
|
|
52
|
+
flex-shrink: 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
& hr[role="separator"], & hr {
|
|
57
|
+
@apply my-1 h-px;
|
|
58
|
+
background: var(--panel-border);
|
|
59
|
+
}
|
|
60
|
+
&.combobox-empty::after {
|
|
61
|
+
content: attr(data-empty);
|
|
62
|
+
@apply block py-6 text-center text-[13px] text-muted-foreground;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
&[data-open] > [data-combobox-content] {
|
|
67
|
+
display: block;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* ========== COMMAND ========== */
|
|
2
|
+
.command {
|
|
3
|
+
@apply flex flex-col rounded-2xl bg-card overflow-hidden;
|
|
4
|
+
box-shadow: var(--shadow-lg), var(--float-ring);
|
|
5
|
+
& > header {
|
|
6
|
+
@apply flex items-center gap-2 px-3.5;
|
|
7
|
+
border-bottom: 1px solid var(--panel-border);
|
|
8
|
+
& svg { @apply size-4 shrink-0 text-muted-foreground; }
|
|
9
|
+
& input {
|
|
10
|
+
@apply h-12 flex-1 bg-transparent text-[13px] text-foreground outline-none;
|
|
11
|
+
&::placeholder { @apply text-muted-foreground; opacity: 0.45; }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
& [role="menu"], & [role="listbox"] {
|
|
15
|
+
@apply max-h-72 overflow-y-auto p-1.5;
|
|
16
|
+
& [role="group"] {
|
|
17
|
+
& > [role="heading"], & > span[role="heading"] {
|
|
18
|
+
@apply block px-2.5 py-1.5 text-[11px] font-semibold text-muted-foreground;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
& [role="menuitem"], & [role="option"] {
|
|
22
|
+
@apply flex items-center gap-2.5 rounded-[8px] px-2.5 py-2 text-[13px] text-foreground cursor-pointer;
|
|
23
|
+
transition: background-color 0.12s var(--apple-ease);
|
|
24
|
+
& svg { @apply size-4 shrink-0 text-muted-foreground; }
|
|
25
|
+
& span { @apply flex-1; }
|
|
26
|
+
&:hover { @apply bg-accent; }
|
|
27
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
28
|
+
&[data-active] { @apply bg-accent; }
|
|
29
|
+
&[aria-disabled="true"] { @apply opacity-50 pointer-events-none; }
|
|
30
|
+
&[data-selected]::before {
|
|
31
|
+
content: "";
|
|
32
|
+
display: inline-block;
|
|
33
|
+
width: 1rem; height: 1rem;
|
|
34
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor' stroke-width='2.5'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
|
|
35
|
+
background-size: contain;
|
|
36
|
+
background-repeat: no-repeat;
|
|
37
|
+
flex-shrink: 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
& hr[role="separator"], & hr {
|
|
41
|
+
@apply my-1 h-px;
|
|
42
|
+
background: var(--panel-border);
|
|
43
|
+
}
|
|
44
|
+
&.command-empty::after {
|
|
45
|
+
content: attr(data-empty);
|
|
46
|
+
@apply block py-6 text-center text-[13px] text-muted-foreground;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
dialog.command-dialog,
|
|
51
|
+
.command-dialog {
|
|
52
|
+
@apply m-auto w-full max-w-lg rounded-[20px] border-0 bg-transparent p-0;
|
|
53
|
+
box-shadow: var(--shadow-xl);
|
|
54
|
+
&::backdrop {
|
|
55
|
+
background: var(--backdrop-bg);
|
|
56
|
+
backdrop-filter: var(--glass-blur);
|
|
57
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
58
|
+
}
|
|
59
|
+
&[open] { animation: dialogShow 0.25s var(--apple-spring); }
|
|
60
|
+
& > .command {
|
|
61
|
+
box-shadow: none;
|
|
62
|
+
border: 1px solid var(--panel-border);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* ========== CONTEXT MENU ========== */
|
|
2
|
+
.context-menu-trigger {
|
|
3
|
+
@apply cursor-default;
|
|
4
|
+
}
|
|
5
|
+
.context-menu-content {
|
|
6
|
+
@apply fixed z-[9999] min-w-[200px] rounded-xl p-1.5;
|
|
7
|
+
display: none;
|
|
8
|
+
background: var(--glass-bg);
|
|
9
|
+
backdrop-filter: var(--glass-blur);
|
|
10
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
11
|
+
box-shadow: var(--shadow-lg), var(--float-ring);
|
|
12
|
+
animation: slideUp 0.12s var(--apple-spring);
|
|
13
|
+
& button, & a {
|
|
14
|
+
@apply flex w-full items-center gap-2.5 rounded-[8px] px-3 py-2 text-left text-[13px] text-foreground;
|
|
15
|
+
transition: background-color 0.12s var(--apple-ease);
|
|
16
|
+
&:hover { @apply bg-accent; }
|
|
17
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
18
|
+
& svg { @apply size-4 text-muted-foreground; }
|
|
19
|
+
}
|
|
20
|
+
& hr {
|
|
21
|
+
@apply my-1 h-px mx-1.5;
|
|
22
|
+
background: var(--panel-border);
|
|
23
|
+
}
|
|
24
|
+
& .context-menu-shortcut {
|
|
25
|
+
@apply ml-auto text-xs text-muted-foreground;
|
|
26
|
+
}
|
|
27
|
+
&[data-open] { display: block; }
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* ========== DIALOG ========== */
|
|
2
|
+
dialog.dialog,
|
|
3
|
+
.dialog {
|
|
4
|
+
@apply m-auto w-full max-w-md rounded-[20px] bg-card text-card-foreground p-0;
|
|
5
|
+
box-shadow: var(--shadow-xl), var(--float-ring);
|
|
6
|
+
&::backdrop {
|
|
7
|
+
background: var(--backdrop-bg);
|
|
8
|
+
backdrop-filter: var(--glass-blur);
|
|
9
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
10
|
+
}
|
|
11
|
+
&[open] { animation: dialogShow 0.28s var(--apple-spring); }
|
|
12
|
+
& > header {
|
|
13
|
+
@apply px-6 pt-6;
|
|
14
|
+
& h2 { @apply text-[20px] font-semibold tracking-tight text-foreground; }
|
|
15
|
+
& p { @apply mt-2 text-[13px] text-muted-foreground; }
|
|
16
|
+
}
|
|
17
|
+
& > section {
|
|
18
|
+
@apply px-6 pt-4;
|
|
19
|
+
}
|
|
20
|
+
& > footer {
|
|
21
|
+
@apply flex justify-end gap-2 px-6 pb-6 pt-6;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* ========== DRAWER ========== */
|
|
2
|
+
dialog.sheet-bottom,
|
|
3
|
+
.sheet-bottom {
|
|
4
|
+
@apply fixed bottom-0 left-0 right-0 top-auto m-0 w-full max-w-full bg-card text-card-foreground;
|
|
5
|
+
max-height: min(85vh, 600px);
|
|
6
|
+
border-radius: 20px 20px 0 0;
|
|
7
|
+
box-shadow: 0 -8px 32px oklch(0 0 0 / 0.1), var(--float-ring);
|
|
8
|
+
&::backdrop {
|
|
9
|
+
background: var(--backdrop-bg);
|
|
10
|
+
backdrop-filter: var(--glass-blur);
|
|
11
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
12
|
+
}
|
|
13
|
+
&[open] { animation: sheetSlideInBottom 0.35s var(--apple-spring); }
|
|
14
|
+
& > header {
|
|
15
|
+
@apply px-6 py-5;
|
|
16
|
+
& h2 { @apply text-[20px] font-semibold tracking-tight text-foreground; }
|
|
17
|
+
& p { @apply mt-1 text-[13px] text-muted-foreground; }
|
|
18
|
+
}
|
|
19
|
+
& > section {
|
|
20
|
+
@apply overflow-y-auto px-6 py-5;
|
|
21
|
+
}
|
|
22
|
+
& > footer {
|
|
23
|
+
@apply px-6 py-4;
|
|
24
|
+
border-top: 1px solid var(--panel-border);
|
|
25
|
+
}
|
|
26
|
+
& .sheet-close {
|
|
27
|
+
@apply absolute right-4 top-4 rounded-full p-1.5 text-muted-foreground cursor-pointer;
|
|
28
|
+
transition: all 0.2s var(--apple-ease);
|
|
29
|
+
&:hover { @apply text-foreground bg-accent; }
|
|
30
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: 2px; }
|
|
31
|
+
& svg { @apply size-4; }
|
|
32
|
+
}
|
|
33
|
+
& .drawer-handle {
|
|
34
|
+
@apply mx-auto mt-2 mb-1 h-1 w-9 rounded-full;
|
|
35
|
+
background: var(--surface-7);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
dialog.sheet-top,
|
|
39
|
+
.sheet-top {
|
|
40
|
+
@apply fixed top-0 left-0 right-0 bottom-auto m-0 w-full max-w-full bg-card text-card-foreground;
|
|
41
|
+
max-height: min(85vh, 600px);
|
|
42
|
+
border-radius: 0 0 20px 20px;
|
|
43
|
+
box-shadow: 0 8px 32px oklch(0 0 0 / 0.1), var(--float-ring);
|
|
44
|
+
&::backdrop {
|
|
45
|
+
background: var(--backdrop-bg);
|
|
46
|
+
backdrop-filter: var(--glass-blur);
|
|
47
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
48
|
+
}
|
|
49
|
+
&[open] { animation: sheetSlideInTop 0.35s var(--apple-spring); }
|
|
50
|
+
& > header {
|
|
51
|
+
@apply px-6 py-5;
|
|
52
|
+
& h2 { @apply text-[20px] font-semibold tracking-tight text-foreground; }
|
|
53
|
+
& p { @apply mt-1 text-[13px] text-muted-foreground; }
|
|
54
|
+
}
|
|
55
|
+
& > section {
|
|
56
|
+
@apply overflow-y-auto px-6 py-5;
|
|
57
|
+
}
|
|
58
|
+
& > footer {
|
|
59
|
+
@apply px-6 py-4;
|
|
60
|
+
border-top: 1px solid var(--panel-border);
|
|
61
|
+
}
|
|
62
|
+
& .sheet-close {
|
|
63
|
+
@apply absolute right-4 top-4 rounded-full p-1.5 text-muted-foreground cursor-pointer;
|
|
64
|
+
transition: all 0.2s var(--apple-ease);
|
|
65
|
+
&:hover { @apply text-foreground bg-accent; }
|
|
66
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: 2px; }
|
|
67
|
+
& svg { @apply size-4; }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* ========== DROPDOWN MENU ========== */
|
|
2
|
+
.dropdown-menu {
|
|
3
|
+
@apply absolute z-50 mt-1.5 min-w-[200px] rounded-xl p-1.5;
|
|
4
|
+
display: none;
|
|
5
|
+
background: var(--glass-bg);
|
|
6
|
+
backdrop-filter: var(--glass-blur);
|
|
7
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
8
|
+
box-shadow: var(--shadow-lg), var(--float-ring);
|
|
9
|
+
&[data-open] { display: block; }
|
|
10
|
+
& button, & a {
|
|
11
|
+
@apply flex w-full items-center gap-2.5 rounded-[8px] px-3 py-2 text-left text-[13px] text-foreground;
|
|
12
|
+
transition: background-color 0.12s var(--apple-ease);
|
|
13
|
+
&:hover { @apply bg-accent; }
|
|
14
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
15
|
+
& svg { @apply size-4 text-muted-foreground; }
|
|
16
|
+
}
|
|
17
|
+
& .dropdown-divider, & hr {
|
|
18
|
+
@apply my-1 h-px mx-1.5;
|
|
19
|
+
background: var(--panel-border);
|
|
20
|
+
}
|
|
21
|
+
& .dropdown-destructive {
|
|
22
|
+
color: var(--destructive);
|
|
23
|
+
&:hover { background: oklch(from var(--destructive) l c h / 0.08); }
|
|
24
|
+
&:is(.dark *) {
|
|
25
|
+
&:hover { background: oklch(from var(--destructive) l c h / 0.12); }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* ========== EMPTY ========== */
|
|
2
|
+
.empty {
|
|
3
|
+
@apply flex min-w-0 flex-1 flex-col items-center justify-center gap-3 rounded-2xl p-10 text-center text-balance;
|
|
4
|
+
& .empty-icon {
|
|
5
|
+
@apply mb-1 flex size-14 shrink-0 items-center justify-center rounded-2xl text-muted-foreground;
|
|
6
|
+
background: var(--surface-3);
|
|
7
|
+
& svg { @apply size-6; }
|
|
8
|
+
}
|
|
9
|
+
& h3 { @apply text-[20px] font-semibold tracking-tight text-foreground; }
|
|
10
|
+
& p { @apply text-[13px] text-muted-foreground; max-width: 28ch; }
|
|
11
|
+
& .empty-actions { @apply mt-3 flex gap-2; }
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* ========== FIELD (auto-styles children — form controls inherited from shared base above) ========== */
|
|
2
|
+
.field {
|
|
3
|
+
@apply space-y-1.5;
|
|
4
|
+
& > label { @apply text-[13px] font-medium text-foreground; }
|
|
5
|
+
& > p { @apply text-xs text-muted-foreground; }
|
|
6
|
+
& > p.field-error { color: var(--destructive); }
|
|
7
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* ========== FILE TREE ========== */
|
|
2
|
+
.file-tree {
|
|
3
|
+
@apply rounded-2xl bg-card;
|
|
4
|
+
box-shadow: var(--shadow-sm), var(--panel-ring);
|
|
5
|
+
|
|
6
|
+
& summary {
|
|
7
|
+
list-style: none;
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
&::-webkit-details-marker { display: none; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Root header */
|
|
13
|
+
& > summary {
|
|
14
|
+
@apply flex items-center justify-between rounded-2xl px-4 py-3 text-[13px] font-medium text-foreground;
|
|
15
|
+
transition: background-color 0.15s var(--apple-ease);
|
|
16
|
+
&:hover { background: var(--surface-1); }
|
|
17
|
+
}
|
|
18
|
+
&[open] > summary { @apply rounded-b-none; }
|
|
19
|
+
|
|
20
|
+
/* Tree body */
|
|
21
|
+
& > div {
|
|
22
|
+
@apply p-2;
|
|
23
|
+
|
|
24
|
+
& summary {
|
|
25
|
+
@apply flex items-center gap-1.5 rounded-lg px-2 py-1 text-[13px] text-foreground;
|
|
26
|
+
transition: background-color 0.15s var(--apple-ease);
|
|
27
|
+
&:hover { background: var(--surface-2); }
|
|
28
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
29
|
+
& > svg { @apply size-4 shrink-0 text-muted-foreground; }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
& .file-tree-chevron {
|
|
33
|
+
@apply size-3.5 shrink-0 text-muted-foreground;
|
|
34
|
+
transition: transform 0.2s var(--apple-ease);
|
|
35
|
+
}
|
|
36
|
+
& details[open] > summary > .file-tree-chevron {
|
|
37
|
+
transform: rotate(90deg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* 12px per nesting level (Xcode-like density) */
|
|
41
|
+
& details > div { @apply pl-3; }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* File item */
|
|
45
|
+
& .file-tree-item {
|
|
46
|
+
@apply flex cursor-pointer items-center gap-1.5 rounded-lg py-1 pr-2 text-[13px] text-muted-foreground;
|
|
47
|
+
padding-left: 1.75rem; /* aligns file icon with folder icon: px-2 + chevron + gap */
|
|
48
|
+
transition: background-color 0.15s var(--apple-ease);
|
|
49
|
+
&:hover { background: var(--surface-2); }
|
|
50
|
+
&:focus-visible { outline: 3px solid oklch(from var(--primary) l c h / 0.3); outline-offset: -3px; }
|
|
51
|
+
& > svg { @apply size-4 shrink-0; }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* ========== FORM CONTROLS (shared base) ========== */
|
|
2
|
+
.input,
|
|
3
|
+
.textarea,
|
|
4
|
+
.select,
|
|
5
|
+
.field > input:not([type="checkbox"]):not([type="radio"]),
|
|
6
|
+
.field > textarea,
|
|
7
|
+
.field > select {
|
|
8
|
+
@apply w-full rounded-[12px] border text-[13px] text-foreground outline-none;
|
|
9
|
+
background-color: var(--card);
|
|
10
|
+
transition: border-color 0.2s var(--apple-ease);
|
|
11
|
+
&::placeholder { @apply text-muted-foreground; opacity: 0.45; }
|
|
12
|
+
&:focus {
|
|
13
|
+
border-color: var(--primary);
|
|
14
|
+
}
|
|
15
|
+
&:disabled { @apply cursor-not-allowed opacity-50; }
|
|
16
|
+
}
|
|
17
|
+
/* Text inputs + textareas share border behavior */
|
|
18
|
+
.input,
|
|
19
|
+
.textarea,
|
|
20
|
+
.field > input:not([type="checkbox"]):not([type="radio"]),
|
|
21
|
+
.field > textarea {
|
|
22
|
+
border-color: var(--input-border);
|
|
23
|
+
&:hover:not(:focus) { border-color: var(--input-border-hover); }
|
|
24
|
+
}
|
|
25
|
+
/* Input sizing */
|
|
26
|
+
.input,
|
|
27
|
+
.field > input:not([type="checkbox"]):not([type="radio"]) {
|
|
28
|
+
@apply h-11 px-3.5;
|
|
29
|
+
}
|
|
30
|
+
/* Textarea sizing */
|
|
31
|
+
.textarea,
|
|
32
|
+
.field > textarea {
|
|
33
|
+
@apply px-3.5 py-3;
|
|
34
|
+
}
|
|
35
|
+
/* Select sizing + chevron */
|
|
36
|
+
.select,
|
|
37
|
+
.field > select {
|
|
38
|
+
@apply h-11 appearance-none pl-3.5 pr-10;
|
|
39
|
+
border-color: var(--input);
|
|
40
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%236E6E73' stroke-width='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
|
|
41
|
+
background-repeat: no-repeat;
|
|
42
|
+
background-position: right 0.75rem center;
|
|
43
|
+
background-size: 1rem;
|
|
44
|
+
&:is(.dark *) {
|
|
45
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2398989D' stroke-width='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
|
|
46
|
+
}
|
|
47
|
+
&:hover:not(:focus) { border-color: var(--border-solid); }
|
|
48
|
+
}
|
|
49
|
+
/* Error states */
|
|
50
|
+
.input[aria-invalid="true"], .input.input-error,
|
|
51
|
+
.textarea[aria-invalid="true"], .textarea.textarea-error,
|
|
52
|
+
.field > input[aria-invalid="true"], .field > input.input-error {
|
|
53
|
+
border-color: var(--destructive);
|
|
54
|
+
&:focus {
|
|
55
|
+
border-color: var(--destructive);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* ========== FORM ========== */
|
|
2
|
+
.fieldset {
|
|
3
|
+
@apply flex flex-col gap-5;
|
|
4
|
+
& legend {
|
|
5
|
+
@apply w-full text-base font-semibold tracking-tight text-foreground;
|
|
6
|
+
letter-spacing: -0.01em;
|
|
7
|
+
float: left;
|
|
8
|
+
}
|
|
9
|
+
& legend + p {
|
|
10
|
+
@apply mt-1 text-[13px] text-muted-foreground;
|
|
11
|
+
}
|
|
12
|
+
& hr {
|
|
13
|
+
background: var(--panel-border);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* ========== HOVER CARD ========== */
|
|
2
|
+
.hover-card {
|
|
3
|
+
@apply relative inline-block;
|
|
4
|
+
}
|
|
5
|
+
.hover-card-content {
|
|
6
|
+
@apply pointer-events-none absolute z-50 mt-2 min-w-[280px] rounded-2xl p-4;
|
|
7
|
+
background: var(--glass-bg-opaque);
|
|
8
|
+
backdrop-filter: var(--glass-blur);
|
|
9
|
+
-webkit-backdrop-filter: var(--glass-blur);
|
|
10
|
+
box-shadow: var(--shadow-lg), var(--float-ring);
|
|
11
|
+
opacity: 0;
|
|
12
|
+
transform: translateY(4px);
|
|
13
|
+
transition: opacity 0.2s var(--apple-ease), transform 0.2s var(--apple-ease);
|
|
14
|
+
}
|
|
15
|
+
.hover-card:hover .hover-card-content {
|
|
16
|
+
@apply pointer-events-auto;
|
|
17
|
+
opacity: 1;
|
|
18
|
+
transform: translateY(0);
|
|
19
|
+
}
|
|
20
|
+
.hover-card-bottom .hover-card-content {
|
|
21
|
+
@apply bottom-auto top-full mt-2;
|
|
22
|
+
}
|
|
23
|
+
.hover-card-top .hover-card-content {
|
|
24
|
+
@apply bottom-full top-auto mb-2 mt-0;
|
|
25
|
+
}
|