Skip to content

Commit 8987534

Browse files
authored
(hub-client) re-organise titlebar (#273)
* Re-organise titlebar * Fix indicator height
1 parent 746d8d7 commit 8987534

4 files changed

Lines changed: 198 additions & 95 deletions

File tree

hub-client/src/components/MinimalHeader.css

Lines changed: 89 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
display: flex;
33
align-items: center;
44
justify-content: space-between;
5-
padding: 8px 16px;
5+
padding: 6px 12px;
66
background: var(--editor-header-bg);
77
border-bottom: 1px solid var(--editor-header-border);
88
min-height: 36px;
@@ -14,16 +14,97 @@
1414
min-width: 0;
1515
display: flex;
1616
align-items: center;
17-
gap: 12px;
17+
gap: 6px;
18+
}
19+
20+
/* Shared icon action button (switch / share / preview). */
21+
.minimal-header .icon-btn {
22+
display: flex;
23+
align-items: center;
24+
justify-content: center;
25+
width: 28px;
26+
height: 28px;
27+
padding: 0;
28+
background: none;
29+
border: 1px solid transparent;
30+
border-radius: 6px;
31+
color: var(--editor-text-muted);
32+
cursor: pointer;
33+
flex-shrink: 0;
34+
transition: background 0.15s, color 0.15s, border-color 0.15s;
35+
}
36+
37+
.minimal-header .icon-btn:hover {
38+
background: var(--view-toggle-hover-bg);
39+
color: var(--editor-text);
40+
}
41+
42+
/* Preview is the primary action: filled accent pill with icon + label. */
43+
.minimal-header .preview-btn {
44+
display: flex;
45+
align-items: center;
46+
gap: 6px;
47+
height: 28px;
48+
padding: 0 12px;
49+
background: var(--header-preview-bg);
50+
border: 1px solid var(--header-preview-bg);
51+
border-radius: 6px;
52+
color: var(--header-preview-text);
53+
font-size: 13px;
54+
font-weight: 600;
55+
cursor: pointer;
56+
flex-shrink: 0;
57+
transition: background 0.15s, border-color 0.15s;
58+
}
59+
60+
.minimal-header .preview-btn:hover {
61+
background: var(--header-preview-hover);
62+
border-color: var(--header-preview-hover);
63+
}
64+
65+
/* Vertical divider separating the actions from the document identity. */
66+
.header-divider {
67+
width: 1px;
68+
align-self: stretch;
69+
margin: 4px 2px;
70+
background: var(--editor-header-border);
71+
flex-shrink: 0;
72+
}
73+
74+
/* Document identity: project name / file path. */
75+
.header-doc {
76+
display: flex;
77+
align-items: baseline;
78+
gap: 8px;
79+
min-width: 0;
80+
overflow: hidden;
81+
}
82+
83+
.header-doc .project-name {
84+
font-size: 13px;
85+
font-weight: 600;
86+
color: var(--editor-text);
87+
white-space: nowrap;
88+
flex-shrink: 0;
89+
}
90+
91+
.header-doc .path-sep {
92+
color: var(--editor-text-muted);
93+
font-size: 13px;
94+
flex-shrink: 0;
1895
}
1996

