@livx.cc/bare-v3 0.1.0-alpha.73 → 0.1.0-alpha.74

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.0-alpha.73",
2
+ "version": "0.1.0-alpha.74",
3
3
  "cssSha256": "22fd9b0597887cc93f1c1429bace791fee5efcc4268bf9c24c68cc263cfdd88b",
4
4
  "classes": [
5
5
  "b3-accordion",
@@ -450,6 +450,25 @@
450
450
  ],
451
451
  "guidance": "Combine b3-mobile-app b3-app-frame with direct header, main, and exactly one bottom region: nav OR a footer containing nav. Never put sibling nav and footer elements in the frame; both occupy its third grid row. Main scrolls; grid reserves the actual navigation height, including large labels. The frame owns top and side device insets. With bottom navigation, its surface paints to the bottom edge and owns the home-indicator padding; do not add that inset again to the frame or host. Without bottom navigation, the frame retains its bottom inset. Set --b3-frame-height for a bounded embedded preview; otherwise the frame uses 100dvh. Do not add a fixed-nav padding estimate or change its navigation to position:fixed. For transient messages, add b3-toast-region as a direct sibling of main and nav/footer. It overlays the content row and scrolls when messages exceed the available height. Keep custom footer-anchored feedback only when its interaction requires it; do not guess a bar-height offset. Restore per-route scroll with main.scrollTop, not window.scrollY. Keep the DOM order meaningful and use intrinsic grids inside main for wider screens. The frame fills available inline space up to its app-width cap. Bottom navigation wraps whole destinations when enlarged labels cannot fit on one row; use short destination names and let the frame measure navigation height. Existing b3-mobile-app without this atom retains its original fixed-navigation behavior. The hosting platform owns any external chrome; do not reproduce a host footer or fake OS bars inside the app.",
452
452
  "example": "<div class=\"b3-mobile-app b3-app-frame\" data-b3-platform=\"ios\"><header class=\"b3-app-bar\"><strong>Today</strong><button class=\"b3-button\">New plan</button></header><main class=\"b3-shell b3-stack\" tabindex=\"-1\" aria-label=\"Plans\"><h1 class=\"b3-title\">Make a little progress</h1><div class=\"b3-grid\"><article class=\"b3-surface\">Your first plan</article></div></main><nav class=\"b3-bottom-nav\" aria-label=\"Main\"><a class=\"b3-bottom-link\" href=\"#today\" aria-current=\"page\">Today</a><a class=\"b3-bottom-link\" href=\"#saved\">Saved</a></nav></div>"
453
+ },
454
+ {
455
+ "id": "tui",
456
+ "title": "Terminal UI (opt-in sheet)",
457
+ "classes": [
458
+ "b3-tui",
459
+ "b3-tui-frame",
460
+ "b3-tui-edge",
461
+ "b3-tui-fill",
462
+ "b3-tui-box",
463
+ "b3-tui-list",
464
+ "b3-tui-prompt",
465
+ "b3-tui-row",
466
+ "b3-tui-tag",
467
+ "b3-tui-section",
468
+ "b3-tui-keys"
469
+ ],
470
+ "guidance": "Opt-in: link @livx.cc/bare-v3/css/tui (standalone or after bare.css); these classes are not in the core sheet. For a picker or card that should look like the terminal it sits in: monospace, xterm palette, box-drawing frame. b3-tui on the root sets --b3-tui-* tokens (bg, fg, muted, faint, line, selected, accent, success, warning, danger, font); data-b3-tone=accent|success|warning|danger|muted|faint colors any descendant. b3-tui-frame is a column: a top b3-tui-edge (optional <b> title, <span class=b3-tui-fill>, optional <i> meta), b3-tui-box rows for fixed content, one b3-tui-box b3-tui-list that takes the rest and is the only scroller, a bottom edge (data-b3-edge=bottom), then b3-tui-keys with <kbd> hints. The list hides its scrollbar: put ▲/▼ in the bottom edge's <i> from a scroll listener. b3-tui-prompt is a label whose input gets a > prefix. b3-tui-row is a button (or a summary) with a 1ch cursor column; the app moves aria-selected=\"true\" to draw > and keeps keyboard focus in the prompt. details.b3-tui-section > summary.b3-tui-row gets a ▸/▾ twisty. b3-tui-tag brackets a state word: [open]. Touch gets 44px rows and a 16px input.",
471
+ "example": "<main class=\"b3-tui b3-tui-frame\"><div class=\"b3-tui-edge\"><b>sessions</b><span class=\"b3-tui-fill\"></span><i>3 live</i></div><div class=\"b3-tui-box\"><label class=\"b3-tui-prompt\"><input placeholder=\"filter\" aria-label=\"Filter\"></label></div><div class=\"b3-tui-box b3-tui-list\"><button class=\"b3-tui-row\" aria-selected=\"true\"><span data-b3-tone=\"success\">●</span>api server<span class=\"b3-tui-tag\" data-b3-tone=\"success\">open</span></button><details class=\"b3-tui-section\"><summary class=\"b3-tui-row\">ended (1)</summary><button class=\"b3-tui-row\"><span data-b3-tone=\"faint\">●</span>build<span class=\"b3-tui-tag\" data-b3-tone=\"danger\">crashed</span></button></details></div><div class=\"b3-tui-edge\" data-b3-edge=\"bottom\"><span class=\"b3-tui-fill\"></span><i></i></div><div class=\"b3-tui-keys\"><kbd>↑↓</kbd> select · <kbd>⏎</kbd> open</div></main>"
453
472
  }
