@xenosystem/elements-react 0.0.1 → 0.0.3
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/LICENSE +18 -18
- package/README.md +41 -41
- package/package.json +58 -58
- package/src/chrome-separated.css +132 -132
- package/src/chrome-unified.css +72 -72
- package/src/containers/Badges.css +116 -116
- package/src/containers/avatar.css +70 -70
- package/src/containers/card.css +75 -75
- package/src/containers/chip.css +103 -103
- package/src/containers/list-row.css +132 -132
- package/src/containers/message-bubble.css +112 -112
- package/src/containers/panel.css +120 -120
- package/src/containers/table.css +102 -102
- package/src/containers/tile.css +17 -17
- package/src/content/callout.css +77 -77
- package/src/content/caret.css +30 -30
- package/src/content/code-block.css +159 -159
- package/src/content/collapsible.css +80 -80
- package/src/content/inline-code.css +14 -14
- package/src/content/model-picker.css +219 -219
- package/src/content/source-card.css +99 -99
- package/src/content/sources-disclosure.css +118 -118
- package/src/controls.css +453 -453
- package/src/fonts.css +34 -34
- package/src/forms/Checkbox.css +114 -114
- package/src/forms/RadioGroup.css +115 -115
- package/src/goo.css +97 -97
- package/src/icon-motion.css +1909 -1909
- package/src/layout/ResizablePanel.css +79 -79
- package/src/nav/sidebar.css +296 -296
- package/src/overlays/date-time-picker.css +238 -238
- package/src/overlays/menu.css +195 -195
- package/src/overlays/modal.css +167 -167
- package/src/overlays/picker-field.css +81 -81
- package/src/overlays/pill-filter.css +129 -129
- package/src/overlays/reveal.css +56 -56
- package/src/overlays/segmented-control.css +185 -185
- package/src/overlays/tabs.css +143 -143
- package/src/overlays/tooltip.css +126 -126
- package/src/scrollbar.css +184 -184
- package/src/size.css +179 -179
- package/src/status/progress-bar.css +88 -88
- package/src/status/spinner.css +33 -33
- package/src/status/statusindicator.css +65 -65
- package/src/status/steptimeline.css +137 -137
- package/src/status/thinkingcube.css +75 -75
- package/src/xeno-element.css +60 -60
- package/src/xeno-elements.css +71 -71
- package/src/xeno-theme.css +99 -99
package/src/overlays/tabs.css
CHANGED
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* <Tabs> — a horizontal tablist over a hairline baseline, plus an optional panel. CSS-first: the
|
|
3
|
-
* selected tab carries `data-selection="on"`, a disabled tab carries `data-availability="disabled"`.
|
|
4
|
-
* Size metrics arrive as inline `--xeno-h/-padx/-gap/-font` vars from the size tokens. Monochrome only.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
.xeno-tabs {
|
|
8
|
-
display: flex;
|
|
9
|
-
flex-direction: column;
|
|
10
|
-
gap: 16px;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.xeno-tablist {
|
|
14
|
-
position: relative; /* the containing block the indicator's measured offset is relative to */
|
|
15
|
-
display: inline-flex;
|
|
16
|
-
align-items: stretch;
|
|
17
|
-
gap: 2px;
|
|
18
|
-
border-bottom: 1px solid var(--xeno-border);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
.xeno-tab {
|
|
22
|
-
position: relative;
|
|
23
|
-
display: inline-flex;
|
|
24
|
-
align-items: center;
|
|
25
|
-
justify-content: center;
|
|
26
|
-
gap: var(--xeno-gap, 6px);
|
|
27
|
-
height: var(--xeno-h, 32px);
|
|
28
|
-
padding: 0 var(--xeno-padx, 12px);
|
|
29
|
-
font-family: inherit;
|
|
30
|
-
font-size: var(--xeno-font, 14px);
|
|
31
|
-
font-weight: 500;
|
|
32
|
-
line-height: 1;
|
|
33
|
-
white-space: nowrap;
|
|
34
|
-
color: var(--xeno-muted);
|
|
35
|
-
background: transparent;
|
|
36
|
-
border: none;
|
|
37
|
-
cursor: pointer;
|
|
38
|
-
user-select: none;
|
|
39
|
-
transition: color var(--xeno-dur) var(--xeno-ease);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* The underline — ONE hairline bar for the whole tablist, which SLIDES from the tab you left to the tab
|
|
43
|
-
you chose. It used to be a `::after` on each tab scaling from 0 to 1, so it appeared on the new tab
|
|
44
|
-
and vanished from the old one: two events, no journey, and no clue where it came from.
|
|
45
|
-
Its position and width arrive as `--xeno-tab-x` / `--xeno-tab-w`, measured by the component (a tab is
|
|
46
|
-
as wide as its label — layout is the only thing that can answer that). Everything after those two
|
|
47
|
-
numbers is CSS: the travel, the stretch, and the settle. */
|
|
48
|
-
.xeno-tab-indicator {
|
|
49
|
-
/* Mid-flight the bar ELONGATES along its travel and thins — reaching for where it is going — then
|
|
50
|
-
rebounds a hair as it lands. Both scale with how far it has to go (`--xeno-tab-dist`). */
|
|
51
|
-
--xeno-tab-stretch: 0.22;
|
|
52
|
-
--xeno-tab-thin: 0.2;
|
|
53
|
-
--xeno-tab-goo-x: calc(1 + var(--xeno-tab-stretch) * var(--xeno-tab-dist, 1));
|
|
54
|
-
--xeno-tab-goo-y: calc(1 - var(--xeno-tab-thin) * var(--xeno-tab-dist, 1));
|
|
55
|
-
--xeno-tab-goo-x2: calc(1 - var(--xeno-tab-thin) * 0.25);
|
|
56
|
-
--xeno-tab-goo-y2: calc(1 + var(--xeno-tab-thin) * 0.25);
|
|
57
|
-
/* ONE duration for the travel and the deformation, or the stretch peaks off-centre and reads as a
|
|
58
|
-
glitch rather than as weight. */
|
|
59
|
-
--xeno-tab-dur: 300ms;
|
|
60
|
-
--xeno-tab-ease: cubic-bezier(0.34, 1.12, 0.5, 1);
|
|
61
|
-
position: absolute;
|
|
62
|
-
left: 0;
|
|
63
|
-
bottom: -1px;
|
|
64
|
-
width: var(--xeno-tab-w, 0px);
|
|
65
|
-
height: 2px;
|
|
66
|
-
translate: var(--xeno-tab-x, 0px) 0;
|
|
67
|
-
background: var(--xeno-text);
|
|
68
|
-
/* Square. At 2px tall even `--xeno-radius-hair` is 75% of the height — semicircular ends, i.e. a
|
|
69
|
-
capsule. Below about 4px there is no radius that reads as a corner, so a hairline stays a hairline. */
|
|
70
|
-
border-radius: 0;
|
|
71
|
-
pointer-events: none;
|
|
72
|
-
}
|
|
73
|
-
/* Not armed until the selection has actually changed once — otherwise the first measurement after mount
|
|
74
|
-
would slide the bar in from the left edge on page load. */
|
|
75
|
-
.xeno-tablist[data-motion='ready'] .xeno-tab-indicator {
|
|
76
|
-
transition:
|
|
77
|
-
translate var(--xeno-tab-dur) var(--xeno-tab-ease),
|
|
78
|
-
width var(--xeno-tab-dur) var(--xeno-tab-ease);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.xeno-tab:hover:not([data-availability='disabled']) {
|
|
82
|
-
color: var(--xeno-text);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.xeno-tab[data-selection='on'] {
|
|
86
|
-
color: var(--xeno-text);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/* The stretch, keyed off the tablist's `data-index`. One keyframe track per position, all identical:
|
|
90
|
-
moving to another tab only changes which rule matches, and a browser will not restart an animation
|
|
91
|
-
whose name did not change. Eight positions; past that the bar still travels, it just stops
|
|
92
|
-
stretching. */
|
|
93
|
-
.xeno-tablist[data-motion='ready'][data-index='0'] .xeno-tab-indicator { animation: xeno-tab-goo-0 var(--xeno-tab-dur) 1; }
|
|
94
|
-
.xeno-tablist[data-motion='ready'][data-index='1'] .xeno-tab-indicator { animation: xeno-tab-goo-1 var(--xeno-tab-dur) 1; }
|
|
95
|
-
.xeno-tablist[data-motion='ready'][data-index='2'] .xeno-tab-indicator { animation: xeno-tab-goo-2 var(--xeno-tab-dur) 1; }
|
|
96
|
-
.xeno-tablist[data-motion='ready'][data-index='3'] .xeno-tab-indicator { animation: xeno-tab-goo-3 var(--xeno-tab-dur) 1; }
|
|
97
|
-
.xeno-tablist[data-motion='ready'][data-index='4'] .xeno-tab-indicator { animation: xeno-tab-goo-4 var(--xeno-tab-dur) 1; }
|
|
98
|
-
.xeno-tablist[data-motion='ready'][data-index='5'] .xeno-tab-indicator { animation: xeno-tab-goo-5 var(--xeno-tab-dur) 1; }
|
|
99
|
-
.xeno-tablist[data-motion='ready'][data-index='6'] .xeno-tab-indicator { animation: xeno-tab-goo-6 var(--xeno-tab-dur) 1; }
|
|
100
|
-
.xeno-tablist[data-motion='ready'][data-index='7'] .xeno-tab-indicator { animation: xeno-tab-goo-7 var(--xeno-tab-dur) 1; }
|
|
101
|
-
@keyframes xeno-tab-goo-0 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
102
|
-
@keyframes xeno-tab-goo-1 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
103
|
-
@keyframes xeno-tab-goo-2 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
104
|
-
@keyframes xeno-tab-goo-3 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
105
|
-
@keyframes xeno-tab-goo-4 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
106
|
-
@keyframes xeno-tab-goo-5 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
107
|
-
@keyframes xeno-tab-goo-6 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
108
|
-
@keyframes xeno-tab-goo-7 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
109
|
-
|
|
110
|
-
.xeno-tab:focus-visible {
|
|
111
|
-
outline: none;
|
|
112
|
-
border-radius: var(--xeno-radius-xs);
|
|
113
|
-
box-shadow:
|
|
114
|
-
0 0 0 2px var(--xeno-canvas),
|
|
115
|
-
0 0 0 4px var(--xeno-border);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.xeno-tab[data-availability='disabled'] {
|
|
119
|
-
opacity: 0.4;
|
|
120
|
-
cursor: not-allowed;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.xeno-tab-panel {
|
|
124
|
-
color: var(--xeno-text);
|
|
125
|
-
outline: none;
|
|
126
|
-
}
|
|
127
|
-
.xeno-tab-panel:focus-visible {
|
|
128
|
-
border-radius: var(--xeno-radius-sm);
|
|
129
|
-
box-shadow:
|
|
130
|
-
0 0 0 2px var(--xeno-canvas),
|
|
131
|
-
0 0 0 4px var(--xeno-border);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
@media (prefers-reduced-motion: reduce) {
|
|
135
|
-
.xeno-tab,
|
|
136
|
-
.xeno-tablist[data-motion='ready'] .xeno-tab-indicator {
|
|
137
|
-
transition: none;
|
|
138
|
-
}
|
|
139
|
-
/* The bar still marks the tab — it just gets there without travelling or stretching. */
|
|
140
|
-
.xeno-tab-indicator {
|
|
141
|
-
animation: none !important;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* <Tabs> — a horizontal tablist over a hairline baseline, plus an optional panel. CSS-first: the
|
|
3
|
+
* selected tab carries `data-selection="on"`, a disabled tab carries `data-availability="disabled"`.
|
|
4
|
+
* Size metrics arrive as inline `--xeno-h/-padx/-gap/-font` vars from the size tokens. Monochrome only.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.xeno-tabs {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: 16px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.xeno-tablist {
|
|
14
|
+
position: relative; /* the containing block the indicator's measured offset is relative to */
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: stretch;
|
|
17
|
+
gap: 2px;
|
|
18
|
+
border-bottom: 1px solid var(--xeno-border);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.xeno-tab {
|
|
22
|
+
position: relative;
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
gap: var(--xeno-gap, 6px);
|
|
27
|
+
height: var(--xeno-h, 32px);
|
|
28
|
+
padding: 0 var(--xeno-padx, 12px);
|
|
29
|
+
font-family: inherit;
|
|
30
|
+
font-size: var(--xeno-font, 14px);
|
|
31
|
+
font-weight: 500;
|
|
32
|
+
line-height: 1;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
color: var(--xeno-muted);
|
|
35
|
+
background: transparent;
|
|
36
|
+
border: none;
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
user-select: none;
|
|
39
|
+
transition: color var(--xeno-dur) var(--xeno-ease);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* The underline — ONE hairline bar for the whole tablist, which SLIDES from the tab you left to the tab
|
|
43
|
+
you chose. It used to be a `::after` on each tab scaling from 0 to 1, so it appeared on the new tab
|
|
44
|
+
and vanished from the old one: two events, no journey, and no clue where it came from.
|
|
45
|
+
Its position and width arrive as `--xeno-tab-x` / `--xeno-tab-w`, measured by the component (a tab is
|
|
46
|
+
as wide as its label — layout is the only thing that can answer that). Everything after those two
|
|
47
|
+
numbers is CSS: the travel, the stretch, and the settle. */
|
|
48
|
+
.xeno-tab-indicator {
|
|
49
|
+
/* Mid-flight the bar ELONGATES along its travel and thins — reaching for where it is going — then
|
|
50
|
+
rebounds a hair as it lands. Both scale with how far it has to go (`--xeno-tab-dist`). */
|
|
51
|
+
--xeno-tab-stretch: 0.22;
|
|
52
|
+
--xeno-tab-thin: 0.2;
|
|
53
|
+
--xeno-tab-goo-x: calc(1 + var(--xeno-tab-stretch) * var(--xeno-tab-dist, 1));
|
|
54
|
+
--xeno-tab-goo-y: calc(1 - var(--xeno-tab-thin) * var(--xeno-tab-dist, 1));
|
|
55
|
+
--xeno-tab-goo-x2: calc(1 - var(--xeno-tab-thin) * 0.25);
|
|
56
|
+
--xeno-tab-goo-y2: calc(1 + var(--xeno-tab-thin) * 0.25);
|
|
57
|
+
/* ONE duration for the travel and the deformation, or the stretch peaks off-centre and reads as a
|
|
58
|
+
glitch rather than as weight. */
|
|
59
|
+
--xeno-tab-dur: 300ms;
|
|
60
|
+
--xeno-tab-ease: cubic-bezier(0.34, 1.12, 0.5, 1);
|
|
61
|
+
position: absolute;
|
|
62
|
+
left: 0;
|
|
63
|
+
bottom: -1px;
|
|
64
|
+
width: var(--xeno-tab-w, 0px);
|
|
65
|
+
height: 2px;
|
|
66
|
+
translate: var(--xeno-tab-x, 0px) 0;
|
|
67
|
+
background: var(--xeno-text);
|
|
68
|
+
/* Square. At 2px tall even `--xeno-radius-hair` is 75% of the height — semicircular ends, i.e. a
|
|
69
|
+
capsule. Below about 4px there is no radius that reads as a corner, so a hairline stays a hairline. */
|
|
70
|
+
border-radius: 0;
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
}
|
|
73
|
+
/* Not armed until the selection has actually changed once — otherwise the first measurement after mount
|
|
74
|
+
would slide the bar in from the left edge on page load. */
|
|
75
|
+
.xeno-tablist[data-motion='ready'] .xeno-tab-indicator {
|
|
76
|
+
transition:
|
|
77
|
+
translate var(--xeno-tab-dur) var(--xeno-tab-ease),
|
|
78
|
+
width var(--xeno-tab-dur) var(--xeno-tab-ease);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.xeno-tab:hover:not([data-availability='disabled']) {
|
|
82
|
+
color: var(--xeno-text);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.xeno-tab[data-selection='on'] {
|
|
86
|
+
color: var(--xeno-text);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* The stretch, keyed off the tablist's `data-index`. One keyframe track per position, all identical:
|
|
90
|
+
moving to another tab only changes which rule matches, and a browser will not restart an animation
|
|
91
|
+
whose name did not change. Eight positions; past that the bar still travels, it just stops
|
|
92
|
+
stretching. */
|
|
93
|
+
.xeno-tablist[data-motion='ready'][data-index='0'] .xeno-tab-indicator { animation: xeno-tab-goo-0 var(--xeno-tab-dur) 1; }
|
|
94
|
+
.xeno-tablist[data-motion='ready'][data-index='1'] .xeno-tab-indicator { animation: xeno-tab-goo-1 var(--xeno-tab-dur) 1; }
|
|
95
|
+
.xeno-tablist[data-motion='ready'][data-index='2'] .xeno-tab-indicator { animation: xeno-tab-goo-2 var(--xeno-tab-dur) 1; }
|
|
96
|
+
.xeno-tablist[data-motion='ready'][data-index='3'] .xeno-tab-indicator { animation: xeno-tab-goo-3 var(--xeno-tab-dur) 1; }
|
|
97
|
+
.xeno-tablist[data-motion='ready'][data-index='4'] .xeno-tab-indicator { animation: xeno-tab-goo-4 var(--xeno-tab-dur) 1; }
|
|
98
|
+
.xeno-tablist[data-motion='ready'][data-index='5'] .xeno-tab-indicator { animation: xeno-tab-goo-5 var(--xeno-tab-dur) 1; }
|
|
99
|
+
.xeno-tablist[data-motion='ready'][data-index='6'] .xeno-tab-indicator { animation: xeno-tab-goo-6 var(--xeno-tab-dur) 1; }
|
|
100
|
+
.xeno-tablist[data-motion='ready'][data-index='7'] .xeno-tab-indicator { animation: xeno-tab-goo-7 var(--xeno-tab-dur) 1; }
|
|
101
|
+
@keyframes xeno-tab-goo-0 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
102
|
+
@keyframes xeno-tab-goo-1 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
103
|
+
@keyframes xeno-tab-goo-2 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
104
|
+
@keyframes xeno-tab-goo-3 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
105
|
+
@keyframes xeno-tab-goo-4 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
106
|
+
@keyframes xeno-tab-goo-5 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
107
|
+
@keyframes xeno-tab-goo-6 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
108
|
+
@keyframes xeno-tab-goo-7 { 0% { scale: 1 1; } 34% { scale: var(--xeno-tab-goo-x) var(--xeno-tab-goo-y); } 72% { scale: var(--xeno-tab-goo-x2) var(--xeno-tab-goo-y2); } 100% { scale: 1 1; } }
|
|
109
|
+
|
|
110
|
+
.xeno-tab:focus-visible {
|
|
111
|
+
outline: none;
|
|
112
|
+
border-radius: var(--xeno-radius-xs);
|
|
113
|
+
box-shadow:
|
|
114
|
+
0 0 0 2px var(--xeno-canvas),
|
|
115
|
+
0 0 0 4px var(--xeno-border);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.xeno-tab[data-availability='disabled'] {
|
|
119
|
+
opacity: 0.4;
|
|
120
|
+
cursor: not-allowed;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.xeno-tab-panel {
|
|
124
|
+
color: var(--xeno-text);
|
|
125
|
+
outline: none;
|
|
126
|
+
}
|
|
127
|
+
.xeno-tab-panel:focus-visible {
|
|
128
|
+
border-radius: var(--xeno-radius-sm);
|
|
129
|
+
box-shadow:
|
|
130
|
+
0 0 0 2px var(--xeno-canvas),
|
|
131
|
+
0 0 0 4px var(--xeno-border);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@media (prefers-reduced-motion: reduce) {
|
|
135
|
+
.xeno-tab,
|
|
136
|
+
.xeno-tablist[data-motion='ready'] .xeno-tab-indicator {
|
|
137
|
+
transition: none;
|
|
138
|
+
}
|
|
139
|
+
/* The bar still marks the tab — it just gets there without travelling or stretching. */
|
|
140
|
+
.xeno-tab-indicator {
|
|
141
|
+
animation: none !important;
|
|
142
|
+
}
|
|
143
|
+
}
|
package/src/overlays/tooltip.css
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Tooltip — a hover/focus hint. CSS-first reveal driven by `data-state` (JS-controlled), positioned on
|
|
3
|
-
* a `data-side` of the trigger. Monochrome shell: an elevated panel with a hairline border and muted
|
|
4
|
-
* 12px mono text; rounded squares only. Motion is transform/opacity, behind reduced-motion.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
.xeno-tooltip {
|
|
8
|
-
position: relative;
|
|
9
|
-
display: inline-flex;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.xeno-tooltip-panel {
|
|
13
|
-
position: absolute;
|
|
14
|
-
z-index: 50;
|
|
15
|
-
width: max-content;
|
|
16
|
-
max-width: 240px;
|
|
17
|
-
padding: 6px 8px;
|
|
18
|
-
background: var(--xeno-elevated);
|
|
19
|
-
border: 1px solid var(--xeno-border);
|
|
20
|
-
border-radius: var(--xeno-radius-sm);
|
|
21
|
-
color: var(--xeno-muted);
|
|
22
|
-
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
23
|
-
font-size: 12px;
|
|
24
|
-
line-height: 1.4;
|
|
25
|
-
letter-spacing: 0.01em;
|
|
26
|
-
text-align: left;
|
|
27
|
-
white-space: normal;
|
|
28
|
-
pointer-events: none;
|
|
29
|
-
opacity: 0;
|
|
30
|
-
visibility: hidden;
|
|
31
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.24);
|
|
32
|
-
transition:
|
|
33
|
-
opacity var(--xeno-dur) var(--xeno-ease),
|
|
34
|
-
transform var(--xeno-dur) var(--xeno-ease),
|
|
35
|
-
visibility 0s linear var(--xeno-dur);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/* Sides — centre with inset + auto margins (works even when the panel is wider than the trigger) so
|
|
39
|
-
* the entrance transform stays free to animate. A small gap separates the panel from the trigger. */
|
|
40
|
-
.xeno-tooltip-panel[data-side='top'] {
|
|
41
|
-
bottom: 100%;
|
|
42
|
-
left: 0;
|
|
43
|
-
right: 0;
|
|
44
|
-
margin-inline: auto;
|
|
45
|
-
margin-bottom: 8px;
|
|
46
|
-
transform: translateY(4px);
|
|
47
|
-
}
|
|
48
|
-
.xeno-tooltip-panel[data-side='bottom'] {
|
|
49
|
-
top: 100%;
|
|
50
|
-
left: 0;
|
|
51
|
-
right: 0;
|
|
52
|
-
margin-inline: auto;
|
|
53
|
-
margin-top: 8px;
|
|
54
|
-
transform: translateY(-4px);
|
|
55
|
-
}
|
|
56
|
-
.xeno-tooltip-panel[data-side='left'] {
|
|
57
|
-
right: 100%;
|
|
58
|
-
top: 0;
|
|
59
|
-
bottom: 0;
|
|
60
|
-
margin-block: auto;
|
|
61
|
-
margin-right: 8px;
|
|
62
|
-
transform: translateX(4px);
|
|
63
|
-
}
|
|
64
|
-
.xeno-tooltip-panel[data-side='right'] {
|
|
65
|
-
left: 100%;
|
|
66
|
-
top: 0;
|
|
67
|
-
bottom: 0;
|
|
68
|
-
margin-block: auto;
|
|
69
|
-
margin-left: 8px;
|
|
70
|
-
transform: translateX(-4px);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/* Revealed — settle to the resting position; keep visibility on until the fade completes on close. */
|
|
74
|
-
.xeno-tooltip-panel[data-state='open'] {
|
|
75
|
-
opacity: 1;
|
|
76
|
-
visibility: visible;
|
|
77
|
-
transform: translate(0, 0);
|
|
78
|
-
transition:
|
|
79
|
-
opacity var(--xeno-dur) var(--xeno-ease),
|
|
80
|
-
transform var(--xeno-dur) var(--xeno-ease),
|
|
81
|
-
visibility 0s linear 0s;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/* Arrow — a small rounded square rotated 45°, overlapping the panel edge so it reads as a pointer. */
|
|
85
|
-
.xeno-tooltip-arrow {
|
|
86
|
-
position: absolute;
|
|
87
|
-
width: 7px;
|
|
88
|
-
height: 7px;
|
|
89
|
-
background: var(--xeno-elevated);
|
|
90
|
-
border-radius: var(--xeno-radius-hair);
|
|
91
|
-
}
|
|
92
|
-
.xeno-tooltip-panel[data-side='top'] .xeno-tooltip-arrow {
|
|
93
|
-
left: 50%;
|
|
94
|
-
bottom: -3px;
|
|
95
|
-
transform: translateX(-50%) rotate(45deg);
|
|
96
|
-
}
|
|
97
|
-
.xeno-tooltip-panel[data-side='bottom'] .xeno-tooltip-arrow {
|
|
98
|
-
left: 50%;
|
|
99
|
-
top: -3px;
|
|
100
|
-
transform: translateX(-50%) rotate(45deg);
|
|
101
|
-
}
|
|
102
|
-
.xeno-tooltip-panel[data-side='left'] .xeno-tooltip-arrow {
|
|
103
|
-
top: 50%;
|
|
104
|
-
right: -3px;
|
|
105
|
-
transform: translateY(-50%) rotate(45deg);
|
|
106
|
-
}
|
|
107
|
-
.xeno-tooltip-panel[data-side='right'] .xeno-tooltip-arrow {
|
|
108
|
-
top: 50%;
|
|
109
|
-
left: -3px;
|
|
110
|
-
transform: translateY(-50%) rotate(45deg);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
@media (prefers-reduced-motion: reduce) {
|
|
114
|
-
.xeno-tooltip-panel {
|
|
115
|
-
transform: none;
|
|
116
|
-
transition:
|
|
117
|
-
opacity var(--xeno-dur) linear,
|
|
118
|
-
visibility 0s linear var(--xeno-dur);
|
|
119
|
-
}
|
|
120
|
-
.xeno-tooltip-panel[data-state='open'] {
|
|
121
|
-
transform: none;
|
|
122
|
-
transition:
|
|
123
|
-
opacity var(--xeno-dur) linear,
|
|
124
|
-
visibility 0s linear 0s;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Tooltip — a hover/focus hint. CSS-first reveal driven by `data-state` (JS-controlled), positioned on
|
|
3
|
+
* a `data-side` of the trigger. Monochrome shell: an elevated panel with a hairline border and muted
|
|
4
|
+
* 12px mono text; rounded squares only. Motion is transform/opacity, behind reduced-motion.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.xeno-tooltip {
|
|
8
|
+
position: relative;
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.xeno-tooltip-panel {
|
|
13
|
+
position: absolute;
|
|
14
|
+
z-index: 50;
|
|
15
|
+
width: max-content;
|
|
16
|
+
max-width: 240px;
|
|
17
|
+
padding: 6px 8px;
|
|
18
|
+
background: var(--xeno-elevated);
|
|
19
|
+
border: 1px solid var(--xeno-border);
|
|
20
|
+
border-radius: var(--xeno-radius-sm);
|
|
21
|
+
color: var(--xeno-muted);
|
|
22
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
23
|
+
font-size: 12px;
|
|
24
|
+
line-height: 1.4;
|
|
25
|
+
letter-spacing: 0.01em;
|
|
26
|
+
text-align: left;
|
|
27
|
+
white-space: normal;
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
opacity: 0;
|
|
30
|
+
visibility: hidden;
|
|
31
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.24);
|
|
32
|
+
transition:
|
|
33
|
+
opacity var(--xeno-dur) var(--xeno-ease),
|
|
34
|
+
transform var(--xeno-dur) var(--xeno-ease),
|
|
35
|
+
visibility 0s linear var(--xeno-dur);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Sides — centre with inset + auto margins (works even when the panel is wider than the trigger) so
|
|
39
|
+
* the entrance transform stays free to animate. A small gap separates the panel from the trigger. */
|
|
40
|
+
.xeno-tooltip-panel[data-side='top'] {
|
|
41
|
+
bottom: 100%;
|
|
42
|
+
left: 0;
|
|
43
|
+
right: 0;
|
|
44
|
+
margin-inline: auto;
|
|
45
|
+
margin-bottom: 8px;
|
|
46
|
+
transform: translateY(4px);
|
|
47
|
+
}
|
|
48
|
+
.xeno-tooltip-panel[data-side='bottom'] {
|
|
49
|
+
top: 100%;
|
|
50
|
+
left: 0;
|
|
51
|
+
right: 0;
|
|
52
|
+
margin-inline: auto;
|
|
53
|
+
margin-top: 8px;
|
|
54
|
+
transform: translateY(-4px);
|
|
55
|
+
}
|
|
56
|
+
.xeno-tooltip-panel[data-side='left'] {
|
|
57
|
+
right: 100%;
|
|
58
|
+
top: 0;
|
|
59
|
+
bottom: 0;
|
|
60
|
+
margin-block: auto;
|
|
61
|
+
margin-right: 8px;
|
|
62
|
+
transform: translateX(4px);
|
|
63
|
+
}
|
|
64
|
+
.xeno-tooltip-panel[data-side='right'] {
|
|
65
|
+
left: 100%;
|
|
66
|
+
top: 0;
|
|
67
|
+
bottom: 0;
|
|
68
|
+
margin-block: auto;
|
|
69
|
+
margin-left: 8px;
|
|
70
|
+
transform: translateX(-4px);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Revealed — settle to the resting position; keep visibility on until the fade completes on close. */
|
|
74
|
+
.xeno-tooltip-panel[data-state='open'] {
|
|
75
|
+
opacity: 1;
|
|
76
|
+
visibility: visible;
|
|
77
|
+
transform: translate(0, 0);
|
|
78
|
+
transition:
|
|
79
|
+
opacity var(--xeno-dur) var(--xeno-ease),
|
|
80
|
+
transform var(--xeno-dur) var(--xeno-ease),
|
|
81
|
+
visibility 0s linear 0s;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Arrow — a small rounded square rotated 45°, overlapping the panel edge so it reads as a pointer. */
|
|
85
|
+
.xeno-tooltip-arrow {
|
|
86
|
+
position: absolute;
|
|
87
|
+
width: 7px;
|
|
88
|
+
height: 7px;
|
|
89
|
+
background: var(--xeno-elevated);
|
|
90
|
+
border-radius: var(--xeno-radius-hair);
|
|
91
|
+
}
|
|
92
|
+
.xeno-tooltip-panel[data-side='top'] .xeno-tooltip-arrow {
|
|
93
|
+
left: 50%;
|
|
94
|
+
bottom: -3px;
|
|
95
|
+
transform: translateX(-50%) rotate(45deg);
|
|
96
|
+
}
|
|
97
|
+
.xeno-tooltip-panel[data-side='bottom'] .xeno-tooltip-arrow {
|
|
98
|
+
left: 50%;
|
|
99
|
+
top: -3px;
|
|
100
|
+
transform: translateX(-50%) rotate(45deg);
|
|
101
|
+
}
|
|
102
|
+
.xeno-tooltip-panel[data-side='left'] .xeno-tooltip-arrow {
|
|
103
|
+
top: 50%;
|
|
104
|
+
right: -3px;
|
|
105
|
+
transform: translateY(-50%) rotate(45deg);
|
|
106
|
+
}
|
|
107
|
+
.xeno-tooltip-panel[data-side='right'] .xeno-tooltip-arrow {
|
|
108
|
+
top: 50%;
|
|
109
|
+
left: -3px;
|
|
110
|
+
transform: translateY(-50%) rotate(45deg);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@media (prefers-reduced-motion: reduce) {
|
|
114
|
+
.xeno-tooltip-panel {
|
|
115
|
+
transform: none;
|
|
116
|
+
transition:
|
|
117
|
+
opacity var(--xeno-dur) linear,
|
|
118
|
+
visibility 0s linear var(--xeno-dur);
|
|
119
|
+
}
|
|
120
|
+
.xeno-tooltip-panel[data-state='open'] {
|
|
121
|
+
transform: none;
|
|
122
|
+
transition:
|
|
123
|
+
opacity var(--xeno-dur) linear,
|
|
124
|
+
visibility 0s linear 0s;
|
|
125
|
+
}
|
|
126
|
+
}
|