@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.
Files changed (49) hide show
  1. package/LICENSE +18 -18
  2. package/README.md +41 -41
  3. package/package.json +58 -58
  4. package/src/chrome-separated.css +132 -132
  5. package/src/chrome-unified.css +72 -72
  6. package/src/containers/Badges.css +116 -116
  7. package/src/containers/avatar.css +70 -70
  8. package/src/containers/card.css +75 -75
  9. package/src/containers/chip.css +103 -103
  10. package/src/containers/list-row.css +132 -132
  11. package/src/containers/message-bubble.css +112 -112
  12. package/src/containers/panel.css +120 -120
  13. package/src/containers/table.css +102 -102
  14. package/src/containers/tile.css +17 -17
  15. package/src/content/callout.css +77 -77
  16. package/src/content/caret.css +30 -30
  17. package/src/content/code-block.css +159 -159
  18. package/src/content/collapsible.css +80 -80
  19. package/src/content/inline-code.css +14 -14
  20. package/src/content/model-picker.css +219 -219
  21. package/src/content/source-card.css +99 -99
  22. package/src/content/sources-disclosure.css +118 -118
  23. package/src/controls.css +453 -453
  24. package/src/fonts.css +34 -34
  25. package/src/forms/Checkbox.css +114 -114
  26. package/src/forms/RadioGroup.css +115 -115
  27. package/src/goo.css +97 -97
  28. package/src/icon-motion.css +1909 -1909
  29. package/src/layout/ResizablePanel.css +79 -79
  30. package/src/nav/sidebar.css +296 -296
  31. package/src/overlays/date-time-picker.css +238 -238
  32. package/src/overlays/menu.css +195 -195
  33. package/src/overlays/modal.css +167 -167
  34. package/src/overlays/picker-field.css +81 -81
  35. package/src/overlays/pill-filter.css +129 -129
  36. package/src/overlays/reveal.css +56 -56
  37. package/src/overlays/segmented-control.css +185 -185
  38. package/src/overlays/tabs.css +143 -143
  39. package/src/overlays/tooltip.css +126 -126
  40. package/src/scrollbar.css +184 -184
  41. package/src/size.css +179 -179
  42. package/src/status/progress-bar.css +88 -88
  43. package/src/status/spinner.css +33 -33
  44. package/src/status/statusindicator.css +65 -65
  45. package/src/status/steptimeline.css +137 -137
  46. package/src/status/thinkingcube.css +75 -75
  47. package/src/xeno-element.css +60 -60
  48. package/src/xeno-elements.css +71 -71
  49. package/src/xeno-theme.css +99 -99
