mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-12 19:57:37 +00:00
feat(ui): add Classic, Smart, and Compact desktop navigation styles (#1642)
* feat(ui): add Classic, Smart, and Compact desktop navigation styles Introduce a shared app-nav registry and reachable model so TopBar, the command palette, and mobile menus share one destination source. Smart bar is the default; Appearance gains a Navigation subsection with quick links. * fix(e2e): stop clearing top-nav prefs on every reload The desktop-navigation suite used addInitScript to wipe mode storage, which re-ran on reload and undid the classic/compact values under test. * fix(ui): harden nav PR docs and Compact quick-link coverage Drop the partial docs-refresh import that left missing image assets and a stale Display screenshot, keep navigation-scoped operator docs against main, and add an E2E path that proves Compact quick-link add, persist, and render after reload. * fix(ui): polish Compact quick links and menu mastheads Align Smart/Compact menus with Theme chrome, keep pin labels always visible, and drive add capacity from persisted pins (max five) with a trailing + picker and per-pin remove. * test(e2e): exact-match Compact Networking pin locator Avoid Playwright strict-mode clash with Actions for Networking. * fix(ui): simplify Compact quick link removal and fix + button trailing Remove the (...) dropdown per quick link in Compact mode. Right-click context menu remains as the sole on-bar removal affordance. Fix the + add-button to trail quick links rather than pinning to the far right by removing flex-1 from the quick-link rail.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { lazy, Suspense, useCallback, useEffect, useRef, useState, type ReactNode } from 'react';
|
||||
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
|
||||
import { Button } from './ui/button';
|
||||
import { Plus, Loader2, ChevronLeft, AlertCircle, RefreshCw } from 'lucide-react';
|
||||
import { UserProfileDropdown } from './UserProfileDropdown';
|
||||
@@ -44,6 +44,9 @@ import type { SidebarActivityAction } from '@/components/sidebar/SidebarActivity
|
||||
import { useComposeDiffPreviewEnabled } from '@/hooks/use-compose-diff-preview-enabled';
|
||||
import { useTopNavLabels } from '@/hooks/use-top-nav-labels';
|
||||
import { useTopNavAlign } from '@/hooks/use-top-nav-align';
|
||||
import { useTopNavMode } from '@/hooks/use-top-nav-mode';
|
||||
import { useTopNavQuickLinks } from '@/hooks/use-top-nav-quick-links';
|
||||
import { getAppNavItem } from '@/lib/navigation/appNavRegistry';
|
||||
import { useStackMuteActions } from '@/hooks/useMuteRuleActions';
|
||||
import { toast } from '@/components/ui/toast-store';
|
||||
import { useIsMobile } from '@/hooks/use-is-mobile';
|
||||
@@ -195,6 +198,8 @@ export default function EditorLayout() {
|
||||
const [diffPreviewEnabled] = useComposeDiffPreviewEnabled();
|
||||
const [topNavLabels] = useTopNavLabels();
|
||||
const [topNavAlign] = useTopNavAlign();
|
||||
const [topNavMode] = useTopNavMode();
|
||||
const { persistedIds: quickLinkIds, addQuickLink, removeQuickLink } = useTopNavQuickLinks();
|
||||
|
||||
// Use a ref to break the circular dependency:
|
||||
// useViewNavigationState needs onNavigateToDashboard -> resetEditorState
|
||||
@@ -220,10 +225,22 @@ export default function EditorLayout() {
|
||||
handleMutePrefillConsumed,
|
||||
handleNavigate,
|
||||
navItems,
|
||||
navModel,
|
||||
openMuteRulesWithPrefill,
|
||||
reachCtx,
|
||||
} = navState;
|
||||
|
||||
const visibleQuickLinks = useMemo(() => {
|
||||
const candidateSet = new Set(navModel.quickLinkCandidates.map((item) => item.value));
|
||||
return quickLinkIds
|
||||
.filter((id) => candidateSet.has(id))
|
||||
.map((id) => {
|
||||
const item = getAppNavItem(id);
|
||||
return item ? { value: item.value, label: item.label, icon: item.icon } : null;
|
||||
})
|
||||
.filter((item): item is NonNullable<typeof item> => item !== null);
|
||||
}, [quickLinkIds, navModel.quickLinkCandidates]);
|
||||
|
||||
const {
|
||||
notifications,
|
||||
tickerConnected,
|
||||
@@ -908,6 +925,13 @@ export default function EditorLayout() {
|
||||
userMenu={userMenuEl}
|
||||
showLabels={topNavLabels}
|
||||
navAlign={topNavAlign}
|
||||
navMode={topNavMode}
|
||||
navModel={navModel}
|
||||
quickLinks={visibleQuickLinks}
|
||||
persistedQuickLinkIds={quickLinkIds}
|
||||
onAddQuickLink={(value) => addQuickLink(value as typeof quickLinkIds[number])}
|
||||
onRemoveQuickLink={(value) => removeQuickLink(value as typeof quickLinkIds[number])}
|
||||
onOpenSettings={() => openSettings()}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -962,6 +986,7 @@ export default function EditorLayout() {
|
||||
stackUpdates={stackUpdates}
|
||||
urlHydratingStack={urlHydratingStack}
|
||||
isFileLoading={isFileLoading}
|
||||
quickLinkCandidates={navModel.quickLinkCandidates}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -1033,6 +1058,7 @@ export default function EditorLayout() {
|
||||
headerActions={mobileMastheadActions}
|
||||
selectedSection={mobileSettingsSection}
|
||||
onSelectedSectionChange={setMobileSettingsSection}
|
||||
quickLinkCandidates={navModel.quickLinkCandidates}
|
||||
/>
|
||||
);
|
||||
case 'security':
|
||||
|
||||
Reference in New Issue
Block a user