mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
refactor(web): replace entry global header with sidebar brand + reorder bottom chips
Pre-existing layout: a global \`AppChromeHeader\` strip sat across the
whole top of EntryView (logo + settings gear), then a 2-column body
below it. Visual mass concentrated in a thin horizontal bar that did
not relate to the page's column structure, and the settings gear
duplicated the bottom Local-CLI chip.
New layout matches the two-column "brand-in-sidebar + tabs-in-main"
pattern: the brand block lives at the top of \`.entry-side\` (left
column), the right tabs live at the top of \`.entry-main\`, and the
vertical divider between them is the only horizontal seam.
EntryView:
- Drop \`<AppChromeHeader actions={avatarMenu} />\` from EntryView's
render — the home page no longer renders the global chrome strip.
(ProjectView still uses AppChromeHeader for back-nav / file
actions, so the component itself stays in the codebase.)
- Add a sidebar brand block inside \`.entry-side\` using the
already-defined \`.entry-brand\` / \`.entry-brand-mark\` /
\`.entry-brand-title\` classes that were sitting dead in
index.css.
- Reorder \`.entry-side-foot\` chips so that the env-critical
Local CLI row sits on top of the row, with the secondary
toggles (language picker, pet adoption, X follow icon) compact
on a second row. The Follow @nexudotio chip drops its text
label and becomes icon-only — pure marketing content, so it no
longer earns a full-width pill.
- Settings access moves entirely to the Local CLI chip's existing
click handler; the top-right gear is gone (it was a duplicate).
CSS:
- \`.entry-shell\` grid: \`auto 1fr\` → \`1fr\` (no header row).
- \`.entry-side\` background: \`var(--bg-panel)\` → \`transparent\`,
so the sidebar shares the page beige and only the New-prototype
card reads as white. Removes the "everything on the left is on
one big white sheet" feeling.
- \`.entry-brand\` gets \`padding: 24px 20px 18px\` so the logo +
title block has breathing room at the top of the sidebar.
- \`.entry-brand-mark\` width/height \`44 → 34\`. The previous
44px gradient ring was visually heavier than the title text it
sat next to.
- \`.entry-brand-title\` weight \`600 → 450\`, color
\`var(--text-strong)\` → \`var(--text)\`. Serif title still
reads as the page anchor without the chunky "bold black" stamp.
- \`.entry-brand-actions\` added for future right-aligned actions
(carries no actual content in this commit — kept so re-adding a
settings/avatar entry point doesn't need new CSS).
- \`.entry-side-foot .foot-pill\` slim pass: padding
\`4px 10px → 3px 8px\`, font \`11.5px → 10.5px\`, gap \`6 → 5\`,
plus \`justify-content: center\` and \`min-height: 24px\` so the
icon-only Follow pill stays the same height as the text pills
next to it.
This commit is contained in:
@@ -469,7 +469,6 @@ export function EntryView({
|
||||
|
||||
return (
|
||||
<div className="entry-shell">
|
||||
<AppChromeHeader actions={avatarMenu} />
|
||||
<div
|
||||
className={`entry${petRailHidden ? '' : ' has-pet-rail'}`}
|
||||
style={{
|
||||
@@ -479,6 +478,16 @@ export function EntryView({
|
||||
}}
|
||||
>
|
||||
<aside className="entry-side" style={{ width: sidebarWidth }}>
|
||||
<div className="entry-brand">
|
||||
<span className="entry-brand-mark" aria-hidden>
|
||||
<img src="/app-icon.svg" alt="" className="brand-mark-img" draggable={false} />
|
||||
</span>
|
||||
<div className="entry-brand-text">
|
||||
<div className="entry-brand-title-row">
|
||||
<span className="entry-brand-title">{t('app.brand')}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NewProjectPanel
|
||||
skills={skills}
|
||||
designSystems={designSystems}
|
||||
@@ -496,7 +505,26 @@ export function EntryView({
|
||||
loading={skillsLoading || designSystemsLoading}
|
||||
/>
|
||||
<div className="entry-side-foot">
|
||||
<button
|
||||
type="button"
|
||||
className="foot-pill foot-pill-env"
|
||||
onClick={() => onOpenSettings()}
|
||||
aria-label={t('settings.envConfigure')}
|
||||
title={t('settings.envConfigure')}
|
||||
>
|
||||
<Icon name="settings" size={12} />
|
||||
<span>
|
||||
{config.mode === 'daemon'
|
||||
? t('settings.localCli')
|
||||
: apiProtocolLabel(config.apiProtocol)}
|
||||
</span>
|
||||
<span style={{ color: 'var(--text-faint)' }}>·</span>
|
||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 180 }}>
|
||||
{envMetaLine}
|
||||
</span>
|
||||
</button>
|
||||
<div className="entry-side-foot-row">
|
||||
<LanguageMenu />
|
||||
<button
|
||||
type="button"
|
||||
className={`foot-pill pet-pill${config.pet?.adopted ? '' : ' pet-pill-fresh'}`}
|
||||
@@ -530,28 +558,8 @@ export function EntryView({
|
||||
aria-label="Follow @nexudotio on X"
|
||||
>
|
||||
<Icon name="external-link" size={12} />
|
||||
<span className="foot-pill-follow-label">Follow @nexudotio</span>
|
||||
</a>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="foot-pill"
|
||||
onClick={() => onOpenSettings()}
|
||||
aria-label={t('settings.envConfigure')}
|
||||
title={t('settings.envConfigure')}
|
||||
>
|
||||
<Icon name="settings" size={12} />
|
||||
<span>
|
||||
{config.mode === 'daemon'
|
||||
? t('settings.localCli')
|
||||
: apiProtocolLabel(config.apiProtocol)}
|
||||
</span>
|
||||
<span style={{ color: 'var(--text-faint)' }}>·</span>
|
||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 180 }}>
|
||||
{envMetaLine}
|
||||
</span>
|
||||
</button>
|
||||
<LanguageMenu />
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
+17
-9
@@ -3656,7 +3656,7 @@ code {
|
||||
============================================================ */
|
||||
.entry-shell {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
height: 100vh;
|
||||
min-height: 0;
|
||||
background: var(--bg);
|
||||
@@ -3672,7 +3672,7 @@ code {
|
||||
|
||||
.entry-side {
|
||||
border-right: 1px solid var(--border);
|
||||
background: var(--bg-panel);
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -3681,10 +3681,16 @@ code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 24px 20px 18px;
|
||||
}
|
||||
.entry-brand-actions {
|
||||
margin-left: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.entry-brand-mark {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--accent-tint) 0%, var(--accent-soft) 100%);
|
||||
color: var(--accent);
|
||||
@@ -3711,11 +3717,11 @@ code {
|
||||
}
|
||||
.entry-brand-title {
|
||||
font-family: var(--serif);
|
||||
font-weight: 600;
|
||||
font-weight: 450;
|
||||
font-size: 22px;
|
||||
letter-spacing: -0.015em;
|
||||
line-height: 1;
|
||||
color: var(--text-strong);
|
||||
color: var(--text);
|
||||
}
|
||||
.entry-brand-pill {
|
||||
font-size: 10.5px;
|
||||
@@ -4792,12 +4798,14 @@ code {
|
||||
.entry-side-foot .foot-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 10px;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
padding: 3px 8px;
|
||||
min-height: 24px;
|
||||
background: var(--bg-subtle);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-pill);
|
||||
font-size: 11.5px;
|
||||
font-size: 10.5px;
|
||||
color: var(--text-muted);
|
||||
align-self: flex-start;
|
||||
cursor: pointer;
|
||||
|
||||
Reference in New Issue
Block a user