refactor(ux): address /code-review high findings on the fixpack

- Extract the optimistic + debounced-flush feed-priority flow into a shared
  useChannelPriority hook (mirrors useChannelTagActions); the manager and the
  channel-detail page now share it instead of two drifting copies.
- NavSidebar: drop the always-true `slim` const and its dead expanded-rail
  branches; refresh the now-stale pinned/collapsible comments.
- Remove the orphaned `navCollapsed` localStorage key (no readers/writers left
  after the always-slim rail).
- Channel page: drop the wrapper native `title` that duplicated PriorityStepper's
  own Tooltip.

The keyboard-focus nav-label finding needed no change: the popover platform
already wires useFocus (visibleOnly), so a real Tab press shows the flyout label
(verified in-browser).
This commit is contained in:
2026-08-11 03:29:08 +02:00
parent 71bbf35f5a
commit 02754f479f
5 changed files with 123 additions and 123 deletions
+12 -27
View File
@@ -17,9 +17,9 @@ import Tooltip from "./Tooltip";
import LanguageSwitcher from "./LanguageSwitcher";
import { PopoverSurface, useAnchoredPopover } from "./AnchoredPopover";
// Primary app navigation: a collapsible left rail with icon+label entries (Design C). The
// modules used to hide under the avatar dropdown; they now live here. Collapsed, it becomes
// a thin icon-only rail. Account actions sit at the bottom in a popover.
// Primary app navigation: a thin icon-only left rail. The modules used to hide under the avatar
// dropdown; they now live here, each revealing its name in a hover/focus flyout label. Account
// actions sit at the bottom in a popover.
export default function NavSidebar({
me,
onOpenAbout,
@@ -34,10 +34,10 @@ export default function NavSidebar({
const { t } = useTranslation();
const { page } = useNavigation();
const { setPage } = useNavigationActions();
// The rail is ALWAYS slim: a thin icon-only column flush against the left edge. There is no
// expanded/pinned mode anymore — instead each icon reveals a floating name label on hover (a
// rest-to-show flyout via Tooltip), so the names are one glance away without the rail ever growing.
const slim = true;
// The rail is ALWAYS a thin icon-only column flush against the left edge. There is no
// expanded/pinned mode anymore — instead each icon reveals a floating name label on hover or
// keyboard focus (a rest-to-show flyout via Tooltip), so the names are one glance away without the
// rail ever growing.
const [acctOpen, setAcctOpen] = useState(false);
// The account panel holds mixed content with its own tab order (profile, account switches, two
// actions), so it is a `dialog` popover, not a roving menu. It portals out of the nav — whose
@@ -198,8 +198,6 @@ export default function NavSidebar({
};
return (
// Layout slot: reserves only the slim footprint when unpinned, so the expanded rail (below)
// overlays content instead of pushing it. Pinned reserves the full width (in-flow).
// Slim icon rail, flush against the left viewport edge (only top/bottom margin), never grows.
// The slot is exactly the card's width so the filter tab/bar docks flush against its right edge.
<div className="relative shrink-0 w-14">
@@ -213,28 +211,15 @@ export default function NavSidebar({
style={listFade.style}
>
{userItems.map(renderItem)}
{systemItems.length > 0 &&
(slim ? (
// Collapsed rail: a short, thicker centred rule is the clearest "new section" cue
// when there's no room for a label.
<div className="my-2 mx-auto w-7 border-t-2 border-border" />
) : (
<div className="mt-4 mb-1 px-2.5 flex items-center gap-2">
<span className="text-3xs font-semibold uppercase tracking-wider text-muted/70">
{t("nav.adminSection")}
</span>
<span className="flex-1 border-t border-border" />
</div>
))}
{systemItems.length > 0 && (
// A short, thicker centred rule is the clearest "new section" cue on an icon-only rail.
<div className="my-2 mx-auto w-7 border-t-2 border-border" />
)}
{systemItems.map(renderItem)}
</div>
<div className="mt-2 pt-2 border-t border-border flex flex-col gap-1">
<div
className={`flex items-center justify-center gap-2 pb-2 mb-1 border-b border-border ${
slim ? "flex-col" : "flex-row"
}`}
>
<div className="flex flex-col items-center justify-center gap-2 pb-2 mb-1 border-b border-border">
<LanguageSwitcher variant="rail" value={language} onChange={onChangeLanguage} />
<button
onClick={onOpenAbout}