@hearthscale/app-ui 0.0.0-stage → 0.1.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.
@@ -0,0 +1,507 @@
1
+ # The `hs-*` class names — versioned API
2
+
3
+ Every class below is public API from the moment the first app renders
4
+ against it: themes select on these names, and the top maintenance cost in
5
+ comparable ecosystems is undocumented class names that move. Renaming or
6
+ removing one is a break — one major per release train, named in the release
7
+ notes. Adding a name is free.
8
+
9
+ Scope:
10
+
11
+ - **`.hs-shell`** is the theme root (`<ThemeRoot>`), the glass frame every
12
+ surface renders in; its palette is the token set on `.hs-shell` /
13
+ `.hs-shell[data-theme='light']`. Nothing leaks into a page that does not
14
+ opt in.
15
+
16
+ ## Shell frame
17
+
18
+ Model presentation uses `.hs-model-avatar` for publisher artwork,
19
+ `.hs-model-details` / `.hs-model-details-row` for the fact rows,
20
+ `.hs-model-detail-fact` / `.hs-model-detail-chip` for labeled metadata, and
21
+ `.hs-model-capabilities-labeled` for icon-and-label capability chips. The compact
22
+ capability variant retains `.hs-model-capabilities` / `.hs-model-capability`.
23
+
24
+ | Class | Marks |
25
+ | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
+ | `hs-shell` | the theme root carrying the token set |
27
+ | `hs-shell-frame` | a window's frame; its `data-*` carry the desktop frame's states |
28
+ | `hs-side` | the side column: the rail |
29
+ | `hs-plugrow` | one app row in the sidebar |
30
+ | `hs-projrow` | a project row in the sidebar |
31
+ | `hs-sess`, `hs-sessrow`, `hs-stitle` | a session list, one session row, its title |
32
+ | `hs-session-row` | a session or helper row; `data-filed` in a project, `data-child` for a helper, `data-dragged` while carried |
33
+ | `hs-helper-mark` | the helper mark at the end of a helper row |
34
+ | `hs-project-row`, `hs-app-row` | a project row, an app row; `data-over` while a drag hovers it |
35
+ | `hs-sidebar-plus`, `hs-sidebar-spacer` | a row's new-session mark; the room the windowed list keeps for rows it does not draw |
36
+ | `hs-sidebar-rail-mark` | an app's mark on its rail plate |
37
+ | `hs-rowact` | the actions that appear on a hovered row |
38
+ | `hs-pinned` | the pin mark on a pinned session row |
39
+ | `hs-spin` | the turning arc of a session status mark |
40
+ | `hs-profile-glyph` | the account mark on the ladder |
41
+ | `hs-model-picker`, `hs-model-trigger`, `hs-model-trigger-name`, `hs-model-trigger-chevron` | the composer's models, one trigger per kind, its name and chevron |
42
+ | `hs-picker`, `hs-picker-rail`, `hs-picker-rail-item`, `hs-picker-main`, `hs-picker-search` | the model picker, its provider rail, one provider (`data-active`), the list side, the search |
43
+ | `hs-picker-list`, `hs-picker-section`, `hs-picker-heading`, `hs-picker-empty` | the models, one provider's section, its heading, "No model matches." |
44
+ | `hs-picker-row`, `hs-picker-row-text`, `hs-picker-row-name`, `hs-picker-row-sub` | one model (`data-state` is `ready`, `absent` or `unavailable`), its name and where it runs |
45
+ | `hs-provider-mark` | a provider's place or cloud mark |
46
+ | `hs-rview`, `hs-ptab`, `hs-tabscroll` | a tab's own box, a tab of a strip, the tab strip |
47
+ | `hs-app-surface` | an app's own tab in a row: the shell's chat of a conversation or the enable card; an app's view lays its `hs-sidebar-column` beside its chat in it |
48
+ | `hs-page` | a page of the shell's own in a tab: its navigation, a hairline, and `hs-page-main` |
49
+ | `hs-page-main` | a page's own column: Settings', the documentation's, the Marketplace's or the account's; `data-crowded` while the documentation's column reaches under its Ask press |
50
+ | `hs-window-notice`, `hs-window-notice-text` | a stopped platform's card over the inner window, and its sentence |
51
+ | `hs-window-wrap` | the inner window's box beside the rail |
52
+ | `hs-window-tiles` | the workspace's box, which the requests and notices of the window lie over |
53
+ | `hs-level`, `hs-level-control`, `hs-level-name`, `hs-level-chevron` | the permission level control and its name, which a narrow composer hides; `data-level` names the level in force, `data-open` marks its open menu |
54
+ | `hs-chat-body` | the transcript's box under whatever sits above it |
55
+ | `hs-view-frame`, `hs-view-iframe`, `hs-view-failure` | a hosted view in a view row, or a view surface that fills its tab; its sandboxed frame; `data-mode` is `inline` under its result, `tab` in a tab of its own or for a view surface, `modal` in a modal over its tile; `data-border` is `false` for a view that draws its own edge |
56
+ | `hs-view-modal` | a view in a modal over its tile: the scrim that dims the tile, under the view's clear frame and under the requests that float over the tile |
57
+ | `hs-view-sheet` | the plate a view’s frame sits on |
58
+ | `hs-view-place` | the place of a result’s view under its result; `data-away` while it shows in a tab of its own |
59
+ | `hs-view-bar`, `hs-view-bar-head` | the host's bar of a result's view, under its result and in its modal: the app's mark and name, then the presses that move the view; `data-mode` is `inline` or `modal` |
60
+ | `hs-view-home` | the element a result's view renders into, which moves between its place, its tab and its modal and adds no box |
61
+ | `hs-view-modal-plate` | the plate of a result's view the person moved over the chat, inset from the tile's edges |
62
+ | `hs-ask-float` | a request floating over the inner window, over the soft scrim |
63
+ | `hs-slot-layer`, `hs-slot`, `hs-slot-part` | the layer over a view that fills its tab; one slot the view reserved, anchored by its insets, `data-kind` its kind (`chat`, `composer`, `cards`, `terminal`) and `data-slot` its id; the part the shell draws there |
64
+ | `hs-url`, `hs-urlin`, `hs-urlgo`, `hs-urlph` | a browser's address field and its parts |
65
+ | `hs-scroll` | a scroll container with the shell's scrollbar |
66
+ | `hs-menu`, `hs-mitem` | a floating menu surface and one item |
67
+ | `hs-waytile`, `hs-orb` | a colourway tile and one of its orbs; `data-sel` marks the pick |
68
+ | `hs-confirm` | the backdrop of a confirmation dialog, or of a wait with no control, over the shell |
69
+ | `hs-confirm-box` | that dialog; `hs-confirm-title`, `hs-confirm-body` its two lines |
70
+ | `hs-confirm-notes` | the scrolling text under a dialog's body: a release's notes |
71
+ | `hs-confirm-cancel`, `hs-confirm-action` | its two buttons: the way out, and the action it asks for |
72
+ | `hs-sheet-shell` | a small text sheet over the shell |
73
+ | `hs-walk` | a walkthrough; `data-host` is `dialog` (a plate over the shell, on a veil) or `window` (the whole window) |
74
+ | `hs-walk-card`, `hs-walk-close` | its card; the close mark at the card's top right |
75
+ | `hs-walk-image` | the picture band across the top of a card |
76
+ | `hs-walk-main` | the region under the picture that holds the words, the rows and the live content; `data-image` under one |
77
+ | `hs-walk-title`, `hs-walk-sub` | a card's title and the line under it |
78
+ | `hs-walk-rows`, `hs-walk-row` | a card's list (`data-layout` is `list`, `open` or `grid`), and one row of it |
79
+ | `hs-walk-row-mark`, `hs-walk-row-text`, `hs-walk-row-title`, `hs-walk-row-sub` | a row's mark, its words, its title and the line under the title |
80
+ | `hs-walk-body` | the bordered plate a card's live content sits in |
81
+ | `hs-walk-foot`, `hs-walk-dots`, `hs-walk-dot` | the foot, the page dots, one dot; `data-sel` marks the card shown |
82
+ | `hs-walk-foot-start`, `hs-walk-next-off` | Back and a second way off the card; the forward press on a card the reader cannot move past |
83
+ | `hs-onboarding-body`, `hs-onboarding-prose` | the live part of a first-run card; a line of words in it |
84
+ | `hs-onboarding-row` | a glass row that starts an act (`data-press`) or says it is done (`data-ticked`) |
85
+ | `hs-onboarding-row-mark`, `hs-onboarding-row-label`, `hs-onboarding-row-done` | the row's mark, its words, and the check and word of a done act |
86
+ | `hs-onboarding-fine`, `hs-onboarding-problem`, `hs-onboarding-retry` | a quiet line under a press; a failure; the press that tries again |
87
+ | `hs-onboarding-link` | a link in a card's words, in the words' own colour |
88
+ | `hs-titlebar` | the title bar of a window that draws its own caption buttons (the Server, the installer) |
89
+ | `hs-caption-glyph` | a caption glyph under the system's own caption button; `data-hovered` while that button is hovered |
90
+ | `hs-app-state` | an app's state on the card that enables it; `data-tone` is `ok`, `mut`, `warn` or `bad` |
91
+ | `hs-submenu-chevron` | the chevron of a menu row that opens a flyout |
92
+ | `hs-browser-step-off` | a browser's Back or Forward with no page to go to |
93
+ | `hs-tip`, `hs-tipwrap` | a tooltip and the element that anchors one |
94
+ | `hs-tog` | a toggle switch |
95
+ | `hs-in`, `hs-ta`, `hs-ph-icon` | a text input, a textarea, a placeholder with a leading icon |
96
+ | `hs-navhead`, `hs-setrow`, `hs-chip` | a settings nav section label, a settings row, a choice chip |
97
+ | `hs-sethead` | a settings detail page's header: its mark, its name and its sub |
98
+ | `hs-grantrow` | one grant in the access list, a `hs-list-row` with its Revoke; an approval surface |
99
+ | `hs-range`, `hs-tile` | a settings slider; a scheme or colourway tile |
100
+ | `hs-flash` | the row a settings search hit landed on |
101
+ | `hs-mask` | a drop-in icon set's mark, drawn as a mask in the text colour |
102
+
103
+ ## The frame: rail, tiles and surfaces
104
+
105
+ | Class | Marks |
106
+ | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
107
+ | `hs-rail` | the rail at the window's left edge, with `hs-sidebar-rail`; `data-lifting` while a plate is dragged |
108
+ | `hs-rail-top`, `hs-rail-plate` | the mark's zone at the top, an app's plate; `data-lifted` during a drag, `data-settle` at its end |
109
+ | `hs-ladder`, `hs-ladder-button`, `hs-ladder-dot` | the system button and its ladder (`data-open`), the button, its dot when a rung waits |
110
+ | `hs-ladder-rungs`, `hs-ladder-rung` | the ladder's glass backing, one rung; `data-solid`, `data-active`, `data-pressed` |
111
+ | `hs-workspace` | the tiles' box; `data-drag` is `row`, `column` or `tab` |
112
+ | `hs-workspace-tile`, `hs-tile-panel` | a tile (`data-tile`), its panel |
113
+ | `hs-lane` | a tile's lane; `data-row` is `top` or `low`, `data-caption` where it ends under the caption buttons |
114
+ | `hs-lane-crumb`, `hs-lane-crumb-app`, `hs-lane-crumb-title` | a lone tab's breadcrumb, its app's name, its title |
115
+ | `hs-lane-tabs`, `hs-lane-tab`, `hs-lane-tab-mark` | the strip from the second tab on, with the panel tab classes; a tab (`data-hover`; `data-leaving` while it closes), its mark |
116
+ | `hs-lane-button`, `hs-lane-plus`, `hs-lane-title-field` | a lane control (`data-control`), the plus, a title edited in place |
117
+ | `hs-lane-rule` | the hairline between two lanes side by side |
118
+ | `hs-tab-card`, `hs-tab-card-title`, `hs-tab-card-preview` | the hover card under a strip's tab (`data-open`), its title, its picture |
119
+ | `hs-divider` | the invisible divider of a split; `data-axis` is `row` or `column` |
120
+ | `hs-tile-drop` | where a dragged tab would land |
121
+ | `hs-surfaces`, `hs-surface` | the stable layer (`data-drag`), one surface (`data-surface`; `data-state` is `live` or `warm`) |
122
+ | `hs-web-page` | an app's web surface: its page, which fills its surface |
123
+
124
+ ## Shell interaction states
125
+
126
+ | Class | Marks |
127
+ | --------------------------------------------------- | ---------------------------------------------------------------------- |
128
+ | `hs-hovbox`, `hs-hovbox-ink` | hover plate; hover plate that also brightens the ink |
129
+ | `hs-hovink`, `hs-hovmut` | hover that brightens ink only / mutes |
130
+ | `hs-boxact`, `hs-boxsel` | the active plate, the selected plate |
131
+ | `hs-glassbtn` | a glass button |
132
+ | `hs-inktext`, `hs-inkmut`, `hs-inkdim`, `hs-inkbad` | the ink an element rests at, so a hover or selection rule can reach it |
133
+
134
+ ## Transcript
135
+
136
+ | Class | Marks |
137
+ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
138
+ | `hs-transcript`, `hs-transcript-spacer` | the column of rows, and the room under it that holds a sent prompt near the top |
139
+ | `hs-turn` | one prompt or one answer, with the actions that show on hover |
140
+ | `hs-md`, `hs-md-link`, `hs-md-picture`, `hs-md-missing` | an answer's markdown; a link in it; a picture of the turn it names; a named picture that is not there |
141
+ | `hs-abar` | the actions under a prompt or an answer |
142
+ | `hs-chat-action`, `hs-chat-time`, `hs-chat-pager` | one of those actions; the moment on hover; the branch pager |
143
+ | `hs-copy`, `hs-copy-tip` | the Copy action and the "Copied" tip over it |
144
+ | `hs-work-row` | one call; `data-status` is `running`, `waiting`, `completed`, `failed`, `declined`, `stopped`, `skipped` or `unknown` |
145
+ | `hs-work-head` | a line with an action beside it, such as Stop; a row's `data-cell` names a program that runs on |
146
+ | `hs-work-line`, `hs-work-mark`, `hs-work-label`, `hs-work-time`, `hs-work-chevron` | a row's line, its mark, its words, the time the call took (on hover), its chevron (`data-open`) |
147
+ | `hs-work-body` | what an opened call did |
148
+ | `hs-work-nested` | the calls made while a call ran, under its line |
149
+ | `hs-work-command`, `hs-work-path`, `hs-work-text`, `hs-work-output` | its blocks: the command, the path, the prompt or text, the output |
150
+ | `hs-work-decision`, `hs-work-note`, `hs-work-more` | who let it run or refused it (`data-refused`); a quiet line; the raw details' disclosure |
151
+ | `hs-work-live` | the row that names the live turn's running call |
152
+ | `hs-work-toggle`, `hs-work-sentence` | a finished run of calls as one sentence; `data-failure` marks a run that ended in a failure |
153
+ | `hs-work-group` | an opened run; `data-fade` is `top`, `bottom` or `both` where more calls lie beyond its edge |
154
+ | `hs-activity`, `hs-activity-list` | thoughts and calls of one turn (`data-active` while live), and its opened list |
155
+ | `hs-thought`, `hs-thought-preview`, `hs-reasoning` | one thought, its one-line preview, its text |
156
+ | `hs-spawn`, `hs-spawn-members`, `hs-spawn-member` | the helpers a turn handed work to (`data-failure`), their list, one helper |
157
+ | `hs-spawn-head`, `hs-spawn-title`, `hs-spawn-agent`, `hs-spawn-preview` | a helper's line, its title, its agent, its latest words |
158
+ | `hs-working`, `hs-working-clock` | the live turn's header and its clock |
159
+ | `hs-turn-fold` | a settled turn's work behind one line |
160
+ | `hs-thread-mark`, `hs-thread-mark-line`, `hs-thread-mark-text` | a line across the transcript with a caption in it |
161
+ | `hs-fork-origin`, `hs-tail-mark` | where a fork came from; where the model reads word for word again |
162
+ | `hs-compaction`, `hs-compaction-line`, `hs-compaction-body`, `hs-compaction-where` | the separator of compacted messages, its line, the summary, who wrote it |
163
+ | `hs-notice-row`, `hs-notice-text` | something that went wrong or stopped; `data-tone` is `bad` or `warn` |
164
+ | `hs-app-entry` | an app's own entry |
165
+ | `hs-changed`, `hs-changed-head`, `hs-changed-title`, `hs-changed-files` | the files a turn changed, its head, its title, the file chips |
166
+ | `hs-diff-count` | a line count beside a changed file; `data-kind` is `add` or `del` |
167
+ | `hs-view-row` | a result's view in the transcript |
168
+ | `hs-media`, `hs-media-pictures`, `hs-media-actions` | what a call made; its pictures (`data-count` is `one` or `many`); the actions over a picture |
169
+ | `hs-chat-image`, `hs-chat-image-name` | a picture a call made, in a frame of its size; the name of one that did not load |
170
+ | `hs-audio`, `hs-audio-play`, `hs-audio-name`, `hs-audio-bar`, `hs-audio-fill` | a sound's player, its play and pause, its name, its bar and the part played |
171
+ | `hs-audio-time`, `hs-audio-save` | the player's times and its Save |
172
+ | `hs-user-bubble`, `hs-user-text`, `hs-user-more` | a prompt, its text (`data-folded`), "Show full message" |
173
+ | `hs-user-tiles`, `hs-user-tile-cell`, `hs-user-tile`, `hs-user-tile-name` | a prompt's pictures, one cell, the tile, the name of one that did not load |
174
+ | `hs-user-caption`, `hs-user-caption-toggle`, `hs-user-caption-text` | what a model read in a picture, its disclosure, its words |
175
+ | `hs-user-file`, `hs-user-file-name` | another file a prompt carried, and its name |
176
+ | `hs-turn-rail`, `hs-turn-rail-mark`, `hs-turn-rail-line`, `hs-turn-preview` | the rail of prompts, one mark, its line (`data-bright` for the turns on screen), the hover preview |
177
+ | `hs-jump-place`, `hs-jump` | where the "Scroll to end" pill sits, and the pill |
178
+ | `hs-chat` | the chat; `data-layout` is `composer` where it draws the composer alone |
179
+ | `hs-compose-position`, `hs-compose-box`, `hs-chat-fade` | the composer's column (`data-empty` on the opening screen), its box, the fade at the top |
180
+ | `hs-composer`, `hs-composer-dock`, `hs-composer-main` | the composer (`data-answering` while a request waits, `data-narrow` in its narrow form), the drawers on its top edge, its glass box |
181
+ | `hs-composer-field`, `hs-composer-editor`, `hs-composer-placeholder` | the editor's box, the editor, its placeholder |
182
+ | `hs-composer-footer`, `hs-composer-fill`, `hs-composer-tool`, `hs-composer-stop`, `hs-composer-send` | the footer, its spacer, a tool such as attach, Stop, Send |
183
+ | `hs-drawer`, `hs-drawer-dot`, `hs-drawer-fill`, `hs-drawer-text` | a drawer on the composer (`data-tone` is `info` or `menu`), its dot, its spacer, its sentence |
184
+ | `hs-composer-menu`, `hs-composer-menu-list`, `hs-composer-menu-row` | the `/` and `@` menu, its list, one row (`data-active`) |
185
+ | `hs-composer-menu-mark`, `hs-composer-menu-label`, `hs-composer-menu-sub`, `hs-composer-menu-status` | a row's mark, name and description; the searching or none-found words |
186
+ | `hs-inline-chip`, `hs-inline-chip-mark` | a file, a folder, a skill or an app's item in the editor or a sent prompt (`data-kind` is `file`, `folder`, `skill` or `mention`), its mark |
187
+ | `hs-composer-shelf`, `hs-shelf-tiles`, `hs-shelf-tile`, `hs-shelf-tile-open`, `hs-shelf-remove` | what rides the next prompt; its pictures, one tile, the tile's opener, a remove button |
188
+ | `hs-shelf-file`, `hs-shelf-file-name`, `hs-shelf-file-size` | another file on the shelf, its name, its size |
189
+ | `hs-shelf-chips`, `hs-shelf-chip`, `hs-shelf-chip-note` | the chips (`data-kind` is `folder`, `terminal`, or `context` for what a view adds, with `data-chip` its id), the "read only" note |
190
+ | `hs-shelf-refused` | a file the composer could not attach, or a level change the platform refused, in words |
191
+ | `hs-ring`, `hs-ring-panel`, `hs-ring-title`, `hs-ring-share`, `hs-ring-note` | the context ring, its popover, the popover's title, the share used, its sentence |
192
+ | `hs-ring-actions`, `hs-ring-answer`, `hs-ring-details-toggle`, `hs-ring-details` | Compact and the daemon's answer; the Details disclosure and what it holds |
193
+ | `hs-ring-fact`, `hs-ring-layer`, `hs-ring-layer-line`, `hs-ring-cost`, `hs-ring-text` | a fact of the prompt; one layer, its line (`data-static` for a tool's), its cost, its text |
194
+ | `hs-ask`, `hs-ask-head`, `hs-ask-mark`, `hs-ask-title`, `hs-ask-app`, `hs-ask-count` | a request (`data-placement` is `docked` or `floating`, `data-narrow` in its narrow form), its head, mark, title, app, and "1 of 3" |
195
+ | `hs-ask-body`, `hs-ask-note`, `hs-ask-data`, `hs-ask-command` | its sentence, a warning under it, a path or a code in it, the command it would run or a tool call's arguments |
196
+ | `hs-ask-tools`, `hs-ask-tool`, `hs-ask-tool-name`, `hs-ask-tool-text` | a connector's tools, one tool, its name, its description |
197
+ | `hs-ask-actions`, `hs-ask-keys`, `hs-ask-options`, `hs-ask-option` | the request's buttons and the keys that answer it; a question's options, one option |
198
+ | `hs-ask-scroll`, `hs-ask-message`, `hs-ask-form` | a form's words, fields and preview, which scroll as one inside the card; its words, which keep their lines; its fields |
199
+ | `hs-ask-field`, `hs-ask-field-head`, `hs-ask-field-title`, `hs-ask-field-switch` | one field (`data-kind` names its kind, `data-problem` while it holds a value it may not send), its head, its title, the switch of a yes or no |
200
+ | `hs-ask-problem`, `hs-ask-refusal` | why a field cannot be sent; the platform's words when it refused the form |
201
+ | `hs-ask-chips`, `hs-ask-add` | a field's choices, the presses of its suggestions or words; the row that adds a word or a file |
202
+ | `hs-ask-picks`, `hs-ask-pick`, `hs-ask-pick-press`, `hs-ask-picture`, `hs-ask-pick-title`, `hs-ask-pick-mark` | a list of choices with pictures or of resources, one row (`data-sel` while chosen), its press, its picture, its title, the mark of whether it is chosen |
203
+ | `hs-chat-destination` | the project the first message of an opening screen goes into |
204
+ | `hs-drop-overlay`, `hs-drop-pill` | files dragged over the chat, and the words over them |
205
+ | `hs-user-blocks`, `hs-user-queued` | the terminal lines a prompt carried; the words under a message that waits (`data-queued` on its turn) |
206
+ | `hs-shine` | a live label's shine |
207
+ | `hs-unknown-part` | a transcript part no registered view claims |
208
+ | `hs-unknown-part-head`, `hs-unknown-part-context`, `hs-unknown-part-data` | its disclosure line; the text it fed the model; its raw data |
209
+
210
+ | Primitive | Marks |
211
+ | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
212
+ | `hs-status` | a state in words at the end of a row; `data-tone` is `ok`, `bad`, `warn`, `info` or `dim` |
213
+ | `hs-meter`, `hs-meter-track`, `hs-meter-fill` | how much of something is done or used; `data-variant` is `bar` or `ring`, `data-tone` `bad` near its limit |
214
+ | `hs-kbd` | a key the person can press |
215
+ | `hs-input` | a one-line field with a box; `data-variant` is `text`, `number` or `password` |
216
+ | `hs-chip`, `hs-chip-mark`, `hs-chip-text` | a small named thing; `data-tone` is `neutral`, `info`, `ok`, `warn` or `bad`; a choice chip carries `data-sel` and no tone |
217
+ | `hs-app-icon` | an app's own icon, or the mark of an app or a plugin |
218
+ | `hs-system-icon` | the machine's own icon for a file or a folder |
219
+ | `hs-file-kind` | a file's kind as a coloured mark until its system icon arrives; `data-kind` names the kind |
220
+ | `hs-lightbox`, `hs-lightbox-bar`, `hs-lightbox-button` | pictures over the window, its bar, a control on it |
221
+ | `hs-lightbox-step`, `hs-lightbox-body`, `hs-lightbox-stage` | the step to a picture beside (`data-side`), the body, the stage (`data-zoomed`) |
222
+ | `hs-lightbox-broken`, `hs-lightbox-caption`, `hs-lightbox-note`, `hs-lightbox-reread` | a picture that did not load, the caption, the note under it, "Read the picture again" |
223
+
224
+ ## Documentation
225
+
226
+ | Class | Marks |
227
+ | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
228
+ | `hs-docs-root`, `hs-docs-root-title`, `hs-docs-root-mark` | the documentation root on screen, which opens a menu of the others; its name; a root's mark in that menu |
229
+ | `hs-docs-folder-chevron`, `hs-docs-folder-pages` | a folder's chevron in the navigation (`data-open`); its pages, on a line beneath it |
230
+ | `hs-docs-ask` | the press at the page's top right that asks an app about the page |
231
+ | `hs-docs-page-foot` | under a page, over its pager: the date it was last changed |
232
+ | `hs-docs-unreachable` | a page or the whole documentation that could not be read, and its retry |
233
+
234
+ ## Diff
235
+
236
+ | Class | Marks |
237
+ | -------------------------------------------- | --------------------------------------------------------------------------------------- |
238
+ | `hs-diff` | the diff view, carrying the mono face its rows are set in |
239
+ | `hs-diff-bar` | its bar: the counts, collapse-all, and a raw patch's reason |
240
+ | `hs-diff-act` | a control on that bar |
241
+ | `hs-diff-reason`, `hs-diff-picked` | a raw patch's reason on the bar; the number of lines selected |
242
+ | `hs-diff-counts` | the added and deleted counts, each a `hs-diff-count` |
243
+ | `hs-diff-chevron`, `hs-diff-status` | a file header's chevron; its state: added, deleted or renamed |
244
+ | `hs-diff-file`, `hs-diff-path` | one file's header, sticky over that file's rows; the path on it |
245
+ | `hs-diff-row` | one unified row; `data-kind` is `add`, `del` or `ctx`, and `data-sel` marks it selected |
246
+ | `hs-diff-no`, `hs-diff-sign`, `hs-diff-text` | a row's two line-number gutters, its marker column, its text |
247
+ | `hs-diff-gap`, `hs-diff-hunk` | an unmodified run that expands in place; the hunk header beside it |
248
+ | `hs-diff-raw` | a patch the parser did not read, shown as text |
249
+
250
+ ## Product components (`packages/ui/src`)
251
+
252
+ One class per component, named after it: `hs-button`, `hs-card`, `hs-chart`,
253
+ `hs-code-block`, `hs-diagram`, `hs-hearth-pulse`, `hs-icon-button`,
254
+ `hs-label`, `hs-lockup`, `hs-mark`, `hs-modal`, `hs-modal-backdrop`,
255
+ `hs-mono`, `hs-notice`, `hs-page-title`,
256
+ `hs-terminal`, `hs-text-field`.
257
+
258
+ | Class | Marks |
259
+ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
260
+ | `hs-button` | a text button; `data-variant` is `primary`, `secondary`, `ghost` or `danger`, `data-size` is `sm`, `md` or `lg`, `data-full` stretches it |
261
+ | `hs-icon-button` | a mark-only button; `data-size` is `sm`, `md` or `lg` |
262
+ | `hs-card` | a grouped surface; `data-variant` is `solid`, `glass` or `gate` (opaque), `data-tone` `warn` or `info` for one that asks |
263
+ | `hs-label` | a caption in the interface font |
264
+ | `hs-lockup-box`, `hs-lockup-mark`, `hs-lockup-word` | the lockup's 38px box, the mark on its floor, the wordmark beside it |
265
+ | `hs-model-avatar-initial` | a publisher's first letter where it has no picture |
266
+ | `hs-mono` | machine text inside a sentence or a row |
267
+ | `hs-page-title`, `hs-page-lead` | a page's heading (`data-hero` centres and enlarges it) and the line under it |
268
+ | `hs-fact-row`, `hs-fact-label`, `hs-fact-value` | a row of an information table, its label and its wrapping value |
269
+ | `hs-link-row`, `hs-link-row-chevron` | a row that opens its own page, and its chevron |
270
+ | `hs-list-row`, `hs-list-row-actions` | a row of a managed list, and the actions at its end |
271
+ | `hs-grant-groups`, `hs-grant-group-head`, `hs-grant-group-name`, `hs-grant-group-summary`, `hs-grant-group-chevron` | the access list, one card per app: its folding head, the app's name, the summary of what it holds, the chevron |
272
+ | `hs-grant-group-bypass` | the warning mark on the head of an app at Bypass all permissions |
273
+ | `hs-segmented`, `hs-segmented-option` | a choice of a few options, all in sight, and one option; `aria-checked` marks the chosen one |
274
+ | `hs-market-install-note` | why an install cannot start, or why it failed; `data-tone` is `warn` or `bad` |
275
+ | `hs-row-mark` | the mark before a row's label |
276
+ | `hs-nav-rail-press` | a press of the collapsed settings nav, a mark whose name floats beside it; `data-sel` on the page on screen |
277
+ | `hs-fact-lines` | a fact whose value is a list, one line per item |
278
+ | `hs-app-review` | the facts an update added, listed on an app's settings page |
279
+ | `hs-archive-facts` | an archived conversation's date and its number of entries |
280
+ | `hs-link` | a link that runs a handler instead of carrying an address |
281
+ | `hs-code-head`, `hs-code-language`, `hs-code-reason` | a code block's header bar, its language and the reason the code is shown as text |
282
+ | `hs-code-copy`, `hs-code-pre` | a code block's copy control and its text |
283
+ | `hs-modal-head`, `hs-modal-title` | a dialog's header and its title |
284
+ | `hs-report-body` | a dialog of performance reports, each shown as the text that is sent |
285
+ | `hs-field-label`, `hs-field-input`, `hs-field-note`, `hs-field-hint` | a text field's label, input, the note beside the label, the line under the input |
286
+
287
+ ## Server dashboard and installer
288
+
289
+ The Server dashboard and the installer window wear the shell frame
290
+ (`hs-shell-frame`, `hs-frame-*`, `hs-titlebar*`, `hs-side`, `hs-window*`)
291
+ and add these:
292
+
293
+ | Class | Marks |
294
+ | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
295
+ | `hs-caption-button` | a caption button a window with no system caption draws; `data-danger` on the close button |
296
+ | `hs-server-nav`, `hs-server-nav-pages`, `hs-server-nav-footer` | the dashboard's navigation column, its page list, its power action |
297
+ | `hs-server-window` | the box of the dashboard's page panel beside its navigation column |
298
+ | `hs-server-waiting` | the words a dashboard page shows while the Server is not running or not reached |
299
+ | `hs-server-pending` | a row's title with a pulse, while the account link waits on the browser |
300
+ | `hs-server-help` | the endpoint id's help in a dialog |
301
+ | `hs-installer-run`, `hs-installer-rows` | a run's card body, the bar over the list, and the list |
302
+ | `hs-installer-bar`, `hs-installer-fill` | the run's glass bar and its gold fill |
303
+ | `hs-installer-stage` | one stage of a run; `data-state` is `done`, `current`, `pending` or `failed` |
304
+ | `hs-installer-slot`, `hs-installer-dot` | a mark's slot at the start of a row; the dot of the current or a waiting stage |
305
+ | `hs-installer-label`, `hs-installer-detail` | a row's words, and the quiet detail at its end |
306
+ | `hs-installer-stopped`, `hs-installer-stopped-text` | a stopped run's sentence and its Retry; the sentence |
307
+ | `hs-installer-folder` | the install folder, a glass press that opens the folder dialog |
308
+ | `hs-installer-offer`, `hs-installer-specs`, `hs-installer-spec`, `hs-installer-spec-mark` | the set-up's offer, the machine's facts, one fact, its mark |
309
+ | `hs-installer-picks`, `hs-installer-pick`, `hs-installer-tick` | the receipt's rows, one row (`data-ticked`, `data-fixed`), its tick box |
310
+
311
+ ## Rules
312
+
313
+ - A theme overrides token values and selects on these names; it never
314
+ depends on DOM structure between them.
315
+ - Every class takes its corner from a role token: `--r-ctl`, `--r-card`,
316
+ `--r-tile`, the small corner `--r-sm`, or a shape (`--r-pill`,
317
+ `--r-round`, `--r-icon`). [`TOKENS.md`](TOKENS.md) lists the classes of
318
+ each role. A theme reshapes corners through `--r` and the role tokens, and
319
+ selects a class only to give one family a corner of its own.
320
+ - `hs-confirm*`, `hs-grantrow` and `hs-tog` are the approval surfaces: their
321
+ presence and operability (`display`, `visibility`, `opacity`,
322
+ `pointer-events`, `position`) are pinned in `theme.css`'s `hs.guard` layer,
323
+ which no theme can reach past; their colour, type and shape are themeable.
324
+ - New UI lands with an `hs-*` name when a theme could reasonably want it.
325
+ - Removing a class, or moving what it marks, is recorded as a break.
326
+
327
+ ## Component presentation hooks
328
+
329
+ The selectors in [`src/shell.css`](src/shell.css) are the full inventory of
330
+ named shell presentation hooks. They follow these component families:
331
+
332
+ | Surface | Class families |
333
+ | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
334
+ | Frame and title bar | `hs-frame-*`, `hs-window*`, `hs-titlebar*`, `hs-toolbar*` |
335
+ | Sidebar | `hs-sidebar-*`, `hs-session-*`, `hs-project-*`, `hs-app-*`, `hs-selection-*` (the selection toolbar) |
336
+ | Chat and composer | `hs-chat*`, `hs-compose*`, `hs-user-*`, `hs-assistant-*`, `hs-turn-preview-*` |
337
+ | Panels | `hs-panel-*`, `hs-browser-*`, `hs-file-*`, `hs-files-*`, `hs-document-*`, `hs-terminal-*`, `hs-changes-*`, `hs-find-*`, `hs-tab-*` |
338
+ | Settings | `hs-settings-*`, `hs-setting-*`, `hs-appearance-*`, `hs-provider-*`, `hs-nav-*`, `hs-search-*`, `hs-colour*`, `hs-theme-*`, `hs-size-*` |
339
+ | Documentation | `hs-docs-*` |
340
+ | Marketplace | `hs-market*` |
341
+ | Models | `hs-model-*`, `hs-picker-*` |
342
+ | Server dashboard | `hs-server-*` |
343
+ | Forms | `hs-select*`, `hs-toggle-*`, `hs-code-*` (a code block, and the one-time code's slots) |
344
+ | Overlays | `hs-menu-*`, `hs-submenu-*`, `hs-confirm-*`, `hs-sheet-*`, `hs-tooltip*` |
345
+
346
+ Selection uses `data-sel="true"`; settings buttons expose `data-strong` and
347
+ `data-danger`, menu items expose `data-disabled`, and selects expose `data-open`.
348
+ `hs-floating-tip` is a help tip placed beside its mark, `hs-range-value` the
349
+ value beside a slider, `hs-size-step` a step of a size stepper,
350
+ `hs-row-anchor` a row that positions a mark over its corner, and
351
+ `hs-push-end` an element pushed to the end of its row.
352
+ Prefer these hooks to selectors coupled to child order or inline styles.
353
+
354
+ Hooks outside the families: `hs-main-view` is an app's own surface in a tile, and
355
+ `hs-empty-view` with `hs-empty-view-title` a place with nothing in it yet
356
+ (`EmptyState`), such as the view of a window with no app; `hs-view` the root
357
+ of a packaged view's document, beside `hs-shell`;
358
+ `hs-breadcrumb-separator` the mark
359
+ between two places of a trail; `hs-flex-spacer` the room that pushes what
360
+ follows it to the end of its row; `hs-navrow` a settings or documentation
361
+ nav row; `hs-info-row` a settings row with a value; `hs-sethead-action`
362
+ the control at the end of a detail page's header; `hs-help-button` and
363
+ `hs-help-mark` a help tip's mark, with and without a page behind it;
364
+ `hs-address-go`, `hs-site-button` and `hs-path-segment` the panel
365
+ browser's go mark, its site press, and one folder of the Files path;
366
+ `hs-preview-open` the press that opens a previewed file in its app;
367
+ `hs-brand-mark` a vendor's logo; `hs-signin-method` the sign-in control;
368
+ `hs-light-only` and `hs-dark-only` a picture drawn in one scheme only.
369
+
370
+ Virtual slot classes (`hs-session-slot`, `hs-subagent-slot`, `hs-project-slot`) are measured by `SidebarRowMetrics`. Give each role a
371
+ positive uniform height; put visual padding inside its slot, without external
372
+ margins. Theme row-height tokens provide the defaults.
373
+
374
+ Approval classes can be selected directly for cosmetic changes. The final
375
+ layer reserves presence and interaction; it does not pin typography or shape.
376
+
377
+ The file tree measures `hs-file-row` too, including live density edits. Glyphs
378
+ accept `className` for role-specific styling in both the SVG and masked-icon
379
+ paths; `hs-glyph` and `hs-mask` identify those two renderers. `hs-icon` is a
380
+ mark of the Remix Icon font beside its `ri-<name>` class, in the box of its
381
+ font size; the rules that reach a drawn mark reach it too.
382
+
383
+ A file's preview in a view: `hs-document-view` holds Markdown, a CSV, a
384
+ diagram or a chart drawn from the file's text, a CSV as a Markdown table;
385
+ `hs-file-partial` says that only the head of a long file shows.
386
+
387
+ Model browsing uses `hs-model-browser*`, `hs-model-header*`, `hs-model-tile`,
388
+ `hs-model-stat`, `hs-model-stats`, `hs-model-capabilities`, `hs-model-capability`
389
+ and `hs-model-card`. Selected rows use `aria-pressed="true"`.
390
+
391
+ Settings grouping: `hs-settings-card` (`SettingsCard`) owns the outer border;
392
+ `hs-settings-group` / `hs-settings-group-title` divide its content.
393
+ `hs-settings-note` and `hs-settings-actions` inset descriptions and buttons;
394
+ `hs-settings-card-header` aligns collapsible group labels with row content.
395
+ `--content-width` sets the shared composer/settings column width.
396
+ `hs-settings-management` is the separate, right-aligned management footer.
397
+ `hs-menu-position` owns popup placement and its pointer grace area.
398
+ `hs-modal` is a positioned popup root with visible overflow; scrolling belongs
399
+ to its content so menus and help tips stay above the dialog without clipping.
400
+
401
+ `hs-selection-dialog`, `hs-selection-dialog-body`, `hs-selection-list`,
402
+ `hs-selection-option`, `hs-selection-icon`, `hs-selection-name`,
403
+ `hs-selection-description` and `hs-selection-error` style `SelectionDialog`.
404
+
405
+ Documentation images use `hs-docs-image` inside `hs-docs-image-link`, which
406
+ opens the original image at full size. `hs-docs-figure` groups the image and
407
+ its semantic `figcaption`. Figures inherit the current theme and maintain
408
+ their own spacing within the article.
409
+
410
+ Model management: `hs-model-library-*` styles library rows, facts, state and
411
+ hover actions; `.hs-model-hover-action` becomes visible on row hover or focus.
412
+ `hs-settings-tabs` uses `aria-selected` to paint its active glass button.
413
+ `hs-settings-breadcrumbs` and `hs-settings-crumb*` name inner-window locations.
414
+ Compact controls use `hs-settings-input`, `hs-settings-file` and
415
+ `hs-settings-textarea`. Model settings use
416
+ `hs-model-settings-*`; runtime controls use `hs-model-runtime-*`; downloads use
417
+ `hs-model-download*`, and a companion picker's label and repository field
418
+ `hs-model-companion-*`; generated image/audio previews use `hs-model-media-output`.
419
+ `hs-model-error` carries inline request failures. These selectors live in
420
+ `src/shell.css` and read the shared theme tokens.
421
+
422
+ `hs-model-runtime-row`, `hs-model-runtime-header`, `hs-model-runtime-label`,
423
+ `hs-model-runtime-status`, `hs-model-runtime-controls` and
424
+ `hs-model-runtime-control` style `ModelRuntimeRow`. Its container query stacks
425
+ the controls below a 470px card width without changing other settings layouts.
426
+
427
+ - `.hs-sidebar-action` — the full-width shared sidebar action (`SidebarAction`).
428
+ - `.hs-model-fit` — memory fit estimate with explanatory tooltip; `data-fit`
429
+ selects `full`, `partial`, `unlikely` or `unknown`; `data-variant` selects
430
+ `badge` or the noninteractive `icon` at the right of a menu row. A Server's
431
+ memory plan of a load (`ModelMemory`) is the `icon` variant with its figure,
432
+ `unknown` when the load can start now and `unlikely` when it cannot.
433
+ - `.hs-model-execution` — elapsed time and determinate/indeterminate progress.
434
+ - `.hs-server-log` — selectable bounded technical event viewer.
435
+ - `.hs-panel-start-heading` — the launcher's heading over the surfaces other apps
436
+ place in a tab ("From other apps").
437
+ - `.hs-launcher-address` — the launcher's address field, as wide as its rows.
438
+ - `.hs-panel-unavailable` — the sentence a tab shows when its app no longer places
439
+ the surface in a tab.
440
+ - `.hs-tab-dot` — the mark on a tab an agent drives.
441
+ - `.hs-panel-favicon` — a tab's own picture in the tab strip: a page's icon, or the mark a
442
+ view gave its tab.
443
+ - `.hs-browser-page-slot` — the place a browser's view keeps for its web page.
444
+ - `.hs-settings-plate` — the 52px plate beside an app's name on its settings page.
445
+ - `.hs-connector-unattached` — the words on a connector's row while no app has it attached.
446
+ - `.hs-skill-text` — a skill's own text on its settings page.
447
+ - `.hs-key-control` — a shortcut's controls on the Keybindings page: `.hs-key-binding`,
448
+ the press that holds its key and starts the recorder (`data-set` is `false` for a
449
+ shortcut not set), `.hs-key-record`, the recorder, and `.hs-key-remove`, the remove
450
+ mark; `.hs-key-clash` is the line that names a key another shortcut holds.
451
+ - `.hs-provider-title` — a provider's name behind its mark; `.hs-provider-offer` and
452
+ `.hs-provider-offer-name`, a computer on the account the Providers page offers to add,
453
+ and its name.
454
+
455
+ ## Breaks
456
+
457
+ Removed or renamed classes, with what replaces them:
458
+
459
+ | Class | Now |
460
+ | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
461
+ | `hs-daemon-bar`, `hs-daemon-bar-text`, `hs-daemon-bar-action` | `hs-window-notice`, `hs-window-notice-text`, `hs-button` |
462
+ | `hs-confirm-button` | `hs-button` with `hs-confirm-cancel` or `hs-confirm-action` |
463
+ | `hs-appearance-row`, `hs-appearance-label`, `hs-appearance-value` | `hs-setrow` with `hs-range-value` |
464
+ | `hs-mono-label` | `hs-label`, or `hs-mono` for machine text |
465
+ | `hs-theme-author` | `hs-label` |
466
+ | `hs-gold-text` | `hs-link` |
467
+ | `hs-gold-glyph` | the solid kind of `hs-ladder-rung` |
468
+ | `hs-gold-action-button` | `hs-link` |
469
+ | `hs-utilbtn`, `hs-utility-button` | `hs-ladder-rung` |
470
+ | `hs-titlebar-center`, `hs-titlebar-divider`, `data-overlay` on `hs-titlebar` | `hs-rail-top`; nothing; `hs-lane` with `data-caption` |
471
+ | `hs-app-picker` | `hs-lane-crumb` |
472
+ | `hs-crow` | `hs-window-tiles` |
473
+ | `hs-sidebar-empty` | `hs-empty-view` |
474
+ | `hs-sidebar-footer`, `hs-sidebar-lift`, `data-slide` and `data-lifted` on `hs-app-block` | `hs-sidebar-rail-market`; nothing; nothing |
475
+ | `hs-artifact-card` | nothing |
476
+ | `hs-tool-row`, `hs-tool-line`, `hs-tool-details` | `hs-work-row`, `hs-work-line`, `hs-work-body` |
477
+ | `hs-work` | `hs-work-line`, `hs-work-toggle` |
478
+ | `hs-described-image` | `hs-user-tile` and `hs-user-caption` |
479
+ | `hs-chat-date` | `hs-thread-mark` |
480
+ | `hs-selection-controls` | nothing |
481
+ | `hs-chat-composer`, `hs-composer-input`, `hs-composer-toolbar`, `hs-composer-attach` | `hs-composer-main`, `hs-composer-editor`, `hs-composer-footer`, `hs-composer-tool` |
482
+ | `hs-composer-files`, `hs-composer-glimmer`, `hs-composer-disabled` | `hs-composer-shelf`; nothing; a disabled `hs-composer-send` |
483
+ | `hs-card-layer`, `hs-card-app` | `hs-composer-dock` and `hs-ask-float`; `hs-ask-app` |
484
+ | `hs-permission-card` | `hs-ask` |
485
+ | `hs-harness`, `hs-harness-layer`, `hs-harness-text`, `hs-context-meter`, `hs-context-bar` | `hs-ring` and its popover |
486
+ | `hs-side-nav`, `hs-mode-lane`, `data-mode` on `hs-window-wrap` | `hs-page`; nothing; nothing |
487
+ | `hs-settings-home`, `hs-settings-home-mark` | the lane's `hs-lane-crumb` |
488
+ | `hs-settings-crumb`, `hs-settings-crumb-link` | the lane's `hs-lane-crumb` |
489
+ | `hs-nav-footer`, `hs-nav-back`, `hs-nav-rail-back` | the tab's `hs-tab-close` |
490
+ | `hs-toolbar-button` | nothing |
491
+ | `hs-subagents`, `hs-subagent`, `hs-chat-chips`, `hs-suggestion` | `hs-drawer` |
492
+ | `hs-filechip` | `hs-shelf-file`, `hs-shelf-chip`, `hs-inline-chip` |
493
+ | `hs-live`, `hs-shimmer`, `hs-shimmer-hi` | `hs-shine` |
494
+ | `hs-model-label` | `hs-model-trigger-name` |
495
+ | `hs-provider-field` | `hs-input` |
496
+ | `hs-colourway-name-input` | `hs-input` |
497
+ | `data-soon` on `hs-toggle-row` | nothing |
498
+ | `hs-market-lightbox`, `hs-market-lightbox-arrow`, `-close`, `-count` | `hs-lightbox` and its parts |
499
+ | `hs-pulse`, `hs-menu-section-sub` | nothing |
500
+ | `hs-browser-webview` | `hs-browser-page-slot` |
501
+ | `hs-browser-menu-popover`, `hs-browser-site-popover` | `hs-menu-position` (`MenuSurface`) |
502
+ | `hs-realm-slot`, `hs-realm-guest`, `hs-realm-views`, `hs-realm-view`, `hs-panel-app` | nothing: the window draws no app page in a realm |
503
+ | `hs-realm-dock`, `hs-realm-mark` | nothing |
504
+ | `hs-view-slot`, `hs-realm-chat` | nothing: no chat draws in an app's document |
505
+ | `hs-browser-pages`, `hs-browser-page` | `hs-tab-page` of a view's tab, `hs-web-page` of a web surface |
506
+ | `hs-panel-view-slot`, `hs-panel-action`, `hs-file-guest`, `hs-changed-show` | nothing: the window draws no Files, Diff, Terminal or browser tab of its own |
507
+ | `hs-app-bypass` | nothing |