@@ -1,195 +1,195 @@
1
- /*
2
- * Popover / Menu / MenuItem — a hand-rolled anchored overlay (no portal lib). CSS-first: the panel is an
3
- * absolutely-positioned card anchored to a `position:relative` wrapper; the anchored edge flips on the
4
- * `data-align` attribute. Depth is a hairline border + one soft (uncoloured) shadow. Monochrome shell,
5
- * rounded squares only, tokens from `xeno-theme.css`. Motion is transform/opacity, behind reduced-motion.
6
- */
7
-
8
- /* ── Popover (anchor + panel) ─────────────────────────────────────────────────────── */
9
- .xeno-popover {
10
- position: relative;
11
- display: inline-flex;
12
- }
13
-
14
- .xeno-popover-panel {
15
- position: absolute;
16
- top: calc(100% + 6px);
17
- left: 0;
18
- z-index: 50;
19
- min-width: 180px;
20
- padding: 6px;
21
- background: var(--xeno-elevated);
22
- border: 1px solid var(--xeno-border);
23
- border-radius: var(--xeno-radius-md);
24
- box-shadow:
25
- 0 12px 32px -12px rgba(0, 0, 0, 0.55),
26
- 0 2px 8px rgba(0, 0, 0, 0.24);
27
- color: var(--xeno-text);
28
- outline: none;
29
- }
30
- .xeno-popover-panel[data-align='end'] {
31
- left: auto;
32
- right: 0;
33
- }
34
-
35
- /* ── Menu (a Popover panel that is a role=menu list) ──────────────────────────────── */
36
- /* `position: relative` + `isolation` come from `xeno-goo-host`, which the component also puts on this
37
- element; the 4px padding is what `--xeno-goo-inset` defaults to, so the pill lines up with the rows. */
38
- .xeno-menu {
39
- min-width: 200px;
40
- padding: 4px;
41
- }
42
-
43
- /* The travelling hover pill is a PRIMITIVE, not a menu feature — see `goo.css` and `useGooPill()`. A
44
- * menu was simply the first list that needed it; a command palette or a product's own hand-rolled
45
- * dropdown wants the same behaviour, so it does not live here. `<Menu>` carries `xeno-goo-host` and
46
- * renders the pill as its first child, and the rows below give up painting their own hover background
47
- * because the pill IS the filled surface. */
48
-
49
- /* ── MenuItem (row: lead · label · shortcut · chevron) ────────────────────────────── */
50
- .xeno-menu-item {
51
- display: flex;
52
- align-items: center;
53
- gap: 10px;
54
- width: 100%;
55
- /* 32, not the 34 this was written with. The system's own control scale is xs 24 / sm 28 / md 32 /
56
- lg 36 and there is no 34 in it — the number was picked by eye and never checked against the table
57
- it belongs to. Found by measuring a product's menu rows against this component: the product was on
58
- the scale and the library was not. */
59
- height: 32px;
60
- margin: 0;
61
- padding: 0 8px;
62
- background: transparent;
63
- border: none;
64
- /* `md`, not `sm`. The locked radius scale is explicit that overlay chrome is "6px throughout", and a
65
- menu row is overlay chrome; 5px is the badge/checkbox step. */
66
- border-radius: var(--xeno-radius-md);
67
- color: var(--xeno-text);
68
- font-family: inherit;
69
- font-size: 14px;
70
- line-height: 1;
71
- text-align: left;
72
- cursor: pointer;
73
- user-select: none;
74
- transition:
75
- background var(--xeno-dur) ease,
76
- color var(--xeno-dur) ease;
77
- }
78
- /* The row paints no background of its own: the travelling pill is the filled surface, and two of them
79
- would read as two highlights. */
80
- .xeno-menu-item:hover:not(:disabled),
81
- .xeno-menu-item:focus-visible {
82
- outline: none;
83
- }
84
- .xeno-menu-item:focus-visible {
85
- box-shadow: inset 0 0 0 1px var(--xeno-border);
86
- }
87
- .xeno-menu-item[data-availability='disabled'] {
88
- opacity: 0.4;
89
- cursor: not-allowed;
90
- }
91
- .xeno-menu-item[data-variant='danger'] {
92
- color: var(--xeno-danger);
93
- }
94
- .xeno-menu-item[data-variant='danger']:hover:not(:disabled),
95
- .xeno-menu-item[data-variant='danger']:focus-visible {
96
- color: var(--xeno-danger-hover);
97
- background: var(--xeno-hover);
98
- }
99
-
100
- /* Leading slot — reserved icon/check column (a rounded box, never a circle). */
101
- .xeno-menu-item-lead {
102
- flex: none;
103
- display: inline-flex;
104
- align-items: center;
105
- justify-content: center;
106
- width: 16px;
107
- height: 16px;
108
- color: var(--xeno-muted);
109
- }
110
- .xeno-menu-item[data-selection='on'] .xeno-menu-item-lead {
111
- color: var(--xeno-text);
112
- }
113
- .xeno-menu-item[data-variant='danger'] .xeno-menu-item-lead {
114
- color: inherit;
115
- }
116
-
117
- /* Label — grows and truncates. */
118
- .xeno-menu-item-label {
119
- flex: 1 1 auto;
120
- min-width: 0;
121
- overflow: hidden;
122
- white-space: nowrap;
123
- text-overflow: ellipsis;
124
- }
125
-
126
- /* Shortcut — trailing, muted mono. */
127
- .xeno-menu-item-shortcut {
128
- flex: none;
129
- margin-left: 12px;
130
- font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
131
- font-size: 12px;
132
- letter-spacing: 0.02em;
133
- color: var(--xeno-muted);
134
- }
135
-
136
- /* Value — trailing, muted, but in the UI font, and that is the whole point of it being a separate
137
- slot. A shortcut is a KEY: mono, tracked out, because it stands for something the reader will
138
- press. A value is a WORD the reader chose ("All", "Last activity") and setting a word in mono
139
- makes it read as a key too. Same slot, same muted colour, different typeface — the distinction
140
- the shortcut rule alone could not draw. Sits before the chevron, so a submenu row reads
141
- label → current value → "there is more this way". */
142
- .xeno-menu-item-value {
143
- flex: none;
144
- /* 2, not the shortcut's 12 — the row's own 10px `gap` is already between them, and a value is a
145
- word rather than a key glyph, so it needs the label's width more than it needs the air. At 12 a
146
- "Last activity / All ›" row ran out of room and ellipsed its own label. */
147
- margin-left: 2px;
148
- color: var(--xeno-muted);
149
- }
150
-
151
- /* Submenu chevron — trailing, muted. */
152
- .xeno-menu-item-chevron {
153
- flex: none;
154
- display: inline-flex;
155
- align-items: center;
156
- margin-left: 2px;
157
- color: var(--xeno-muted);
158
- }
159
-
160
- /* A DISCLOSURE row turns the same chevron a quarter — the region it opens is below, not beside, and
161
- the arrow should point at it. It turns rather than swapping to a chevron-down so the reader can
162
- see WHICH row moved; the rotation is the state change, not a redraw. */
163
- .xeno-menu-item-chevron[data-state] {
164
- transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
165
- }
166
- .xeno-menu-item-chevron[data-state='open'] {
167
- transform: rotate(90deg);
168
- }
169
- @media (prefers-reduced-motion: reduce) {
170
- .xeno-menu-item-chevron[data-state] {
171
- transition: none;
172
- }
173
- }
174
-
175
- /* ── Motion (transform/opacity only; opt-in) ─────────────────────────────────────── */
176
- @media (prefers-reduced-motion: no-preference) {
177
- .xeno-popover-panel {
178
- animation: xeno-popover-in var(--xeno-dur) var(--xeno-ease);
179
- transform-origin: top left;
180
- }
181
- .xeno-popover-panel[data-align='end'] {
182
- transform-origin: top right;
183
- }
184
- }
185
-
186
- @keyframes xeno-popover-in {
187
- from {
188
- opacity: 0;
189
- transform: translateY(-4px) scale(0.98);
190
- }
191
- to {
192
- opacity: 1;
193
- transform: none;
194
- }
195
- }
1
+ /*
2
+ * Popover / Menu / MenuItem — a hand-rolled anchored overlay (no portal lib). CSS-first: the panel is an
3
+ * absolutely-positioned card anchored to a `position:relative` wrapper; the anchored edge flips on the
4
+ * `data-align` attribute. Depth is a hairline border + one soft (uncoloured) shadow. Monochrome shell,
5
+ * rounded squares only, tokens from `xeno-theme.css`. Motion is transform/opacity, behind reduced-motion.
6
+ */
7
+
8
+ /* ── Popover (anchor + panel) ─────────────────────────────────────────────────────── */
9
+ .xeno-popover {
10
+ position: relative;
11
+ display: inline-flex;
12
+ }
13
+
14
+ .xeno-popover-panel {
15
+ position: absolute;
16
+ top: calc(100% + 6px);
17
+ left: 0;
18
+ z-index: 50;
19
+ min-width: 180px;
20
+ padding: 6px;
21
+ background: var(--xeno-elevated);
22
+ border: 1px solid var(--xeno-border);
23
+ border-radius: var(--xeno-radius-md);
24
+ box-shadow:
25
+ 0 12px 32px -12px rgba(0, 0, 0, 0.55),
26
+ 0 2px 8px rgba(0, 0, 0, 0.24);
27
+ color: var(--xeno-text);
28
+ outline: none;
29
+ }
30
+ .xeno-popover-panel[data-align='end'] {
31
+ left: auto;
32
+ right: 0;
33
+ }
34
+
35
+ /* ── Menu (a Popover panel that is a role=menu list) ──────────────────────────────── */
36
+ /* `position: relative` + `isolation` come from `xeno-goo-host`, which the component also puts on this
37
+ element; the 4px padding is what `--xeno-goo-inset` defaults to, so the pill lines up with the rows. */
38
+ .xeno-menu {
39
+ min-width: 200px;
40
+ padding: 4px;
41
+ }
42
+
43
+ /* The travelling hover pill is a PRIMITIVE, not a menu feature — see `goo.css` and `useGooPill()`. A
44
+ * menu was simply the first list that needed it; a command palette or a product's own hand-rolled
45
+ * dropdown wants the same behaviour, so it does not live here. `<Menu>` carries `xeno-goo-host` and
46
+ * renders the pill as its first child, and the rows below give up painting their own hover background
47
+ * because the pill IS the filled surface. */
48
+
49
+ /* ── MenuItem (row: lead · label · shortcut · chevron) ────────────────────────────── */
50
+ .xeno-menu-item {
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 10px;
54
+ width: 100%;
55
+ /* 32, not the 34 this was written with. The system's own control scale is xs 24 / sm 28 / md 32 /
56
+ lg 36 and there is no 34 in it — the number was picked by eye and never checked against the table
57
+ it belongs to. Found by measuring a product's menu rows against this component: the product was on
58
+ the scale and the library was not. */
59
+ height: 32px;
60
+ margin: 0;
61
+ padding: 0 8px;
62
+ background: transparent;
63
+ border: none;
64
+ /* `md`, not `sm`. The locked radius scale is explicit that overlay chrome is "6px throughout", and a
65
+ menu row is overlay chrome; 5px is the badge/checkbox step. */
66
+ border-radius: var(--xeno-radius-md);
67
+ color: var(--xeno-text);
68
+ font-family: inherit;
69
+ font-size: 14px;
70
+ line-height: 1;
71
+ text-align: left;
72
+ cursor: pointer;
73
+ user-select: none;
74
+ transition:
75
+ background var(--xeno-dur) ease,
76
+ color var(--xeno-dur) ease;
77
+ }
78
+ /* The row paints no background of its own: the travelling pill is the filled surface, and two of them
79
+ would read as two highlights. */
80
+ .xeno-menu-item:hover:not(:disabled),
81
+ .xeno-menu-item:focus-visible {
82
+ outline: none;
83
+ }
84
+ .xeno-menu-item:focus-visible {
85
+ box-shadow: inset 0 0 0 1px var(--xeno-border);
86
+ }
87
+ .xeno-menu-item[data-availability='disabled'] {
88
+ opacity: 0.4;
89
+ cursor: not-allowed;
90
+ }
91
+ .xeno-menu-item[data-variant='danger'] {
92
+ color: var(--xeno-danger);
93
+ }
94
+ .xeno-menu-item[data-variant='danger']:hover:not(:disabled),
95
+ .xeno-menu-item[data-variant='danger']:focus-visible {
96
+ color: var(--xeno-danger-hover);
97
+ background: var(--xeno-hover);
98
+ }
99
+
100
+ /* Leading slot — reserved icon/check column (a rounded box, never a circle). */
101
+ .xeno-menu-item-lead {
102
+ flex: none;
103
+ display: inline-flex;
104
+ align-items: center;
105
+ justify-content: center;
106
+ width: 16px;
107
+ height: 16px;
108
+ color: var(--xeno-muted);
109
+ }
110
+ .xeno-menu-item[data-selection='on'] .xeno-menu-item-lead {
111
+ color: var(--xeno-text);
112
+ }
113
+ .xeno-menu-item[data-variant='danger'] .xeno-menu-item-lead {
114
+ color: inherit;
115
+ }
116
+
117
+ /* Label — grows and truncates. */
118
+ .xeno-menu-item-label {
119
+ flex: 1 1 auto;
120
+ min-width: 0;
121
+ overflow: hidden;
122
+ white-space: nowrap;
123
+ text-overflow: ellipsis;
124
+ }
125
+
126
+ /* Shortcut — trailing, muted mono. */
127
+ .xeno-menu-item-shortcut {
128
+ flex: none;
129
+ margin-left: 12px;
130
+ font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
131
+ font-size: 12px;
132
+ letter-spacing: 0.02em;
133
+ color: var(--xeno-muted);
134
+ }
135
+
136
+ /* Value — trailing, muted, but in the UI font, and that is the whole point of it being a separate
137
+ slot. A shortcut is a KEY: mono, tracked out, because it stands for something the reader will
138
+ press. A value is a WORD the reader chose ("All", "Last activity") and setting a word in mono
139
+ makes it read as a key too. Same slot, same muted colour, different typeface — the distinction
140
+ the shortcut rule alone could not draw. Sits before the chevron, so a submenu row reads
141
+ label → current value → "there is more this way". */
142
+ .xeno-menu-item-value {
143
+ flex: none;
144
+ /* 2, not the shortcut's 12 — the row's own 10px `gap` is already between them, and a value is a
145
+ word rather than a key glyph, so it needs the label's width more than it needs the air. At 12 a
146
+ "Last activity / All ›" row ran out of room and ellipsed its own label. */
147
+ margin-left: 2px;
148
+ color: var(--xeno-muted);
149
+ }
150
+
151
+ /* Submenu chevron — trailing, muted. */
152
+ .xeno-menu-item-chevron {
153
+ flex: none;
154
+ display: inline-flex;
155
+ align-items: center;
156
+ margin-left: 2px;
157
+ color: var(--xeno-muted);
158
+ }
159
+
160
+ /* A DISCLOSURE row turns the same chevron a quarter — the region it opens is below, not beside, and
161
+ the arrow should point at it. It turns rather than swapping to a chevron-down so the reader can
162
+ see WHICH row moved; the rotation is the state change, not a redraw. */
163
+ .xeno-menu-item-chevron[data-state] {
164
+ transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
165
+ }
166
+ .xeno-menu-item-chevron[data-state='open'] {
167
+ transform: rotate(90deg);
168
+ }
169
+ @media (prefers-reduced-motion: reduce) {
170
+ .xeno-menu-item-chevron[data-state] {
171
+ transition: none;
172
+ }
173
+ }
174
+
175
+ /* ── Motion (transform/opacity only; opt-in) ─────────────────────────────────────── */
176
+ @media (prefers-reduced-motion: no-preference) {
177
+ .xeno-popover-panel {
178
+ animation: xeno-popover-in var(--xeno-dur) var(--xeno-ease);
179
+ transform-origin: top left;
180
+ }
181
+ .xeno-popover-panel[data-align='end'] {
182
+ transform-origin: top right;
183
+ }
184
+ }
185
+
186
+ @keyframes xeno-popover-in {
187
+ from {
188
+ opacity: 0;
189
+ transform: translateY(-4px) scale(0.98);
190
+ }
191
+ to {
192
+ opacity: 1;
193
+ transform: none;
194
+ }
195
+ }