feat(ui): clarification des contrôles d'en-tête DockControls (#42)
Refinement UX suite #26 : clarifie les contrôles DockControls dans l'en-tête des panneaux. Frontend-pur. QA vert : tsc --noEmit exit 0, vitest 62 fichiers / 616 tests passés. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -40,9 +40,11 @@ import {
|
||||
Button,
|
||||
DockRegion,
|
||||
FloatingWindow,
|
||||
IconButton,
|
||||
Input,
|
||||
MenuBar,
|
||||
Panel,
|
||||
cn,
|
||||
zIndex,
|
||||
type FloatingWindowSize,
|
||||
type MenuBarItem,
|
||||
@ -469,58 +471,72 @@ export function ProjectsView() {
|
||||
const rightPanels = panelsDockedTo(placements, "right");
|
||||
const floatingList = floatingPanels(placements);
|
||||
|
||||
// Placement toggle buttons for a view's header — the "flottant ↔ ancré
|
||||
// (gauche/droite)" control from the contract. The button for the current slot
|
||||
// is disabled so the active placement reads at a glance.
|
||||
// Placement controls for a view's header — labelled icon-buttons aligned 1:1
|
||||
// with the « Panneaux » menu wording (#42). Order: ⇤ gauche · ⇥ droite · □
|
||||
// flottant · ↗ fenêtre détachée · × fermé. The *current* placement reads as
|
||||
// ACTIVE (aria-pressed + ring), never disabled — a disabled control loses its
|
||||
// tooltip/keyboard focus and conflates "impossible" with "already selected".
|
||||
// Only genuinely-impossible actions are disabled (detach with no active
|
||||
// project). All labelling flows through `title` + `aria-label`; no visible
|
||||
// text. The detach control is hidden for the main-window-only `projects` view.
|
||||
function DockControls({ panel }: { panel: PanelId }) {
|
||||
const placement = placementOf(placements, panel);
|
||||
const title = PANEL_TITLE[panel];
|
||||
// Active (current-placement) styling — visually distinct, still clickable.
|
||||
const activeClass = "bg-raised text-content ring-1 ring-border-strong";
|
||||
return (
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
<Button
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={`dock ${title} left`}
|
||||
disabled={isDockedTo(placement, "left")}
|
||||
title="Ancré à gauche"
|
||||
aria-label={`Ancré à gauche — ${title}`}
|
||||
aria-pressed={isDockedTo(placement, "left")}
|
||||
className={cn(isDockedTo(placement, "left") && activeClass)}
|
||||
onClick={() => setPlacement(panel, { dock: "left" })}
|
||||
>
|
||||
◧
|
||||
</Button>
|
||||
<Button
|
||||
⇤
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={`dock ${title} right`}
|
||||
disabled={isDockedTo(placement, "right")}
|
||||
title="Ancré à droite"
|
||||
aria-label={`Ancré à droite — ${title}`}
|
||||
aria-pressed={isDockedTo(placement, "right")}
|
||||
className={cn(isDockedTo(placement, "right") && activeClass)}
|
||||
onClick={() => setPlacement(panel, { dock: "right" })}
|
||||
>
|
||||
◨
|
||||
</Button>
|
||||
<Button
|
||||
⇥
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={`float ${title}`}
|
||||
disabled={placement === "floating"}
|
||||
title="Flottant"
|
||||
aria-label={`Flottant — ${title}`}
|
||||
aria-pressed={placement === "floating"}
|
||||
className={cn(placement === "floating" && activeClass)}
|
||||
onClick={() => setPlacement(panel, "floating")}
|
||||
>
|
||||
⧉
|
||||
</Button>
|
||||
<Button
|
||||
□
|
||||
</IconButton>
|
||||
{panel !== "projects" && (
|
||||
<IconButton
|
||||
size="sm"
|
||||
title="Fenêtre détachée"
|
||||
aria-label={`Fenêtre détachée — ${title}`}
|
||||
aria-pressed={isDetached(placement)}
|
||||
disabled={!active}
|
||||
className={cn(isDetached(placement) && activeClass)}
|
||||
onClick={() => detachPanel(panel)}
|
||||
>
|
||||
↗
|
||||
</IconButton>
|
||||
)}
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={`open ${title} in new window`}
|
||||
disabled={!active || isDetached(placement)}
|
||||
onClick={() => detachPanel(panel)}
|
||||
>
|
||||
⤢
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={`close ${title}`}
|
||||
title="Fermé"
|
||||
aria-label={`Fermé — ${title}`}
|
||||
onClick={() => closePanel(panel)}
|
||||
>
|
||||
✕
|
||||
</Button>
|
||||
×
|
||||
</IconButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user