8.2 KiB
Hosts v5 design import — spec and decisions
Source: Claude Design project DodoSSH, file Hosts.dc.html (1920x1080 desktop mock).
This file holds (a) the agreed decisions, (b) the palette mapping, (c) the raw design HTML at the bottom.
Agreed decisions (user-approved)
- Full re-theme: swap the shared palette (
src/DodoSSH.Client.Shell/Theme/Palette.axaml) to the new purple/near-black scheme — both heads recolor together. Embed Montserrat + JetBrains Mono + Material Icons font files in the desktop head. Android keeps its default sans (fonts are per-head; only colors are shared by decision);MonoFontgains JetBrains Mono at the front of its fallback list. - Flat sections: the desktop hosts screen becomes one collapsible section per group (nesting
flattened into one heading per group in label order, exactly like the phone's
SidebarRows), ungrouped hosts under "No group" first. Per-section collapse + Collapse All. Group cards and the breadcrumb trail leave this screen. Group edit/move/delete move to a menu on the section heading. Collapse state is in-memory only (settings.json stays two scalars by decision). - Pinned folders (QUICK ACCESS): full feature.
HostSecret.PinnedPaths(ordered strings, per-path three-way merge likeTagIds), drawer editor section, pin-count badge on cards, and a chip strip above the terminal for the connected host; clicking a pin opens the SFTP tab with the remote pane at that path (a second authenticated connection, as SFTP always is here). - Last connected: computed from the synced connection log (
max(StartedAt)perHostId) on hosts-screen activation and onSessionEnded; relative time ("just now" / "N min ago" / hours/days), restrung on a 1-minute tick while visible, no background re-read.
Deliberate deviations from the mock (do NOT implement the mock literally on these)
- Relay checkbox copy keeps the honest wording including "(not wired up yet)" — the design copy implies a working relay; the client dial path does not exist yet. Keep the current sentence structure in HostDrawer.axaml:516-535.
- Status dot stays two states (green = terminal open, grey = not). The design's amber has no truthful meaning; nothing probes hosts.
- Card click selects (multi-select depends on it), double-click connects, pencil opens the detail pane. The mock's card-as-link-to-terminal is not adopted.
- Quick connect keeps the auth word (credential/key/password) instead of the mock's SSH/SFTP kind column — every palette connect is SSH, and a constant printed as a reading is refused in this repo.
- Find box stays (restyled) — it is the only search that crosses group boundaries.
- "New group…" moves to the foot of the Group ▼ filter flyout (the mock has no group-creation control).
- The QUICK ACCESS hint sentence ships as what is true: "Pinned folders appear above the terminal for this host." (no "sidebar" claim).
Palette mapping (design rgb → Palette.axaml key)
| Key | Old | New |
|---|---|---|
| CanvasColor | #0E1220 | #05050A (design body rgb(5,5,10)) |
| Chrome | #111629 | #10111E (window rgb(16,17,30)) |
| Sidebar | #0F1426 | #0D0D16 (drawer rgb(13,13,22)) |
| Panel | #111629 | #10111E |
| Raised | #151B31 | #101019 (card rgb(16,16,25)) |
| Field | #0B0F1D | #101019 (inputs rgb(16,16,25)) |
| Chip | #16204A | #1A1A28 (rgb(26,26,40)) |
| Hover/Active/ChromeHover | — | derive slightly lighter than their surfaces, e.g. Hover #14151E, Active #1E1E2C, ChromeHover #1E1E2C |
| Border | #1A2138 | #1E1E2C (rgb(30,30,44)) |
| BorderMid | #232B45 | #24243A (rgb(36,36,58)) |
| BorderHover | #2E3859 | #2C2C3E (rgb(44,44,62)) |
| BorderSubtle/BorderFaint | — | keep one step darker than Border, e.g. #17172", use judgment |
| Text | #FFFFFF | #FFFFFF |
| TextDim | #B4BCD4 | #EDEDF5 (rgb(237,237,245)) |
| TextFaint | #7B849F | #9C9EB4 (rgb(156,158,180)) |
| TextGhost | #5A6280 | #7C7F98 (rgb(124,127,152)); the design also uses #6D6F84 and #5D5F74 for deeper steps — add keys only if needed |
| AccentColor | #5B8CFF | #5D42DE (rgb(93,66,222)) |
| AccentText | #8FA7FF | #A78BFA |
| AccentInk | #0E1220 | #FFFFFF (text on accent is white in this design) |
| AccentSoft/AccentWash | 0.35/0.06 | same opacities over #5D42DE |
| NEW: AccentGradient | — | LinearGradientBrush 180deg #8D51E7 → #5D42DE |
| NEW: AccentGlow | — | for BoxShadow use: 0 0 22 0 #8D51E7 at ~35% alpha |
| Live | #3DDC97 | #34D399 (rgb(52,211,153) — the design's own green) |
| Warn | #FFB454 | #F59E0B (rgb(245,158,11)); WarnText #F5B942 |
| Danger | #E86A6A | keep |
Radii: cards 12, controls 10, small chips 5-6. Field/control height 40. Primary buttons use AccentGradient + glow.
Monogram avatar hue pairs (bg/fg), assigned by stable hash of host label: violet #241C4F/#A78BFA · green #103A2F/#34D399 · amber #423211/#F5B942 · gray #1E1E2C/#9C9EB4.
Raw design HTML (Hosts.dc.html)
The <sc-for>/{{ }} bits are the design tool's templating; style-hover is a hover style.
Sample data lives in the script block at the bottom.
<div data-screen-label="Hosts" style="width:1920px;height:1080px;...background:rgb(16,17,30);...">
<dc-import name="TitleBar" on-search="{{ openQuickConnect }}" hint-size="100%,53px"></dc-import>
<div style="display:flex;flex-direction:row;flex-grow:1;min-height:0;">
<dc-import name="NavRail" active="hosts" mode="ssh" hint-size="255px,100%"></dc-import>
<div style="flex-grow:1;...padding:34px 36px;...">
<!-- Header row: title + count chip | Group ▼, Tag ▼, + New host -->
<span style="font-weight:700;font-size:33px;letter-spacing:-0.5px;color:#fff;">Hosts</span>
<div style="width:34px;height:30px;border-radius:9px;background:rgb(26,26,40);">10</div>
<!-- Group / Tag: h40, radius 10, inset 1px rgb(44,44,62) border, hover border accent -->
<!-- + New host: h40, radius 10, AccentGradient, glow, white 13.5 semibold -->
<!-- Section heading row (margin 32 0 16): "No group · 6" 12.5 medium rgb(124,127,152)
right side: collapse icon + "Collapse All" / "Collapse" 12 medium rgb(93,95,116) -->
<!-- Host grid: 3 columns, gap 14 -->
<!-- Host card: h120, radius 12, bg rgb(16,16,25), inset 1px rgb(30,30,44), hover border accent
- avatar 32x32 radius 9 at 21,20 with 2-letter mono bold 12.5 monogram
- name 17 bold white + 9px status dot, at 68,18
- addr mono 12.5 rgb(109,111,132) + pin badge (h19 radius 5 bg rgb(26,26,40),
push_pin icon 11 + count 10.5) at 68,39
- tag chips bottom-left (h21 radius 5 bg rgb(30,30,44), 11 medium rgb(156,158,180))
- ago text bottom-right 12 rgb(93,95,116) -->
</div>
<!-- Drawer (sc-if drawerOpen): w320, bg rgb(13,13,22), border-left rgb(26,26,40), padding 24 22
- "New host" 20 bold; subtitle "Saving to **DodoTech ▾** vault" 12.5
- section labels: 10px semibold letter-spacing 1.2 rgb(93,95,116): ADDRESS / GENERAL / CONNECTION / QUICK ACCESS
- ADDRESS: h42 radius 10 field with accent 1.5px inset border, ">_" prefix, mono value, blinking caret
- GENERAL: Name field h40; group dropdown ("No group" + expand_more); Add tag field + 40x40 add button; Notes h58
- CONNECTION: Username field + w78 port field ("22" mono) on one row; auth dropdown
("Password (ask each time)" + expand_more); relay checkbox card (radius 12, 18x18 checkbox,
title 13 semibold + body 11.5 rgb(124,127,152))
- QUICK ACCESS: per pin: h33 radius 9 row, folder icon + mono path 12.5 + close ✕;
add row: mono field "/path/to/folder" + 36x36 add button;
hint 11.5 rgb(93,95,116)
- footer: Save host (flex-grow, h44, AccentGradient + glow) + Cancel (w92 h44 ghost) -->
<!-- Quick connect (sc-if quickConnectOpen): full-window scrim rgba(5,5,10,0.6) + blur(3px),
card w640 radius 14 bg rgb(16,17,30) top-offset 160
- header row: ">_" accent mono + mono input "deploy@" + caret + "↵ connect · esc close"
- rows h44 radius 9: status dot 8px, name mono 13, addr mono 11.5, kind right
(selected row bg rgb(93,66,222), texts white) -->
</div>
</div>
Sample data (for tone, not to be shipped): hosts like prod-api-01 / deploy@203.0.113.14 / pins 4 / tags production,api / 2 min ago; pinned = /var/www/app, /etc/nginx, /var/log/pm2.