454
473
  ],
455
474
  "references": [
@@ -482,6 +501,7 @@
482
501
  "conversation.md",
483
502
  "mobile.md",
484
503
  "app-frame.md",
504
+ "tui.md",
485
505
  "cross-screen.md",
486
506
  "date-picker.md",
487
507
  "editable-filtered-rows.md",
@@ -0,0 +1,9 @@
1
+ # Terminal UI (opt-in sheet)
2
+
3
+ Opt-in: link @livx.cc/bare-v3/css/tui (standalone or after bare.css); these classes are not in the core sheet. For a picker or card that should look like the terminal it sits in: monospace, xterm palette, box-drawing frame. b3-tui on the root sets --b3-tui-* tokens (bg, fg, muted, faint, line, selected, accent, success, warning, danger, font); data-b3-tone=accent|success|warning|danger|muted|faint colors any descendant. b3-tui-frame is a column: a top b3-tui-edge (optional <b> title, <span class=b3-tui-fill>, optional <i> meta), b3-tui-box rows for fixed content, one b3-tui-box b3-tui-list that takes the rest and is the only scroller, a bottom edge (data-b3-edge=bottom), then b3-tui-keys with <kbd> hints. The list hides its scrollbar: put ▲/▼ in the bottom edge's <i> from a scroll listener. b3-tui-prompt is a label whose input gets a > prefix. b3-tui-row is a button (or a summary) with a 1ch cursor column; the app moves aria-selected="true" to draw > and keeps keyboard focus in the prompt. details.b3-tui-section > summary.b3-tui-row gets a ▸/▾ twisty. b3-tui-tag brackets a state word: [open]. Touch gets 44px rows and a 16px input.
4
+
5
+ Classes: b3-tui, b3-tui-frame, b3-tui-edge, b3-tui-fill, b3-tui-box, b3-tui-list, b3-tui-prompt, b3-tui-row, b3-tui-tag, b3-tui-section, b3-tui-keys
6
+
7
+ ```html
8
+ <main class="b3-tui b3-tui-frame"><div class="b3-tui-edge"><b>sessions</b><span class="b3-tui-fill"></span><i>3 live</i></div><div class="b3-tui-box"><label class="b3-tui-prompt"><input placeholder="filter" aria-label="Filter"></label></div><div class="b3-tui-box b3-tui-list"><button class="b3-tui-row" aria-selected="true"><span data-b3-tone="success">●</span>api server<span class="b3-tui-tag" data-b3-tone="success">open</span></button><details class="b3-tui-section"><summary class="b3-tui-row">ended (1)</summary><button class="b3-tui-row"><span data-b3-tone="faint">●</span>build<span class="b3-tui-tag" data-b3-tone="danger">crashed</span></button></details></div><div class="b3-tui-edge" data-b3-edge="bottom"><span class="b3-tui-fill"></span><i></i></div><div class="b3-tui-keys"><kbd>↑↓</kbd> select · <kbd>⏎</kbd> open</div></main>
9
+ ```
package/dist/tui.css ADDED
@@ -0,0 +1,269 @@
1
+ @layer bare.components {
2
+ .b3-tui {
3
+ --b3-tui-bg: #1c1c1f;
4
+ --b3-tui-fg: #e6e6e6;
5
+ --b3-tui-muted: #999;
6
+ --b3-tui-faint: #666;
7
+ --b3-tui-line: #555;
8
+ --b3-tui-selected: #303036;
9
+ --b3-tui-accent: #11a8cd;
10
+ --b3-tui-success: #0dbc79;
11
+ --b3-tui-warning: #e5e510;
12
+ --b3-tui-danger: #f14c4c;
13
+ --b3-tui-font: Menlo, Consolas, "DejaVu Sans Mono", monospace;
14
+ color-scheme: dark;
15
+ background: var(--b3-tui-bg);
16
+ color: var(--b3-tui-fg);
17
+ font: 13px/1.5 var(--b3-tui-font);
18
+ }
19
+
20
+ :where(.b3-tui) [data-b3-tone="accent"] {
21
+ color: var(--b3-tui-accent);
22
+ }
23
+
24
+ :where(.b3-tui) [data-b3-tone="success"] {
25
+ color: var(--b3-tui-success);
26
+ }
27
+
28
+ :where(.b3-tui) [data-b3-tone="warning"] {
29
+ color: var(--b3-tui-warning);
30
+ }
31
+
32
+ :where(.b3-tui) [data-b3-tone="danger"] {
33
+ color: var(--b3-tui-danger);
34
+ }
35
+
36
+ :where(.b3-tui) [data-b3-tone="muted"] {
37
+ color: var(--b3-tui-muted);
38
+ }
39
+
40
+ :where(.b3-tui) [data-b3-tone="faint"] {
41
+ color: var(--b3-tui-faint);
42
+ }
43
+
44
+ .b3-tui-frame {
45
+ flex-direction: column;
46
+ min-block-size: 0;
47
+ display: flex;
48
+ }
49
+
50
+ .b3-tui-edge {
51
+ white-space: pre;
52
+ color: var(--b3-tui-line);
53
+ flex: none;
54
+ line-height: normal;
55
+ display: flex;
56
+ overflow: hidden;
57
+ }
58
+
59
+ .b3-tui-edge:before {
60
+ content: "┌";
61
+ }
62
+
63
+ .b3-tui-edge:has( > b):before {
64
+ content: "┌─ ";
65
+ }
66
+
67
+ .b3-tui-edge:after {
68
+ content: "─┐";
69
+ }
70
+
71
+ .b3-tui-edge[data-b3-edge="bottom"]:before {
72
+ content: "└";
73
+ }
74
+
75
+ .b3-tui-edge[data-b3-edge="bottom"]:has( > b):before {
76
+ content: "└─ ";
77
+ }
78
+
79
+ .b3-tui-edge[data-b3-edge="bottom"]:after {
80
+ content: "┘";
81
+ }
82
+
83
+ .b3-tui-edge > b {
84
+ color: var(--b3-tui-accent);
85
+ font-weight: 400;
86
+ }
87
+
88
+ .b3-tui-edge > b:after {
89
+ content: " ";
90
+ }
91
+
92
+ .b3-tui-edge > i {
93
+ color: var(--b3-tui-muted);
94
+ font-style: normal;
95
+ }
96
+
97
+ .b3-tui-edge > i:not(:empty):before, .b3-tui-edge > i:not(:empty):after {
98
+ content: " ";
99
+ }
100
+
101
+ .b3-tui-fill {
102
+ flex: 1;
103
+ min-inline-size: 0;
104
+ overflow: hidden;
105
+ }
106
+
107
+ .b3-tui-fill:before {
108
+ content: "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────";
109
+ }
110
+
111
+ .b3-tui-box {
112
+ border: solid var(--b3-tui-line);
113
+ border-width: 0 1px;
114
+ flex: none;
115
+ margin: 0 .5ch;
116
+ padding: 4px 1ch 0 calc(.5ch - 1px);
117
+ }
118
+
119
+ .b3-tui-list {
120
+ overscroll-behavior: contain;
121
+ -webkit-overflow-scrolling: touch;
122
+ scrollbar-width: none;
123
+ flex: auto;
124
+ min-block-size: 0;
125
+ padding-block: 0 4px;
126
+ overflow-y: auto;
127
+ }
128
+
129
+ .b3-tui-list::-webkit-scrollbar {
130
+ display: none;
131
+ }
132
+
133
+ .b3-tui-prompt {
134
+ min-block-size: 26px;
135
+ color: var(--b3-tui-accent);
136
+ cursor: text;
137
+ align-items: center;
138
+ gap: 1ch;
139
+ display: flex;
140
+ }
141
+
142
+ .b3-tui-prompt:before {
143
+ content: ">";
144
+ }
145
+
146
+ .b3-tui-prompt > input {
147
+ min-inline-size: 0;
148
+ color: var(--b3-tui-fg);
149
+ font: inherit;
150
+ caret-color: var(--b3-tui-success);
151
+ background: none;
152
+ border: 0;
153
+ outline: none;
154
+ flex: 1;
155
+ padding: 0;
156
+ }
157
+
158
+ .b3-tui-prompt > input::placeholder {
159
+ color: var(--b3-tui-faint);
160
+ }
161
+
162
+ .b3-tui-row {
163
+ box-sizing: border-box;
164
+ min-block-size: 26px;
165
+ inline-size: 100%;
166
+ color: inherit;
167
+ font: inherit;
168
+ text-align: start;
169
+ cursor: pointer;
170
+ white-space: nowrap;
171
+ -webkit-tap-highlight-color: transparent;
172
+ background: none;
173
+ border: 0;
174
+ outline: none;
175
+ align-items: center;
176
+ gap: 1ch;
177
+ padding: 1px 0;
178
+ display: flex;
179
+ }
180
+
181
+ .b3-tui-row:before {
182
+ content: " ";
183
+ color: var(--b3-tui-success);
184
+ flex: 0 0 1ch;
185
+ order: -2;
186
+ }
187
+
188
+ .b3-tui-row[aria-selected="true"] {
189
+ background: var(--b3-tui-selected);
190
+ }
191
+
192
+ .b3-tui-row[aria-selected="true"]:before {
193
+ content: ">";
194
+ }
195
+
196
+ .b3-tui-row:focus-visible {
197
+ box-shadow: inset 0 0 0 1px var(--b3-tui-accent);
198
+ }
199
+
200
+ .b3-tui-row:disabled {
201
+ opacity: .5;
202
+ cursor: default;
203
+ }
204
+
205
+ @media (hover: hover) {
206
+ .b3-tui-row:hover {
207
+ background: var(--b3-tui-selected);
208
+ }
209
+ }
210
+
211
+ .b3-tui-tag {
212
+ white-space: nowrap;
213
+ }
214
+
215
+ .b3-tui-tag:before {
216
+ content: "[";
217
+ }
218
+
219
+ .b3-tui-tag:after {
220
+ content: "]";
221
+ }
222
+
223
+ .b3-tui-section > summary {
224
+ color: var(--b3-tui-muted);
225
+ list-style: none;
226
+ }
227
+
228
+ .b3-tui-section > summary::-webkit-details-marker {
229
+ display: none;
230
+ }
231
+
232
+ .b3-tui-section > summary:after {
233
+ content: "▸";
234
+ order: -1;
235
+ }
236
+
237
+ .b3-tui-section[open] > summary:after {
238
+ content: "▾";
239
+ }
240
+
241
+ .b3-tui-keys {
242
+ color: var(--b3-tui-faint);
243
+ white-space: nowrap;
244
+ text-overflow: ellipsis;
245
+ flex: none;
246
+ margin-block-start: 6px;
247
+ padding: 0 1.5ch;
248
+ overflow: hidden;
249
+ }
250
+
251
+ .b3-tui-keys kbd {
252
+ font: inherit;
253
+ color: var(--b3-tui-muted);
254
+ }
255
+
256
+ @media (pointer: coarse) {
257
+ .b3-tui {
258
+ font-size: 14px;
259
+ }
260
+
261
+ .b3-tui-row, .b3-tui-prompt {
262
+ min-block-size: 44px;
263
+ }
264
+
265
+ .b3-tui-prompt > input {
266
+ font-size: 16px;
267
+ }
268
+ }
269
+ }
@@ -0,0 +1 @@
1
+ @layer bare.components{.b3-tui{--b3-tui-bg:#1c1c1f;--b3-tui-fg:#e6e6e6;--b3-tui-muted:#999;--b3-tui-faint:#666;--b3-tui-line:#555;--b3-tui-selected:#303036;--b3-tui-accent:#11a8cd;--b3-tui-success:#0dbc79;--b3-tui-warning:#e5e510;--b3-tui-danger:#f14c4c;--b3-tui-font:Menlo, Consolas, "DejaVu Sans Mono", monospace;color-scheme:dark;background:var(--b3-tui-bg);color:var(--b3-tui-fg);font:13px/1.5 var(--b3-tui-font)}:where(.b3-tui) [data-b3-tone=accent]{color:var(--b3-tui-accent)}:where(.b3-tui) [data-b3-tone=success]{color:var(--b3-tui-success)}:where(.b3-tui) [data-b3-tone=warning]{color:var(--b3-tui-warning)}:where(.b3-tui) [data-b3-tone=danger]{color:var(--b3-tui-danger)}:where(.b3-tui) [data-b3-tone=muted]{color:var(--b3-tui-muted)}:where(.b3-tui) [data-b3-tone=faint]{color:var(--b3-tui-faint)}.b3-tui-frame{flex-direction:column;min-block-size:0;display:flex}.b3-tui-edge{white-space:pre;color:var(--b3-tui-line);flex:none;line-height:normal;display:flex;overflow:hidden}.b3-tui-edge:before{content:"┌"}.b3-tui-edge:has(>b):before{content:"┌─ "}.b3-tui-edge:after{content:"─┐"}.b3-tui-edge[data-b3-edge=bottom]:before{content:"└"}.b3-tui-edge[data-b3-edge=bottom]:has(>b):before{content:"└─ "}.b3-tui-edge[data-b3-edge=bottom]:after{content:"┘"}.b3-tui-edge>b{color:var(--b3-tui-accent);font-weight:400}.b3-tui-edge>b:after{content:" "}.b3-tui-edge>i{color:var(--b3-tui-muted);font-style:normal}.b3-tui-edge>i:not(:empty):before,.b3-tui-edge>i:not(:empty):after{content:" "}.b3-tui-fill{flex:1;min-inline-size:0;overflow:hidden}.b3-tui-fill:before{content:"────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"}.b3-tui-box{border:solid var(--b3-tui-line);border-width:0 1px;flex:none;margin:0 .5ch;padding:4px 1ch 0 calc(.5ch - 1px)}.b3-tui-list{overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-width:none;flex:auto;min-block-size:0;padding-block:0 4px;overflow-y:auto}.b3-tui-list::-webkit-scrollbar{display:none}.b3-tui-prompt{min-block-size:26px;color:var(--b3-tui-accent);cursor:text;align-items:center;gap:1ch;display:flex}.b3-tui-prompt:before{content:">"}.b3-tui-prompt>input{min-inline-size:0;color:var(--b3-tui-fg);font:inherit;caret-color:var(--b3-tui-success);background:0 0;border:0;outline:none;flex:1;padding:0}.b3-tui-prompt>input::placeholder{color:var(--b3-tui-faint)}.b3-tui-row{box-sizing:border-box;min-block-size:26px;inline-size:100%;color:inherit;font:inherit;text-align:start;cursor:pointer;white-space:nowrap;-webkit-tap-highlight-color:transparent;background:0 0;border:0;outline:none;align-items:center;gap:1ch;padding:1px 0;display:flex}.b3-tui-row:before{content:" ";color:var(--b3-tui-success);flex:0 0 1ch;order:-2}.b3-tui-row[aria-selected=true]{background:var(--b3-tui-selected)}.b3-tui-row[aria-selected=true]:before{content:">"}.b3-tui-row:focus-visible{box-shadow:inset 0 0 0 1px var(--b3-tui-accent)}.b3-tui-row:disabled{opacity:.5;cursor:default}@media (hover:hover){.b3-tui-row:hover{background:var(--b3-tui-selected)}}.b3-tui-tag{white-space:nowrap}.b3-tui-tag:before{content:"["}.b3-tui-tag:after{content:"]"}.b3-tui-section>summary{color:var(--b3-tui-muted);list-style:none}.b3-tui-section>summary::-webkit-details-marker{display:none}.b3-tui-section>summary:after{content:"▸";order:-1}.b3-tui-section[open]>summary:after{content:"▾"}.b3-tui-keys{color:var(--b3-tui-faint);white-space:nowrap;text-overflow:ellipsis;flex:none;margin-block-start:6px;padding:0 1.5ch;overflow:hidden}.b3-tui-keys kbd{font:inherit;color:var(--b3-tui-muted)}@media (pointer:coarse){.b3-tui{font-size:14px}.b3-tui-row,.b3-tui-prompt{min-block-size:44px}.b3-tui-prompt>input{font-size:16px}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livx.cc/bare-v3",
3
- "version": "0.1.0-alpha.73",
3
+ "version": "0.1.0-alpha.74",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -9,6 +9,8 @@
9
9
  "exports": {
10
10
  "./css": "./dist/bare.css",
11
11
  "./css/min": "./dist/bare.min.css",
12
+ "./css/tui": "./dist/tui.css",
13
+ "./css/tui/min": "./dist/tui.min.css",
12
14
  "./manifest": "./dist/manifest.json",
13
15
  "./references/*": "./dist/references/*",
14
16
  "./ui": "./dist/ui.js",