20-
.minimal-header .file-path {
97+
.header-doc .file-path {
2198
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
2299
font-size: 13px;
23100
color: var(--editor-text-dim);
101+
white-space: nowrap;
102+
overflow: hidden;
103+
text-overflow: ellipsis;
104+
min-width: 0;
24105
}
25106

26-
.minimal-header .file-path.empty {
107+
.header-doc .file-path.empty {
27108
color: var(--editor-text-muted);
28109
font-style: italic;
29110
}
@@ -39,11 +120,14 @@
39120
display: flex;
40121
align-items: center;
41122
gap: 6px;
42-
padding: 4px 10px;
123+
box-sizing: border-box;
124+
height: 28px;
125+
padding: 0 10px;
43126
background: var(--editor-header-bg);
44127
border: 1px solid var(--editor-disconnected-border);
45128
border-radius: 4px;
46129
font-size: 12px;
130+
line-height: 1;
47131
user-select: none;
48132
}
49133

@@ -77,71 +161,3 @@
77161
color: var(--editor-text-dim);
78162
font-weight: 500;
79163
}
80-
81-
.header-right .project-name {
82-
font-size: 13px;
83-
font-weight: 500;
84-
color: var(--editor-text-muted);
85-
min-width: 120px;
86-
max-width: 400px;
87-
overflow: hidden;
88-
text-overflow: ellipsis;
89-
white-space: nowrap;
90-
text-align: right;
91-
}
92-
93-
.header-right .preview-btn {
94-
padding: 6px 16px;
95-
background: var(--header-preview-bg);
96-
border: 2px solid var(--header-preview-bg);
97-
border-radius: 6px;
98-
color: var(--header-preview-text);
99-
font-size: 14px;
100-
font-weight: 600;
101-
cursor: pointer;
102-
transition: all 0.15s;
103-
box-shadow: 0 2px 8px var(--header-preview-shadow);
104-
}
105-
106-
.header-right .preview-btn:hover {
107-
background: var(--header-preview-hover);
108-
border-color: var(--header-preview-hover);
109-
transform: translateY(-1px);
110-
box-shadow: 0 4px 12px var(--header-preview-shadow-hover);
111-
}
112-
113-
.header-right .preview-btn:active {
114-
transform: translateY(0);
115-
}
116-
117-
.header-right .choose-project-btn {
118-
padding: 4px 10px;
119-
background: none;
120-
border: 1px solid var(--editor-disconnected-border);
121-
border-radius: 4px;
122-
color: var(--editor-text-muted);
123-
font-size: 12px;
124-
cursor: pointer;
125-
transition: all 0.15s;
126-
}
127-
128-
.header-right .choose-project-btn:hover {
129-
border-color: var(--sidebar-active-accent);
130-
color: var(--sidebar-active-accent);
131-
}
132-
133-
.header-right .share-btn {
134-
padding: 4px 10px;
135-
background: var(--header-share-bg);
136-
border: 1px solid var(--header-share-bg);
137-
border-radius: 4px;
138-
color: #fff;
139-
font-size: 12px;
140-
cursor: pointer;
141-
transition: all 0.15s;
142-
}
143-
144-
.header-right .share-btn:hover {
145-
background: var(--header-share-hover);
146-
border-color: var(--header-share-hover);
147-
}

hub-client/src/components/MinimalHeader.tsx

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
22
* Minimal Header Component
33
*
4-
* A slim header bar that displays the current file path on the left
5-
* and project name with navigation on the right.
4+
* Slim header bar. Left: switch/share actions + project / file identity.
5+
* Right: online status, layout toggle, fullscreen-preview action.
66
*/
77

88
import ViewToggleControl from './ViewToggleControl';
@@ -20,6 +20,73 @@ interface MinimalHeaderProps {
2020
isOnline?: boolean;
2121
}
2222

