@sovereignfs/ui 0.23.0 → 0.33.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/Button.module.css +75 -8
- package/dist/Calendar.module.css +126 -0
- package/dist/Card.module.css +4 -2
- package/dist/Checkbox.module.css +14 -2
- package/dist/CodeTextarea.module.css +53 -0
- package/dist/ConfirmDialog.module.css +109 -0
- package/dist/DatePicker.module.css +57 -0
- package/dist/Dialog.module.css +73 -46
- package/dist/DragHandleRow.module.css +9 -3
- package/dist/Drawer.module.css +61 -0
- package/dist/Icon.module.css +5 -0
- package/dist/Menu.module.css +82 -0
- package/dist/NavTabs.module.css +4 -2
- package/dist/OverlayHeader.module.css +98 -0
- package/dist/Popover.module.css +31 -1
- package/dist/SegmentedControl.module.css +4 -2
- package/dist/Sheet.module.css +55 -0
- package/dist/SplitPane.module.css +85 -0
- package/dist/StatusBadge.module.css +59 -0
- package/dist/SystemBanner.module.css +4 -2
- package/dist/Tabs.module.css +4 -2
- package/dist/TagInput.module.css +141 -0
- package/dist/Toast.module.css +4 -2
- package/dist/Tooltip.module.css +6 -1
- package/dist/index.d.ts +493 -17
- package/dist/index.js +1390 -209
- package/dist/tokens/primitives.css +19 -0
- package/dist/tokens/semantic.css +13 -0
- package/package.json +1 -1
- package/src/__tests__/motion.test.tsx +105 -0
- package/src/components/Button/Button.module.css +75 -8
- package/src/components/Button/Button.stories.tsx +6 -0
- package/src/components/Button/Button.tsx +17 -1
- package/src/components/Button/__tests__/Button.test.tsx +19 -0
- package/src/components/Calendar/Calendar.module.css +126 -0
- package/src/components/Calendar/Calendar.tsx +213 -0
- package/src/components/Calendar/__tests__/Calendar.test.tsx +98 -0
- package/src/components/Calendar/dateUtils.ts +97 -0
- package/src/components/Card/Card.module.css +4 -2
- package/src/components/Checkbox/Checkbox.module.css +14 -2
- package/src/components/Checkbox/Checkbox.tsx +22 -12
- package/src/components/CodeTextarea/CodeTextarea.module.css +53 -0
- package/src/components/CodeTextarea/CodeTextarea.stories.tsx +77 -0
- package/src/components/CodeTextarea/CodeTextarea.tsx +36 -0
- package/src/components/ConfirmDialog/ConfirmDialog.module.css +109 -0
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +124 -0
- package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +146 -0
- package/src/components/DatePicker/DatePicker.module.css +57 -0
- package/src/components/DatePicker/DatePicker.tsx +103 -0
- package/src/components/DatePicker/__tests__/DatePicker.test.tsx +89 -0
- package/src/components/Dialog/Dialog.module.css +73 -46
- package/src/components/Dialog/Dialog.stories.tsx +51 -1
- package/src/components/Dialog/Dialog.tsx +86 -22
- package/src/components/Dialog/__tests__/Dialog.test.tsx +67 -3
- package/src/components/DragHandleRow/DragHandleRow.module.css +9 -3
- package/src/components/Drawer/Drawer.module.css +61 -0
- package/src/components/Drawer/Drawer.tsx +117 -13
- package/src/components/Drawer/__tests__/Drawer.test.tsx +123 -2
- package/src/components/Icon/Icon.module.css +5 -0
- package/src/components/Icon/Icon.stories.tsx +4 -3
- package/src/components/Icon/Icon.tsx +1 -1
- package/src/components/Icon/icons/calendar.tsx +23 -0
- package/src/components/Icon/icons/ellipsis-vertical.tsx +22 -0
- package/src/components/Icon/icons/index.ts +8 -4
- package/src/components/Icon/icons/sliders-horizontal.tsx +9 -9
- package/src/components/Menu/Menu.module.css +82 -0
- package/src/components/Menu/Menu.tsx +137 -0
- package/src/components/Menu/__tests__/Menu.test.tsx +197 -0
- package/src/components/NavTabs/NavTabs.module.css +4 -2
- package/src/components/OverlayHeader/OverlayHeader.module.css +98 -0
- package/src/components/OverlayHeader/OverlayHeader.tsx +62 -0
- package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +51 -0
- package/src/components/Popover/Popover.module.css +31 -1
- package/src/components/Popover/Popover.stories.tsx +126 -1
- package/src/components/Popover/Popover.tsx +140 -7
- package/src/components/SegmentedControl/SegmentedControl.module.css +4 -2
- package/src/components/Sheet/Sheet.module.css +55 -0
- package/src/components/Sheet/Sheet.tsx +151 -0
- package/src/components/Sheet/__tests__/Sheet.test.tsx +99 -0
- package/src/components/SplitPane/SplitPane.module.css +85 -0
- package/src/components/SplitPane/SplitPane.stories.tsx +160 -0
- package/src/components/SplitPane/SplitPane.tsx +149 -0
- package/src/components/SplitPane/__tests__/SplitPane.test.tsx +51 -0
- package/src/components/StatusBadge/StatusBadge.module.css +59 -0
- package/src/components/StatusBadge/StatusBadge.stories.tsx +74 -0
- package/src/components/StatusBadge/StatusBadge.tsx +65 -0
- package/src/components/SystemBanner/SystemBanner.module.css +4 -2
- package/src/components/Tabs/Tabs.module.css +4 -2
- package/src/components/TagInput/TagInput.module.css +141 -0
- package/src/components/TagInput/TagInput.stories.tsx +109 -0
- package/src/components/TagInput/TagInput.tsx +174 -0
- package/src/components/TagInput/__tests__/TagInput.test.tsx +69 -0
- package/src/components/Toast/Toast.module.css +4 -2
- package/src/components/Tooltip/Tooltip.module.css +6 -1
- package/src/hooks/__tests__/useDoubleTap.test.tsx +117 -0
- package/src/hooks/__tests__/useIsMobile.test.tsx +80 -0
- package/src/hooks/__tests__/useLongPress.test.tsx +158 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useDoubleTap.ts +91 -0
- package/src/hooks/useIsMobile.ts +33 -0
- package/src/hooks/useLongPress.ts +185 -0
- package/src/index.ts +30 -1
- package/src/motion.ts +78 -0
- package/src/stories/DesignSystemOverview.stories.tsx +292 -4
- package/src/stories/InteractionHooks.stories.tsx +388 -0
- package/src/stories/TokenGallery.stories.tsx +85 -1
- package/src/tokens/primitives.css +19 -0
- package/src/tokens/semantic.css +13 -0
- package/src/components/Icon/icons/terminal.tsx +0 -19
|
@@ -5,9 +5,15 @@
|
|
|
5
5
|
position: relative;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
/* Hover-reveal only where hover genuinely exists — on touch the handle would
|
|
9
|
+
otherwise never become visible (tap-generated hover doesn't count as a
|
|
10
|
+
sustained hover state, and :not(:hover) is always true with no hover
|
|
11
|
+
capability at all), so it stays visible by default there. */
|
|
12
|
+
@media (hover: hover) {
|
|
13
|
+
.row:not(:hover) .handle,
|
|
14
|
+
.row:not(:focus-within) .handle {
|
|
15
|
+
opacity: 0;
|
|
16
|
+
}
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
.handle {
|
package/dist/Drawer.module.css
CHANGED
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
display: flex;
|
|
15
15
|
align-items: flex-end;
|
|
16
16
|
background: var(--sv-color-scrim);
|
|
17
|
+
/* Entrance/exit fade — same two-phase-mount pattern as Dialog (see motion.ts
|
|
18
|
+
and Drawer.tsx). */
|
|
19
|
+
opacity: 0;
|
|
20
|
+
transition: opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.scrimOpen {
|
|
24
|
+
opacity: 1;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
.panel {
|
|
@@ -28,4 +36,57 @@
|
|
|
28
36
|
/* Pull content above the home indicator / bottom bar in standalone mode. */
|
|
29
37
|
padding-bottom: env(safe-area-inset-bottom);
|
|
30
38
|
outline: none;
|
|
39
|
+
/* Slide up from below the viewport. Always a bottom sheet, so unlike Dialog
|
|
40
|
+
there's no desktop-vs-mobile fork here. */
|
|
41
|
+
transform: translateY(100%);
|
|
42
|
+
transition: transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.panelOpen {
|
|
46
|
+
transform: translateY(0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* 'half' snapHeight — a fixed height instead of the default content-sized cap
|
|
50
|
+
* above. Per the design-system's "half screen or less" convention for
|
|
51
|
+
* Drawer; content taller than this belongs in Sheet instead. */
|
|
52
|
+
.panelHalf {
|
|
53
|
+
height: 50dvh;
|
|
54
|
+
max-height: 50dvh;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* See Dialog.module.css's identical rule for why 0.01ms rather than 0. */
|
|
58
|
+
@media (prefers-reduced-motion: reduce) {
|
|
59
|
+
.scrim,
|
|
60
|
+
.panel {
|
|
61
|
+
transition-duration: 0.01ms;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Grab handle — the sole drag-initiation region for swipe-down-to-dismiss
|
|
66
|
+
* (see Drawer.tsx's doc comment for why not the whole panel). The visual bar
|
|
67
|
+
* (::before) stays the small, established 36x4px size; only the hit area
|
|
68
|
+
* grows to a comfortable touch target. */
|
|
69
|
+
.handle {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: var(--sv-touch-target-min, 44px);
|
|
75
|
+
flex-shrink: 0;
|
|
76
|
+
cursor: grab;
|
|
77
|
+
/* JS-driven drag — the browser must not treat a press here as a
|
|
78
|
+
scroll/pan gesture that would fight it. */
|
|
79
|
+
touch-action: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.handle:active {
|
|
83
|
+
cursor: grabbing;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.handle::before {
|
|
87
|
+
content: '';
|
|
88
|
+
width: 36px;
|
|
89
|
+
height: 4px;
|
|
90
|
+
border-radius: var(--sv-radius-full);
|
|
91
|
+
background: var(--sv-color-border-strong);
|
|
31
92
|
}
|
package/dist/Icon.module.css
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* Menu — the item list shared by both presentations (Popover panel on
|
|
2
|
+
* desktop, Drawer panel on mobile); the presentational chrome around it is
|
|
3
|
+
* entirely owned by those two components, not duplicated here. */
|
|
4
|
+
|
|
5
|
+
.list {
|
|
6
|
+
list-style: none;
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: var(--sv-space-1);
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.item {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: var(--sv-space-2);
|
|
17
|
+
width: 100%;
|
|
18
|
+
/* Min touch target (WCAG 2.5.5 / Apple HIG) — this menu renders as a
|
|
19
|
+
Drawer sheet on mobile, so every item must be comfortably tappable. */
|
|
20
|
+
min-height: var(--sv-touch-target-min, 44px);
|
|
21
|
+
padding: var(--sv-space-2) var(--sv-space-3);
|
|
22
|
+
border: none;
|
|
23
|
+
border-radius: var(--sv-radius-sm);
|
|
24
|
+
background: transparent;
|
|
25
|
+
color: var(--sv-color-text-primary);
|
|
26
|
+
font: inherit;
|
|
27
|
+
font-size: var(--sv-font-size-sm);
|
|
28
|
+
text-align: left;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@media (hover: hover) {
|
|
33
|
+
.item:hover:not(:disabled) {
|
|
34
|
+
background: var(--sv-color-surface-sunken);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.item:focus-visible {
|
|
39
|
+
outline: 2px solid var(--sv-color-focus-ring);
|
|
40
|
+
outline-offset: -2px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.item:disabled {
|
|
44
|
+
opacity: 0.5;
|
|
45
|
+
cursor: not-allowed;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.itemDestructive {
|
|
49
|
+
color: var(--sv-color-error-text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@media (hover: hover) {
|
|
53
|
+
.itemDestructive:hover:not(:disabled) {
|
|
54
|
+
background: var(--sv-color-error-surface);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Reserved checkmark gutter for a checkable item — sized so unchecked
|
|
59
|
+
siblings in the same group still align with the checked one's icon. */
|
|
60
|
+
.check {
|
|
61
|
+
display: inline-flex;
|
|
62
|
+
flex-shrink: 0;
|
|
63
|
+
width: var(--sv-icon-size-sm);
|
|
64
|
+
height: var(--sv-icon-size-sm);
|
|
65
|
+
align-items: center;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.label {
|
|
70
|
+
padding: var(--sv-space-2) var(--sv-space-3) var(--sv-space-1);
|
|
71
|
+
font-size: var(--sv-font-size-label);
|
|
72
|
+
font-weight: var(--sv-font-weight-semibold);
|
|
73
|
+
color: var(--sv-color-text-muted);
|
|
74
|
+
text-transform: uppercase;
|
|
75
|
+
letter-spacing: 0.04em;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.separator {
|
|
79
|
+
height: 1px;
|
|
80
|
+
margin: var(--sv-space-1) var(--sv-space-2);
|
|
81
|
+
background: var(--sv-color-border);
|
|
82
|
+
}
|
package/dist/NavTabs.module.css
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* OverlayHeader — shared fixed secondary header for Dialog's mobile mode,
|
|
2
|
+
* Sheet, and Drawer. Not itself pinned via position — the consumer renders it
|
|
3
|
+
* as a flex-shrink: 0 sibling before its own scrolling content region (see
|
|
4
|
+
* the component's own doc comment). */
|
|
5
|
+
|
|
6
|
+
.header {
|
|
7
|
+
flex-shrink: 0;
|
|
8
|
+
background: var(--sv-color-surface);
|
|
9
|
+
border-bottom: 1px solid var(--sv-color-border);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.row {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: var(--sv-space-2);
|
|
16
|
+
padding: var(--sv-space-3) var(--sv-space-4);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.backButton {
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
width: var(--sv-touch-target-min, 44px);
|
|
24
|
+
height: var(--sv-touch-target-min, 44px);
|
|
25
|
+
flex-shrink: 0;
|
|
26
|
+
/* Pull the touch-target padding back so the chevron glyph still sits close
|
|
27
|
+
to the title, matching the visual (not hit-area) spacing of .row's own
|
|
28
|
+
gap — otherwise a 44px box reads as a large empty gap before the title. */
|
|
29
|
+
margin-left: calc(-1 * (var(--sv-touch-target-min, 44px) - var(--sv-icon-size-md)) / 2);
|
|
30
|
+
margin-right: calc(
|
|
31
|
+
-1 * (var(--sv-touch-target-min, 44px) - var(--sv-icon-size-md)) / 2 + var(--sv-space-1)
|
|
32
|
+
);
|
|
33
|
+
border: none;
|
|
34
|
+
border-radius: var(--sv-radius-md);
|
|
35
|
+
background: transparent;
|
|
36
|
+
color: var(--sv-color-text-muted);
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@media (hover: hover) {
|
|
41
|
+
.backButton:hover {
|
|
42
|
+
background: var(--sv-color-surface-sunken);
|
|
43
|
+
color: var(--sv-color-text-primary);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.backButton:focus-visible {
|
|
48
|
+
outline: 2px solid var(--sv-color-focus-ring);
|
|
49
|
+
outline-offset: -2px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.title {
|
|
53
|
+
flex: 1;
|
|
54
|
+
min-width: 0;
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
text-overflow: ellipsis;
|
|
57
|
+
white-space: nowrap;
|
|
58
|
+
font-size: var(--sv-font-size-xl);
|
|
59
|
+
font-weight: var(--sv-font-weight-semibold);
|
|
60
|
+
color: var(--sv-color-text-primary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.action {
|
|
64
|
+
flex-shrink: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.closeButton {
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
width: var(--sv-touch-target-min, 44px);
|
|
72
|
+
height: var(--sv-touch-target-min, 44px);
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
/* Pull the touch-target padding back so the × sits flush with the row's own
|
|
75
|
+
edge padding, same reasoning as .backButton above. */
|
|
76
|
+
margin-right: calc(-1 * (var(--sv-touch-target-min, 44px) - var(--sv-icon-size-sm)) / 2);
|
|
77
|
+
border: none;
|
|
78
|
+
border-radius: var(--sv-radius-md);
|
|
79
|
+
background: transparent;
|
|
80
|
+
color: var(--sv-color-text-muted);
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@media (hover: hover) {
|
|
85
|
+
.closeButton:hover {
|
|
86
|
+
background: var(--sv-color-surface-sunken);
|
|
87
|
+
color: var(--sv-color-text-primary);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.closeButton:focus-visible {
|
|
92
|
+
outline: 2px solid var(--sv-color-focus-ring);
|
|
93
|
+
outline-offset: -2px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.secondRow {
|
|
97
|
+
padding: 0 var(--sv-space-2) var(--sv-space-2);
|
|
98
|
+
}
|
package/dist/Popover.module.css
CHANGED
|
@@ -11,7 +11,16 @@
|
|
|
11
11
|
border: 1px solid var(--sv-color-border);
|
|
12
12
|
border-radius: var(--sv-radius-2xl);
|
|
13
13
|
box-shadow: var(--sv-shadow-popover);
|
|
14
|
-
|
|
14
|
+
/* auto, not hidden: Popover.tsx applies an inline max-height only when the
|
|
15
|
+
panel is taller than the room actually available on whichever side it
|
|
16
|
+
opens (e.g. a tall calendar on a short mobile viewport, where neither
|
|
17
|
+
above nor below has enough space for the whole thing) — auto lets that
|
|
18
|
+
capped case scroll internally instead of silently clipping content with
|
|
19
|
+
no way to reach it. When no max-height is applied (the common case, panel
|
|
20
|
+
already fits), auto behaves identically to hidden — nothing to scroll,
|
|
21
|
+
content still clips at the rounded corners exactly as before. */
|
|
22
|
+
overflow-x: hidden;
|
|
23
|
+
overflow-y: auto;
|
|
15
24
|
/* Slide in from slightly above */
|
|
16
25
|
animation: sv-popover-in 0.12s ease;
|
|
17
26
|
}
|
|
@@ -42,3 +51,24 @@
|
|
|
42
51
|
.left {
|
|
43
52
|
left: 0;
|
|
44
53
|
}
|
|
54
|
+
|
|
55
|
+
/* Collision flip: opens above the trigger instead of below, when the panel
|
|
56
|
+
wouldn't fit within the viewport underneath it (see Popover.tsx's
|
|
57
|
+
layout-effect measurement). Same slide-in treatment, mirrored to slide up
|
|
58
|
+
from slightly below instead of down from slightly above. */
|
|
59
|
+
.upward {
|
|
60
|
+
top: auto;
|
|
61
|
+
bottom: calc(100% + var(--sv-space-2));
|
|
62
|
+
animation-name: sv-popover-in-upward;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@keyframes sv-popover-in-upward {
|
|
66
|
+
from {
|
|
67
|
+
opacity: 0;
|
|
68
|
+
transform: translateY(4px);
|
|
69
|
+
}
|
|
70
|
+
to {
|
|
71
|
+
opacity: 1;
|
|
72
|
+
transform: translateY(0);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Sheet — fills the same rect as a plugin's content area (between the shell's
|
|
2
|
+
* sticky header and footer nav — see --sv-shell-header-height /
|
|
3
|
+
* --sv-shell-footer-height, set by the shell), sliding in from an edge
|
|
4
|
+
* instead of Dialog's centered box or Drawer's partial-height sheet-over-
|
|
5
|
+
* scrim. z-index matches Dialog/Drawer's scrim so it layers consistently
|
|
6
|
+
* with any other overlay. No scrim of its own — see the component doc
|
|
7
|
+
* comment for why. */
|
|
8
|
+
|
|
9
|
+
.panel {
|
|
10
|
+
position: fixed;
|
|
11
|
+
left: 0;
|
|
12
|
+
right: 0;
|
|
13
|
+
top: var(--sv-shell-header-height, 0);
|
|
14
|
+
bottom: var(--sv-shell-footer-height, 0);
|
|
15
|
+
z-index: 100;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
background: var(--sv-color-surface);
|
|
19
|
+
outline: none;
|
|
20
|
+
transform: translateY(100%);
|
|
21
|
+
transition: transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.panelOpen {
|
|
25
|
+
transform: translateY(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Opt-in top variant (slideFrom="top") — a short options/actions menu opened
|
|
29
|
+
* from a header button reads more naturally sliding down from that button's
|
|
30
|
+
* edge than traveling up from off-screen bottom. :not(.panelOpen) is what
|
|
31
|
+
* lets this coexist with .panelOpen above despite equal-looking single-class
|
|
32
|
+
* specificity elsewhere in this file: its (0,2,0) beats .panelOpen's (0,1,0)
|
|
33
|
+
* while closed/entering/closing, and yields to it (transform: translateY(0),
|
|
34
|
+
* same value either direction) once open. */
|
|
35
|
+
.panelFromTop:not(.panelOpen) {
|
|
36
|
+
transform: translateY(-100%);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* See Dialog.module.css's identical rule for why 0.01ms rather than 0. */
|
|
40
|
+
@media (prefers-reduced-motion: reduce) {
|
|
41
|
+
.panel {
|
|
42
|
+
transition-duration: 0.01ms;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Always the scroll container, with or without OverlayHeader present (see
|
|
47
|
+
* Sheet.tsx). No opinionated padding here — matches Drawer's convention of
|
|
48
|
+
* leaving horizontal/top padding and safe-area-bottom clearance to the
|
|
49
|
+
* content itself, since a Sheet's content shape varies far more than a
|
|
50
|
+
* fixed-size Dialog's. */
|
|
51
|
+
.content {
|
|
52
|
+
flex: 1 1 auto;
|
|
53
|
+
overflow-y: auto;
|
|
54
|
+
overscroll-behavior: contain;
|
|
55
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
.splitPane {
|
|
2
|
+
display: grid;
|
|
3
|
+
grid-template-columns:
|
|
4
|
+
minmax(0, var(--split-pane-primary-size, 50%)) 12px
|
|
5
|
+
minmax(0, calc(100% - var(--split-pane-primary-size, 50%)));
|
|
6
|
+
width: 100%;
|
|
7
|
+
min-height: 320px;
|
|
8
|
+
border: 1px solid var(--sv-color-border);
|
|
9
|
+
border-radius: var(--sv-radius-lg);
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
background: var(--sv-color-surface);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.splitPane:not(:has(.handle)) {
|
|
15
|
+
grid-template-columns:
|
|
16
|
+
minmax(0, var(--split-pane-primary-size, 50%))
|
|
17
|
+
minmax(0, calc(100% - var(--split-pane-primary-size, 50%)));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.pane {
|
|
21
|
+
min-width: 0;
|
|
22
|
+
min-height: 0;
|
|
23
|
+
overflow: auto;
|
|
24
|
+
background: var(--sv-color-surface);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.pane + .pane {
|
|
28
|
+
border-left: 1px solid var(--sv-color-border);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.handle {
|
|
32
|
+
position: relative;
|
|
33
|
+
width: 12px;
|
|
34
|
+
min-width: 12px;
|
|
35
|
+
padding: 0;
|
|
36
|
+
border: 0;
|
|
37
|
+
border-inline: 1px solid var(--sv-color-border);
|
|
38
|
+
cursor: col-resize;
|
|
39
|
+
background: var(--sv-color-surface-sunken);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.handle::before {
|
|
43
|
+
position: absolute;
|
|
44
|
+
inset-block: 50%;
|
|
45
|
+
inset-inline: 50%;
|
|
46
|
+
width: 2px;
|
|
47
|
+
height: 40px;
|
|
48
|
+
content: '';
|
|
49
|
+
background: var(--sv-color-border-strong);
|
|
50
|
+
border-radius: var(--sv-radius-full);
|
|
51
|
+
transform: translate(-50%, -50%);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@media (hover: hover) {
|
|
55
|
+
.handle:hover {
|
|
56
|
+
background: var(--sv-color-accent-subtle);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.handle:focus-visible {
|
|
61
|
+
background: var(--sv-color-accent-subtle);
|
|
62
|
+
outline: 2px solid var(--sv-color-focus-ring);
|
|
63
|
+
outline-offset: -2px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@media (max-width: 720px) {
|
|
67
|
+
.splitPane,
|
|
68
|
+
.splitPane:not(:has(.handle)) {
|
|
69
|
+
grid-template-columns: 1fr;
|
|
70
|
+
min-height: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.handle {
|
|
74
|
+
display: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.pane {
|
|
78
|
+
min-height: 220px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.pane + .pane {
|
|
82
|
+
border-top: 1px solid var(--sv-color-border);
|
|
83
|
+
border-left: 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
.badge {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
max-width: 100%;
|
|
5
|
+
min-height: 24px;
|
|
6
|
+
gap: var(--sv-space-1);
|
|
7
|
+
padding: 2px var(--sv-space-2);
|
|
8
|
+
border: 1px solid var(--sv-color-border);
|
|
9
|
+
border-radius: var(--sv-radius-full);
|
|
10
|
+
font-family: var(--sv-font-family);
|
|
11
|
+
font-size: var(--sv-font-size-xs);
|
|
12
|
+
font-weight: var(--sv-font-weight-semibold);
|
|
13
|
+
line-height: 1.2;
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dot {
|
|
18
|
+
width: 7px;
|
|
19
|
+
height: 7px;
|
|
20
|
+
flex: 0 0 auto;
|
|
21
|
+
border-radius: var(--sv-radius-full);
|
|
22
|
+
background: currentColor;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.label {
|
|
26
|
+
min-width: 0;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
text-overflow: ellipsis;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.neutral {
|
|
32
|
+
color: var(--sv-color-text-muted);
|
|
33
|
+
background: var(--sv-color-surface-sunken);
|
|
34
|
+
border-color: var(--sv-color-border);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.info {
|
|
38
|
+
color: var(--sv-color-info-text);
|
|
39
|
+
background: var(--sv-color-info-surface);
|
|
40
|
+
border-color: var(--sv-color-info-border);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.success {
|
|
44
|
+
color: var(--sv-color-success-text);
|
|
45
|
+
background: var(--sv-color-success-surface);
|
|
46
|
+
border-color: var(--sv-color-success-border);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.warning {
|
|
50
|
+
color: var(--sv-color-warning-text);
|
|
51
|
+
background: var(--sv-color-warning-surface);
|
|
52
|
+
border-color: var(--sv-color-warning-border);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.error {
|
|
56
|
+
color: var(--sv-color-error-text);
|
|
57
|
+
background: var(--sv-color-error-surface);
|
|
58
|
+
border-color: var(--sv-color-error-border);
|
|
59
|
+
}
|