@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/containers/tile.css
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Tile — a square icon tile. Rounded square (radius-md), a surface ground, a hairline border, and a
|
|
3
|
-
* centred glyph in muted ink. The box edge arrives as an inline `--xeno-tile-size` var. No literal
|
|
4
|
-
* colours; monochrome shell.
|
|
5
|
-
*/
|
|
6
|
-
.xeno-tile {
|
|
7
|
-
display: inline-flex;
|
|
8
|
-
align-items: center;
|
|
9
|
-
justify-content: center;
|
|
10
|
-
flex: 0 0 auto;
|
|
11
|
-
width: var(--xeno-tile-size, 32px);
|
|
12
|
-
height: var(--xeno-tile-size, 32px);
|
|
13
|
-
color: var(--xeno-muted);
|
|
14
|
-
background: var(--xeno-surface);
|
|
15
|
-
border: 1px solid var(--xeno-border);
|
|
16
|
-
border-radius: var(--xeno-radius-md);
|
|
17
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Tile — a square icon tile. Rounded square (radius-md), a surface ground, a hairline border, and a
|
|
3
|
+
* centred glyph in muted ink. The box edge arrives as an inline `--xeno-tile-size` var. No literal
|
|
4
|
+
* colours; monochrome shell.
|
|
5
|
+
*/
|
|
6
|
+
.xeno-tile {
|
|
7
|
+
display: inline-flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
flex: 0 0 auto;
|
|
11
|
+
width: var(--xeno-tile-size, 32px);
|
|
12
|
+
height: var(--xeno-tile-size, 32px);
|
|
13
|
+
color: var(--xeno-muted);
|
|
14
|
+
background: var(--xeno-surface);
|
|
15
|
+
border: 1px solid var(--xeno-border);
|
|
16
|
+
border-radius: var(--xeno-radius-md);
|
|
17
|
+
}
|
package/src/content/callout.css
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* <Callout> — a left-ruled blockquote. Monochrome by default (muted italic ink, hairline rule); the
|
|
3
|
-
* `danger` tone is the sole exception, swapping the rule and the glyph to `--xeno-danger`. Tokens only.
|
|
4
|
-
*
|
|
5
|
-
* The rule is a pseudo-element rather than a `border-left` for one reason: a border cannot be scaled
|
|
6
|
-
* from its top edge, and the entrance below is the rule DRAWING DOWN. Everything else about it is
|
|
7
|
-
* identical — 2px wide, flush left, the same total 14px inset to the text.
|
|
8
|
-
*/
|
|
9
|
-
.xeno-callout {
|
|
10
|
-
position: relative;
|
|
11
|
-
margin: 0;
|
|
12
|
-
padding-left: 14px;
|
|
13
|
-
color: var(--xeno-muted);
|
|
14
|
-
font-style: italic;
|
|
15
|
-
}
|
|
16
|
-
.xeno-callout::before {
|
|
17
|
-
content: '';
|
|
18
|
-
position: absolute;
|
|
19
|
-
left: 0;
|
|
20
|
-
top: 0;
|
|
21
|
-
bottom: 0;
|
|
22
|
-
width: 2px;
|
|
23
|
-
background: var(--xeno-border);
|
|
24
|
-
/* Square: at 2px wide a 1.5px radius is 75% of the width, which is a capsule, not a corner. */
|
|
25
|
-
border-radius: 0;
|
|
26
|
-
transform-origin: top center;
|
|
27
|
-
}
|
|
28
|
-
.xeno-callout[data-tone='danger']::before {
|
|
29
|
-
background: var(--xeno-danger);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* The flex row exists ONLY when there is a glyph. Without one the children stay direct descendants of
|
|
33
|
-
the blockquote, so a run of `<p>`s lays out as prose rather than as a row of flex items. */
|
|
34
|
-
.xeno-callout[data-icon] {
|
|
35
|
-
display: flex;
|
|
36
|
-
align-items: flex-start;
|
|
37
|
-
gap: 9px;
|
|
38
|
-
}
|
|
39
|
-
.xeno-callout-icon {
|
|
40
|
-
display: inline-flex;
|
|
41
|
-
flex: none;
|
|
42
|
-
margin-top: 1px; /* optical: the glyph's box sits a hair above the italic x-height */
|
|
43
|
-
color: var(--xeno-muted);
|
|
44
|
-
}
|
|
45
|
-
.xeno-callout[data-tone='danger'] .xeno-callout-icon {
|
|
46
|
-
color: var(--xeno-danger);
|
|
47
|
-
}
|
|
48
|
-
.xeno-callout-body {
|
|
49
|
-
min-width: 0;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/* ── Entrance ─────────────────────────────────────────────────────────────────────────
|
|
53
|
-
* The rule leads and the text follows it in. Two tracks rather than one fade, because the rule IS the
|
|
54
|
-
* callout's form — a block that simply fades up could be any block, while a rule drawing down from the
|
|
55
|
-
* top is unmistakably this one. The rule takes longer than the text on purpose: it is still arriving
|
|
56
|
-
* as the words settle, so the two read as one gesture instead of two. */
|
|
57
|
-
.xeno-callout[data-enter] {
|
|
58
|
-
animation: xeno-callout-in var(--xeno-dur-entrance, 240ms) var(--xeno-ease) both;
|
|
59
|
-
}
|
|
60
|
-
.xeno-callout[data-enter]::before {
|
|
61
|
-
animation: xeno-callout-rule 320ms var(--xeno-ease-expo, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
62
|
-
}
|
|
63
|
-
@keyframes xeno-callout-in {
|
|
64
|
-
from { opacity: 0; translate: 5px 0; }
|
|
65
|
-
to { opacity: 1; translate: 0 0; }
|
|
66
|
-
}
|
|
67
|
-
@keyframes xeno-callout-rule {
|
|
68
|
-
from { scale: 1 0; }
|
|
69
|
-
to { scale: 1 1; }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
@media (prefers-reduced-motion: reduce) {
|
|
73
|
-
.xeno-callout[data-enter],
|
|
74
|
-
.xeno-callout[data-enter]::before {
|
|
75
|
-
animation: none;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* <Callout> — a left-ruled blockquote. Monochrome by default (muted italic ink, hairline rule); the
|
|
3
|
+
* `danger` tone is the sole exception, swapping the rule and the glyph to `--xeno-danger`. Tokens only.
|
|
4
|
+
*
|
|
5
|
+
* The rule is a pseudo-element rather than a `border-left` for one reason: a border cannot be scaled
|
|
6
|
+
* from its top edge, and the entrance below is the rule DRAWING DOWN. Everything else about it is
|
|
7
|
+
* identical — 2px wide, flush left, the same total 14px inset to the text.
|
|
8
|
+
*/
|
|
9
|
+
.xeno-callout {
|
|
10
|
+
position: relative;
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding-left: 14px;
|
|
13
|
+
color: var(--xeno-muted);
|
|
14
|
+
font-style: italic;
|
|
15
|
+
}
|
|
16
|
+
.xeno-callout::before {
|
|
17
|
+
content: '';
|
|
18
|
+
position: absolute;
|
|
19
|
+
left: 0;
|
|
20
|
+
top: 0;
|
|
21
|
+
bottom: 0;
|
|
22
|
+
width: 2px;
|
|
23
|
+
background: var(--xeno-border);
|
|
24
|
+
/* Square: at 2px wide a 1.5px radius is 75% of the width, which is a capsule, not a corner. */
|
|
25
|
+
border-radius: 0;
|
|
26
|
+
transform-origin: top center;
|
|
27
|
+
}
|
|
28
|
+
.xeno-callout[data-tone='danger']::before {
|
|
29
|
+
background: var(--xeno-danger);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* The flex row exists ONLY when there is a glyph. Without one the children stay direct descendants of
|
|
33
|
+
the blockquote, so a run of `<p>`s lays out as prose rather than as a row of flex items. */
|
|
34
|
+
.xeno-callout[data-icon] {
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: flex-start;
|
|
37
|
+
gap: 9px;
|
|
38
|
+
}
|
|
39
|
+
.xeno-callout-icon {
|
|
40
|
+
display: inline-flex;
|
|
41
|
+
flex: none;
|
|
42
|
+
margin-top: 1px; /* optical: the glyph's box sits a hair above the italic x-height */
|
|
43
|
+
color: var(--xeno-muted);
|
|
44
|
+
}
|
|
45
|
+
.xeno-callout[data-tone='danger'] .xeno-callout-icon {
|
|
46
|
+
color: var(--xeno-danger);
|
|
47
|
+
}
|
|
48
|
+
.xeno-callout-body {
|
|
49
|
+
min-width: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* ── Entrance ─────────────────────────────────────────────────────────────────────────
|
|
53
|
+
* The rule leads and the text follows it in. Two tracks rather than one fade, because the rule IS the
|
|
54
|
+
* callout's form — a block that simply fades up could be any block, while a rule drawing down from the
|
|
55
|
+
* top is unmistakably this one. The rule takes longer than the text on purpose: it is still arriving
|
|
56
|
+
* as the words settle, so the two read as one gesture instead of two. */
|
|
57
|
+
.xeno-callout[data-enter] {
|
|
58
|
+
animation: xeno-callout-in var(--xeno-dur-entrance, 240ms) var(--xeno-ease) both;
|
|
59
|
+
}
|
|
60
|
+
.xeno-callout[data-enter]::before {
|
|
61
|
+
animation: xeno-callout-rule 320ms var(--xeno-ease-expo, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
62
|
+
}
|
|
63
|
+
@keyframes xeno-callout-in {
|
|
64
|
+
from { opacity: 0; translate: 5px 0; }
|
|
65
|
+
to { opacity: 1; translate: 0 0; }
|
|
66
|
+
}
|
|
67
|
+
@keyframes xeno-callout-rule {
|
|
68
|
+
from { scale: 1 0; }
|
|
69
|
+
to { scale: 1 1; }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@media (prefers-reduced-motion: reduce) {
|
|
73
|
+
.xeno-callout[data-enter],
|
|
74
|
+
.xeno-callout[data-enter]::before {
|
|
75
|
+
animation: none;
|
|
76
|
+
}
|
|
77
|
+
}
|
package/src/content/caret.css
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* <Caret> — a thin streaming caret. A hairline `--xeno-text` block, `radius-hair` corners, sized to the
|
|
3
|
-
* line via `1em`. It blinks only under `prefers-reduced-motion: no-preference`; otherwise it holds solid.
|
|
4
|
-
*/
|
|
5
|
-
.xeno-caret {
|
|
6
|
-
display: inline-block;
|
|
7
|
-
width: 2px;
|
|
8
|
-
height: 1em;
|
|
9
|
-
margin-left: 1px;
|
|
10
|
-
vertical-align: text-bottom;
|
|
11
|
-
background: var(--xeno-text);
|
|
12
|
-
border-radius: var(--xeno-radius-hair);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
16
|
-
.xeno-caret {
|
|
17
|
-
animation: xeno-caret-blink 1s steps(1, end) infinite;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@keyframes xeno-caret-blink {
|
|
22
|
-
0%,
|
|
23
|
-
50% {
|
|
24
|
-
opacity: 1;
|
|
25
|
-
}
|
|
26
|
-
50.01%,
|
|
27
|
-
100% {
|
|
28
|
-
opacity: 0;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* <Caret> — a thin streaming caret. A hairline `--xeno-text` block, `radius-hair` corners, sized to the
|
|
3
|
+
* line via `1em`. It blinks only under `prefers-reduced-motion: no-preference`; otherwise it holds solid.
|
|
4
|
+
*/
|
|
5
|
+
.xeno-caret {
|
|
6
|
+
display: inline-block;
|
|
7
|
+
width: 2px;
|
|
8
|
+
height: 1em;
|
|
9
|
+
margin-left: 1px;
|
|
10
|
+
vertical-align: text-bottom;
|
|
11
|
+
background: var(--xeno-text);
|
|
12
|
+
border-radius: var(--xeno-radius-hair);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
16
|
+
.xeno-caret {
|
|
17
|
+
animation: xeno-caret-blink 1s steps(1, end) infinite;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@keyframes xeno-caret-blink {
|
|
22
|
+
0%,
|
|
23
|
+
50% {
|
|
24
|
+
opacity: 1;
|
|
25
|
+
}
|
|
26
|
+
50.01%,
|
|
27
|
+
100% {
|
|
28
|
+
opacity: 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* CodeBlock — a monochrome code surface. Shell is greyscale (canvas card + hairline border); the code is
|
|
3
|
-
* the ink. State is CSS-first: `data-collapsed` on the root swaps body↔summary and rotates the chevron;
|
|
4
|
-
* `data-selection` on the copy button reflects the transient copied state. Tokens only — the sole hue is
|
|
5
|
-
* `--xeno-danger`, and only on an error output. Motion is transform/opacity, behind the reduce guard.
|
|
6
|
-
*/
|
|
7
|
-
.xeno-code {
|
|
8
|
-
display: flex;
|
|
9
|
-
flex-direction: column;
|
|
10
|
-
min-width: 0;
|
|
11
|
-
background: var(--xeno-canvas);
|
|
12
|
-
border: 1px solid var(--xeno-border);
|
|
13
|
-
border-radius: var(--xeno-radius-card);
|
|
14
|
-
color: var(--xeno-text);
|
|
15
|
-
overflow: hidden;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/* ── Header: language label + action row ─────────────────────────────────────────── */
|
|
19
|
-
.xeno-code-header {
|
|
20
|
-
display: flex;
|
|
21
|
-
align-items: center;
|
|
22
|
-
justify-content: space-between;
|
|
23
|
-
gap: 8px;
|
|
24
|
-
padding: 5px 6px 5px 12px;
|
|
25
|
-
background: var(--xeno-surface);
|
|
26
|
-
border-bottom: 1px solid var(--xeno-border);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.xeno-code-lang {
|
|
30
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
31
|
-
font-size: 11px;
|
|
32
|
-
font-weight: 600;
|
|
33
|
-
letter-spacing: 0.08em;
|
|
34
|
-
text-transform: uppercase;
|
|
35
|
-
color: var(--xeno-muted);
|
|
36
|
-
white-space: nowrap;
|
|
37
|
-
user-select: none;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.xeno-code-actions {
|
|
41
|
-
display: inline-flex;
|
|
42
|
-
align-items: center;
|
|
43
|
-
gap: 2px;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/* Copy button reflects the ~1.5s copied confirmation (icon swaps to Check; ink lifts to full text). */
|
|
47
|
-
.xeno-code-copy.is-copied {
|
|
48
|
-
color: var(--xeno-text);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/* Collapse chevron: points down when open, rotates to point right when collapsed. */
|
|
52
|
-
.xeno-code-collapse .xeno-element {
|
|
53
|
-
transition: transform var(--xeno-dur) var(--xeno-ease);
|
|
54
|
-
}
|
|
55
|
-
.xeno-code[data-collapsed='true'] .xeno-code-collapse .xeno-element {
|
|
56
|
-
transform: rotate(-90deg);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/* ── Body: <pre><code>, monospace, horizontally scrollable ───────────────────────── */
|
|
60
|
-
.xeno-code-body {
|
|
61
|
-
margin: 0;
|
|
62
|
-
padding: 12px 14px;
|
|
63
|
-
overflow-x: auto;
|
|
64
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
65
|
-
font-size: 13px;
|
|
66
|
-
line-height: 1.55;
|
|
67
|
-
color: var(--xeno-text);
|
|
68
|
-
tab-size: 2;
|
|
69
|
-
}
|
|
70
|
-
.xeno-code-body:focus-visible {
|
|
71
|
-
outline: none;
|
|
72
|
-
box-shadow: inset 0 0 0 2px var(--xeno-border);
|
|
73
|
-
}
|
|
74
|
-
.xeno-code-code {
|
|
75
|
-
display: block;
|
|
76
|
-
font: inherit;
|
|
77
|
-
color: inherit;
|
|
78
|
-
white-space: pre;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/* Collapsed ↔ expanded: swap body for the summary line. */
|
|
82
|
-
.xeno-code[data-collapsed='true'] .xeno-code-body {
|
|
83
|
-
display: none;
|
|
84
|
-
}
|
|
85
|
-
.xeno-code[data-collapsed='false'] .xeno-code-summary {
|
|
86
|
-
display: none;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.xeno-code-summary {
|
|
90
|
-
display: flex;
|
|
91
|
-
align-items: center;
|
|
92
|
-
width: 100%;
|
|
93
|
-
padding: 10px 14px;
|
|
94
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
95
|
-
font-size: 12px;
|
|
96
|
-
color: var(--xeno-muted);
|
|
97
|
-
text-align: left;
|
|
98
|
-
background: transparent;
|
|
99
|
-
border: none;
|
|
100
|
-
cursor: pointer;
|
|
101
|
-
transition:
|
|
102
|
-
color var(--xeno-dur) ease,
|
|
103
|
-
background var(--xeno-dur) ease;
|
|
104
|
-
}
|
|
105
|
-
.xeno-code-summary:hover {
|
|
106
|
-
color: var(--xeno-text);
|
|
107
|
-
background: var(--xeno-hover);
|
|
108
|
-
}
|
|
109
|
-
.xeno-code-summary:focus-visible {
|
|
110
|
-
outline: none;
|
|
111
|
-
box-shadow: inset 0 0 0 2px var(--xeno-border);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/* ── Output panel: Running… / result / error ─────────────────────────────────────── */
|
|
115
|
-
.xeno-code-output {
|
|
116
|
-
padding: 10px 14px;
|
|
117
|
-
background: var(--xeno-elevated);
|
|
118
|
-
border-top: 1px solid var(--xeno-border);
|
|
119
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
120
|
-
font-size: 12.5px;
|
|
121
|
-
line-height: 1.5;
|
|
122
|
-
}
|
|
123
|
-
.xeno-code-output-running {
|
|
124
|
-
color: var(--xeno-muted);
|
|
125
|
-
}
|
|
126
|
-
.xeno-code-output-text {
|
|
127
|
-
margin: 0;
|
|
128
|
-
overflow-x: auto;
|
|
129
|
-
white-space: pre-wrap;
|
|
130
|
-
color: var(--xeno-text);
|
|
131
|
-
}
|
|
132
|
-
.xeno-code-output[data-status='error'] {
|
|
133
|
-
border-top-color: var(--xeno-danger);
|
|
134
|
-
}
|
|
135
|
-
.xeno-code-output[data-status='error'] .xeno-code-output-text {
|
|
136
|
-
color: var(--xeno-danger);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
140
|
-
.xeno-code-output[data-status='running'] .xeno-code-output-running {
|
|
141
|
-
animation: xeno-code-pulse 1.2s var(--xeno-ease) infinite;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
@keyframes xeno-code-pulse {
|
|
145
|
-
0%,
|
|
146
|
-
100% {
|
|
147
|
-
opacity: 0.5;
|
|
148
|
-
}
|
|
149
|
-
50% {
|
|
150
|
-
opacity: 1;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
@media (prefers-reduced-motion: reduce) {
|
|
155
|
-
.xeno-code-collapse .xeno-element,
|
|
156
|
-
.xeno-code-summary {
|
|
157
|
-
transition: none;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* CodeBlock — a monochrome code surface. Shell is greyscale (canvas card + hairline border); the code is
|
|
3
|
+
* the ink. State is CSS-first: `data-collapsed` on the root swaps body↔summary and rotates the chevron;
|
|
4
|
+
* `data-selection` on the copy button reflects the transient copied state. Tokens only — the sole hue is
|
|
5
|
+
* `--xeno-danger`, and only on an error output. Motion is transform/opacity, behind the reduce guard.
|
|
6
|
+
*/
|
|
7
|
+
.xeno-code {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
min-width: 0;
|
|
11
|
+
background: var(--xeno-canvas);
|
|
12
|
+
border: 1px solid var(--xeno-border);
|
|
13
|
+
border-radius: var(--xeno-radius-card);
|
|
14
|
+
color: var(--xeno-text);
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* ── Header: language label + action row ─────────────────────────────────────────── */
|
|
19
|
+
.xeno-code-header {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
gap: 8px;
|
|
24
|
+
padding: 5px 6px 5px 12px;
|
|
25
|
+
background: var(--xeno-surface);
|
|
26
|
+
border-bottom: 1px solid var(--xeno-border);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.xeno-code-lang {
|
|
30
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
31
|
+
font-size: 11px;
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
letter-spacing: 0.08em;
|
|
34
|
+
text-transform: uppercase;
|
|
35
|
+
color: var(--xeno-muted);
|
|
36
|
+
white-space: nowrap;
|
|
37
|
+
user-select: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.xeno-code-actions {
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 2px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Copy button reflects the ~1.5s copied confirmation (icon swaps to Check; ink lifts to full text). */
|
|
47
|
+
.xeno-code-copy.is-copied {
|
|
48
|
+
color: var(--xeno-text);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Collapse chevron: points down when open, rotates to point right when collapsed. */
|
|
52
|
+
.xeno-code-collapse .xeno-element {
|
|
53
|
+
transition: transform var(--xeno-dur) var(--xeno-ease);
|
|
54
|
+
}
|
|
55
|
+
.xeno-code[data-collapsed='true'] .xeno-code-collapse .xeno-element {
|
|
56
|
+
transform: rotate(-90deg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ── Body: <pre><code>, monospace, horizontally scrollable ───────────────────────── */
|
|
60
|
+
.xeno-code-body {
|
|
61
|
+
margin: 0;
|
|
62
|
+
padding: 12px 14px;
|
|
63
|
+
overflow-x: auto;
|
|
64
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
65
|
+
font-size: 13px;
|
|
66
|
+
line-height: 1.55;
|
|
67
|
+
color: var(--xeno-text);
|
|
68
|
+
tab-size: 2;
|
|
69
|
+
}
|
|
70
|
+
.xeno-code-body:focus-visible {
|
|
71
|
+
outline: none;
|
|
72
|
+
box-shadow: inset 0 0 0 2px var(--xeno-border);
|
|
73
|
+
}
|
|
74
|
+
.xeno-code-code {
|
|
75
|
+
display: block;
|
|
76
|
+
font: inherit;
|
|
77
|
+
color: inherit;
|
|
78
|
+
white-space: pre;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Collapsed ↔ expanded: swap body for the summary line. */
|
|
82
|
+
.xeno-code[data-collapsed='true'] .xeno-code-body {
|
|
83
|
+
display: none;
|
|
84
|
+
}
|
|
85
|
+
.xeno-code[data-collapsed='false'] .xeno-code-summary {
|
|
86
|
+
display: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.xeno-code-summary {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
width: 100%;
|
|
93
|
+
padding: 10px 14px;
|
|
94
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
95
|
+
font-size: 12px;
|
|
96
|
+
color: var(--xeno-muted);
|
|
97
|
+
text-align: left;
|
|
98
|
+
background: transparent;
|
|
99
|
+
border: none;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
transition:
|
|
102
|
+
color var(--xeno-dur) ease,
|
|
103
|
+
background var(--xeno-dur) ease;
|
|
104
|
+
}
|
|
105
|
+
.xeno-code-summary:hover {
|
|
106
|
+
color: var(--xeno-text);
|
|
107
|
+
background: var(--xeno-hover);
|
|
108
|
+
}
|
|
109
|
+
.xeno-code-summary:focus-visible {
|
|
110
|
+
outline: none;
|
|
111
|
+
box-shadow: inset 0 0 0 2px var(--xeno-border);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* ── Output panel: Running… / result / error ─────────────────────────────────────── */
|
|
115
|
+
.xeno-code-output {
|
|
116
|
+
padding: 10px 14px;
|
|
117
|
+
background: var(--xeno-elevated);
|
|
118
|
+
border-top: 1px solid var(--xeno-border);
|
|
119
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
120
|
+
font-size: 12.5px;
|
|
121
|
+
line-height: 1.5;
|
|
122
|
+
}
|
|
123
|
+
.xeno-code-output-running {
|
|
124
|
+
color: var(--xeno-muted);
|
|
125
|
+
}
|
|
126
|
+
.xeno-code-output-text {
|
|
127
|
+
margin: 0;
|
|
128
|
+
overflow-x: auto;
|
|
129
|
+
white-space: pre-wrap;
|
|
130
|
+
color: var(--xeno-text);
|
|
131
|
+
}
|
|
132
|
+
.xeno-code-output[data-status='error'] {
|
|
133
|
+
border-top-color: var(--xeno-danger);
|
|
134
|
+
}
|
|
135
|
+
.xeno-code-output[data-status='error'] .xeno-code-output-text {
|
|
136
|
+
color: var(--xeno-danger);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
140
|
+
.xeno-code-output[data-status='running'] .xeno-code-output-running {
|
|
141
|
+
animation: xeno-code-pulse 1.2s var(--xeno-ease) infinite;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
@keyframes xeno-code-pulse {
|
|
145
|
+
0%,
|
|
146
|
+
100% {
|
|
147
|
+
opacity: 0.5;
|
|
148
|
+
}
|
|
149
|
+
50% {
|
|
150
|
+
opacity: 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@media (prefers-reduced-motion: reduce) {
|
|
155
|
+
.xeno-code-collapse .xeno-element,
|
|
156
|
+
.xeno-code-summary {
|
|
157
|
+
transition: none;
|
|
158
|
+
}
|
|
159
|
+
}
|