23+
/** Grid of four squares — "switch / all projects". */
24+
function SwitchIcon() {
25+
return (
26+
<svg
27+
width="16"
28+
height="16"
29+
viewBox="0 0 24 24"
30+
fill="none"
31+
stroke="currentColor"
32+
strokeWidth="2"
33+
strokeLinecap="round"
34+
strokeLinejoin="round"
35+
aria-hidden="true"
36+
>
37+
<rect x="3" y="3" width="7" height="7" rx="1" />
38+
<rect x="14" y="3" width="7" height="7" rx="1" />
39+
<rect x="3" y="14" width="7" height="7" rx="1" />
40+
<rect x="14" y="14" width="7" height="7" rx="1" />
41+
</svg>
42+
);
43+
}
44+
45+
/** Connected nodes — "share". */
46+
function ShareIcon() {
47+
return (
48+
<svg
49+
width="16"
50+
height="16"
51+
viewBox="0 0 24 24"
52+
fill="none"
53+
stroke="currentColor"
54+
strokeWidth="2"
55+
strokeLinecap="round"
56+
strokeLinejoin="round"
57+
aria-hidden="true"
58+
>
59+
<circle cx="18" cy="5" r="3" />
60+
<circle cx="6" cy="12" r="3" />
61+
<circle cx="18" cy="19" r="3" />
62+
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />
63+
<line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
64+
</svg>
65+
);
66+
}
67+
68+
/** Outward corners — "fullscreen preview". */
69+
function PreviewIcon() {
70+
return (
71+
<svg
72+
width="16"
73+
height="16"
74+
viewBox="0 0 24 24"
75+
fill="none"
76+
stroke="currentColor"
77+
strokeWidth="2"
78+
strokeLinecap="round"
79+
strokeLinejoin="round"
80+
aria-hidden="true"
81+
>
82+
<path d="M8 3H5a2 2 0 0 0-2 2v3" />
83+
<path d="M21 8V5a2 2 0 0 0-2-2h-3" />
84+
<path d="M3 16v3a2 2 0 0 0 2 2h3" />
85+
<path d="M16 21h3a2 2 0 0 0 2-2v-3" />
86+
</svg>
87+
);
88+
}
89+
2390
export default function MinimalHeader({
2491
currentFilePath,
2592
projectName,
@@ -32,12 +99,34 @@ export default function MinimalHeader({
3299
return (
33100
<header className="minimal-header">
34101
<div className="header-left">
35-
<ViewToggleControl />
36-
{currentFilePath ? (
37-
<span className="file-path">{currentFilePath}</span>
38-
) : (
39-
<span className="file-path empty">No file selected</span>
102+
<button
103+
className="icon-btn"
104+
onClick={onChooseNewProject}
105+
title="Switch project"
106+
aria-label="Switch project"
107+
>
108+
<SwitchIcon />
109+
</button>
110+
{onShare && (
111+
<button
112+
className="icon-btn"
113+
onClick={onShare}
114+
title="Share this project"
115+
aria-label="Share this project"
116+
>
117+
<ShareIcon />
118+
</button>
40119
)}
120+
<span className="header-divider" aria-hidden="true" />
121+
<div className="header-doc">
122+
<span className="project-name">{projectName}</span>
123+
<span className="path-sep" aria-hidden="true">
124+
|
125+
</span>
126+
<span className={`file-path${currentFilePath ? '' : ' empty'}`}>
127+
{currentFilePath ?? 'No file selected'}
128+
</span>
129+
</div>
41130
</div>
42131
<div className="header-right">
43132
<div
@@ -51,20 +140,18 @@ export default function MinimalHeader({
51140
<span className="connection-dot" />
52141
<span className="connection-text">{isOnline ? 'Online' : 'Offline'}</span>
53142
</div>
54-
<span className="project-name">{projectName}</span>
55-
{onShare && (
56-
<button className="share-btn" onClick={onShare} title="Share this project">
57-
Share
58-
</button>
59-
)}
143+
<ViewToggleControl />
60144
{onToggleFullscreenPreview && !isFullscreenPreview && (
61-
<button className="preview-btn" onClick={onToggleFullscreenPreview}>
62-
Preview
145+
<button
146+
className="preview-btn"
147+
onClick={onToggleFullscreenPreview}
148+
title="Fullscreen preview"
149+
aria-label="Fullscreen preview"
150+
>
151+
<PreviewIcon />
152+
<span>Preview</span>
63153
</button>
64154
)}
65-
<button className="choose-project-btn" onClick={onChooseNewProject}>
66-
Switch
67-
</button>
68155
</div>
69156
</header>
70157
);

hub-client/src/components/ViewToggleControl.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useViewMode } from './ViewModeContext';
22
import './ViewToggleControl.css';
33

44
/**
5-
* Compact horizontal view toggle at the top of the sidebar.
5+
* Compact horizontal view toggle in the header.
66
* Three small square buttons with layout-split icons.
77
*/
88
export default function ViewToggleControl() {

hub-client/src/theme.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,9 @@
281281
--replay-tooltip-bg: #0f0f1e;
282282

283283
/* Minimal header */
284-
--header-preview-bg: #ffffff;
285-
--header-preview-text: #1e3a8a;
286-
--header-preview-hover: #f0f0f0;
284+
--header-preview-bg: var(--posit-blue);
285+
--header-preview-text: #ffffff;
286+
--header-preview-hover: var(--posit-blue-dark-1);
287287
--header-preview-shadow: rgba(255, 255, 255, 0.3);
288288
--header-preview-shadow-hover: rgba(255, 255, 255, 0.4);
289289
--header-share-bg: #646cff;

0 commit comments

Comments
 (0)