校对:soup
由配置驱动、品牌不可知的土著反应(RN-web) 导航外壳 联 合 国
dloizides.com 组合: Sidebar + 键 Topbar,从同名字节升级
erevna-web / katalogos-web 导航双胞胎. 这个 铬 共享 项目数据 留下来
您的应用程序 - 组件使呼叫器提供 NavItem[] (标签已经本地化,
图标作为渲染槽),并通过共享 @dloizides/ui-feedback
UiProvider主题 :.
安装
npm install @dloizides/ui-nav @dloizides/ui-feedback @dloizides/auth-web
端点 : @dloizides/ui-feedback >= 1.2.0, (中文(简体) ), @dloizides/auth-web >= 1.5.0, (中文(简体) ), react >= 18, (中文(简体) ),
react-native >= 0.74 (使用时 react-native-web ) (中文(简体) ).
使用量
import { Sidebar, Topbar, accessibleNavItems, type NavItem } from '@dloizides/ui-nav';
const items: NavItem[] = buildItems(); // your role-filtered / grouped items
<Sidebar
items={items}
pathname={usePathname()}
onNavigate={(route) => router.push(route)}
title={FM('menu.title')}
regionLabel={FM('accessibility.navigationRegion')}
navigateHint={(label) => FM('menu.navigateToHint', label)}
expandHint={FM('menu.expandSection')}
collapseHint={FM('menu.collapseSection')}
renderChevron={(open, color, size) => <SvgIcon name={open ? 'chevronUp' : 'chevronDown'} color={color} size={size} />}
header={<HomeShortcut />}
footer={<><DarkModeToggle /><LogoutButton /></>}
/>
<Topbar
left={<TenantLogo />}
language={{ label: FM(`topbar.lang.${locale}`), hint: FM('topbar.langHint'), onPress: toggleLocale }}
notificationSlot={<NotificationBell />}
user={{ name: displayName, email }}
logout={{ label: FM('topbar.logout'), hint: FM('topbar.logoutHint'), onPress: logout, testID: 'logout-button' }}
/>
水平上栏( E)NavBar(中文(简体) )
首选导航链接 顶端 (横向菜单栏) 而不是左侧的栏杆?
NavBar 使同样的 NavItem[] 模式横向——左边的品牌插槽,
内置链接,一个自由形式的右槽(自动 / 用户 / 登录) —— 并崩溃
在可配置断点下方的汉堡包后面链接( 默认) 760匹配
v1 AML 控制台 .global-nav) (中文(简体) ). 纯粹是添加剂; Sidebar 不变.
import { NavBar, type NavItem } from '@dloizides/ui-nav';
<NavBar
items={items} // same role-filtered NavItem[] as Sidebar
pathname={usePathname()}
onNavigate={(route) => router.push(route)}
regionLabel={FM('accessibility.navigationRegion')}
navigateHint={(label) => FM('menu.navigateToHint', label)}
brand={<BrandLogo />} // left slot
right={<AuthLink />} // right slot (auth / user / logout)
menuLabel={FM('menu.toggle')} // a11y label for the hamburger
menuHint={FM('menu.toggleHint')}
collapseBelow={760} // hamburger under this viewport width
overflowLabel={FM('menu.more')} // "More ▾" priority+ trigger label
overflowHint={FM('menu.moreHint')}
/>
优先级+溢出("..."菜单). 上层 collapseBelow 链接坐在一个
非包装行。 当它们不都合身时,一个度量衡的传球就保留了领先的物品
{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}它与内线相接 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}其他的则会倒塌 "再来点" 触发——共享
@dloizides/ui-layout ModalDropdown 因此,任何物品都不能被切断;盈余
移动到一个可传送的键盘导航下拉。 如果活动路线位于
溢出装置, 触发器佩戴口音药丸 这样它仍然可以到达。 本地化
带有可选键的触发器 overflowLabel (可见 + 可访问,默认) "More"(中文(简体) )
财务报告和审定财务报表 overflowHint下图 collapseBelow 整个片段仍然倒塌
反应灵敏的汉堡抽屉, 所以两种机制从来没有重叠.
一个部分,两个方向(Nav(中文(简体) )
Nav 或使水平 NavBar 垂直键 Sidebar 从同
NavItem[],由单个 orientation 道具 — 在上行和侧面之间翻转
铁路不交换部件或再推道具. orientation 默认为
"horizontal"剩下的道具是 代表道具的歧视结合
(TypeScript每个方向执行正确的设定——例如. title 只有垂直,
collapseBelow 编号 : overflowLabel 仅限横向).
import { Nav, type NavItem } from '@dloizides/ui-nav';
<Nav orientation="horizontal" items={items} pathname={p} onNavigate={go} regionLabel={r} /> // NavBar
<Nav orientation="vertical" items={items} pathname={p} onNavigate={go} title={t} regionLabel={r} /> // Sidebar
Nav 纯添加剂: Sidebar 编号 : Topbar 编号 : NavBar 保持导出和不变.
1个外壳,3个布局——上方为QQ 两者 (单位:千美元)NavShell(中文(简体) )
何处 Nav 回答单轴问题(a) NavBar 或者说 (单位:千美元) Sidebar, (中文(简体) ),
NavShell 拥有整个页面构成并制作一个 上边栏页:1 边
铁路,或 两人在一起,由单个 layout 道具 (英语). 上面有条线
输入 AppShell是因为 header 槽和侧道进入它 sidebar 插槽,以及
继承每个 AppShell 能力(自动门、装载/误入/禁止状态)
牌,宽度政策,横幅,应答汉堡+上拉抽屉.
import { NavShell, type NavItem } from '@dloizides/ui-nav';
// layout="both" — a top bar (brand / global links + overflow "…" / user) AND a
// side rail (sections) together (the AML-console shape), now first-class.
<NavShell
layout="both"
pathname={usePathname()}
onNavigate={(route) => router.push(route)}
regionLabel={FM('a11y.nav')}
topBar={{
items: globalItems, // top links (overflow-capable)
brand: <BrandLogo />,
right: <><LanguageSwitcher /><UserChip /></>,
overflowLabel: FM('menu.more'),
barTheme: darkChromeTheme, // optional: dark bar over a light page
contentMaxWidth: 1180, // optional: full-bleed bar, inner capped + centred
}}
sideRail={{
items: sectionItems, // side sections (leaf + expandable)
title: FM('menu.title'),
footer: <><DarkModeControl … /><LogoutButton /></>,
collapsed: { range: { min: 768, max: 1024 } }, // optional 3-tier icon rail
}}
gate={{ pending, authenticated, onRedirect: () => router.push('/login') }}
state={{ loading, error, forbidden }}
width={{ max: 1180, wideMax: 1400, wideMinViewport: 1600 }}
testID="app-shell"
>
<PageContent />
</NavShell>
layout="top"· 仅上行(topBar没有铁路.layout="side"+ 条头+ 条尾相接的持久左轨(sideRail; 通过一个 结构化<Topbar>作为header用于语文/通知/用户槽.layout="both"- 两者,一起.
NavShell 组成现有的组件,所以它保持纯添加剂- AppShell, (中文(简体) ),
NavBar,以及 Sidebar 不变.
品牌位置、铁路宽度和电话抽屉NavShell纳弗-布兰德-1号
一个 brand prop 持有每个选择; 每一个默认(NAV_BRAND_DEFAULTS) 保持今天的布局.
brand 字段 | 数值 | 默认 |
|---|---|---|
placement | 'sidebar' (铁路顶部) 'topbar' (头部左上方,\\ 768 px,背景和下边框与上边栏相同) | 'sidebar' |
railWidth | 'default' 220个 'sm' 240个 'md' 264 妇女 'lg' 288 px (中文(简体) )SIDEBAR_WIDTH_PX(中文(简体) ) | 'default' |
drawerHeader | 'none' • 妇女 'brand' (品牌在开口抽屉的页头,有一个关闭按钮) | 'none' |
drawerWidth | 'default' (280 px 面板 + scrim) → 'full' (整个屏幕,关闭按钮) | 'default' |
<NavShell layout="side" brand={{ placement: 'topbar', railWidth: 'sm', drawerHeader: 'brand', drawerWidth: 'full' }}
sideRail={{ items, title, brand: <AppBrand /> }} header={<Topbar ... />} {...rest} />
品牌节点是一样的 sideRail.brand 在每一个位置;只有在它使变化的地方.
三级响应型铁路AppShell.collapsedSidebar 编号 : CollapsedRail(中文(简体) )
供应a collapsedSidebar (或 NavShell是因为 sideRail.collapsed选择铁路
进入 erevna/katalogos 方案:桌面上的全轨,中间体
持久性 已倒塌的(仅连)铁路 在平板带 [min, max) (默认)
{ min: 768, max: 1024 }电话上盖上抽屉 关闭它和
在布局上保持未变的两级方案(全轨为 768px,下面为抽屉).
CollapsedRail 使图标栏从相同的 NavItem[] (每件物品)
renderIcon,或首字母glyph后退,并有头/脚槽. 纯洁
resolveRailMode 决定等级,可直接进行单位测试.
暗条过一页NavBar.barTheme(中文(简体) )
过 barTheme 联合国 UiTheme)重新为栏目提供主题 仅限 a 包括:
亮工作空间( AML v1 控制台) 上方为 dark appbar 。 现场直播 t 编号 : navigate
重新通过, 因此标签保持本地化; 每种颜色仍然流经主题
(只有风格). 自定义应用程序背景( 如光圈- glow 梯度) 保留
可通过 containerStyle。 。 。 .
以内容为中心栏的全血条(NavBar.contentMaxWidth(中文(简体) )
过 contentMaxWidth (px)——通过 NavBar.contentMaxWidth 或者说
NavShell.topBar.contentMaxWidth - 让酒吧 满出血 当其内容
保留在中列。 外部容器(带有条形背景+
从下边框 barTheme / 主题表面 + 任意 containerStyle例如,AML公司
光圈-glow appbar)横跨全取景口宽;INNER行(品牌+链接+)
上限为 contentMaxWidth 中间的——v1控制台 .ui-appbar
(满血)+ .ui-appbar-inner { max-width; margin: 0 auto } 形状。 放弃它
内部横跨整个容器(不变)。 优先级+溢出"..."
测量被封盖的内向宽度,所以它一直与内容相对应
栏,而不是满载的容器.
通航药(PillNav(中文(简体) )
一排全圆的药丸 NavItem[] kefi的珊瑚仪表板开关器.
活性药丸带有口音(主题) palette.primary) (中文(简体) ). 克菲统治时期的花旗:
隐藏( 投降 ) null除非至少存在 minItems 条目(默认 1 ;
卡菲通行证 2) (中文(简体) ). 放下来 AppShell编号 :NavShell是因为 nav 插槽 .
色彩化学控制( E)DarkModeControl(中文(简体) )
受控光/暗/系统控制(erevna/katalogos),分两种变体:
"segmented" (突出的段行)和 "cycle" (图标+标签按钮)
预留至下个选项。 选项为本地化和不可知值
(字符串),所以在不使用此软件包导入的情况下,绘制您自己的首选项 。 放进去
在一个 Sidebar编号 :CollapsedRail 页脚或一个 NavBar 右侧插槽.
一个让一个 Sidebar 今天切换到顶端栏
Sidebar 用于 NavBar (同样的) items 编号 : pathname 编号 : onNavigate——例如.
aML v2 应用程序投放 NavBar 输入 AppShell header (或 nav时间档是这样的
链接像控制台的其余部分一样坐在顶端.
每个链接都是与 v1 的圆形溢出目标 .gn-links 付薪:在
后缀,使其文字亮出 + 显示一个微妙的药丸背景 盘旋,则a
固态口音药丸当 活动。所有颜色都由主题驱动(恢复=
textSecondary,徘徊文本 = text盘旋bg= surfaceElevated,活动/环=
palette.primary); 徘徊/焦点为只网络和徘徊的交叉淡出荣誉
prefers-reduced-motion。 。 。 .
无障碍. 容器是一个 role="navigation" 标记
regionLabel; 活动链接曝光 aria-current="page" + 键 role="link"; 数据
汉堡包 role="button", (中文(简体) ), aria-expanded,以及 aria-controls
指向可折叠链接区域; 每个链接/切换都是键盘操作
(Enter/Space),有座标焦点环和QQ44×44触地目标. Sidebar 叶子
携带 aria-current="page" 财务报告和审定财务报表 Topbar 按钮同一栏下的重点环.
搜索 – 桌面内置字段 – 移动 & K调色板
铁道可分两道搜索,由取景口选择. resolveSearchAffordance(viewport)
是纯规则: 'inline' 在/以上地区 DEFAULT_SEARCH_BREAKPOINT (768px), (中文(简体) ), 'palette' 见下文.
-
桌面( 宽度 ): 选择
Sidebar进入一个会缩小导航的持久内线域 列表按键运行。 默认关闭——通过enableInlineSearch+ 预先本地化search标签 :<Sidebar items={items} pathname={p} onNavigate={go} title={t} regionLabel={r} enableInlineSearch search={{ placeholder: FM('nav.search'), hint: FM('nav.searchHint'), clearLabel: FM('nav.clear'), clearHint: FM('nav.clearHint'), emptyText: FM('nav.noMatches'), }} />侧边栏拥有查询( 未控制) 除非您通过
searchQuery+ 键onSearchChange。 。 。 . 过滤是纯度filterNavItems(items, query)(所有查询符必须匹配标签;); 与孩子相匹配的团体. -
移动( 窄) : 保留QQK
CommandPalette(长期外地费用太高) 垂直空间)。 这个useCommandPaletteHotkey快捷键在每一宽处都保持绑定.
所以,一个贝壳使 resolveSearchAffordance(width) === 'inline' ? <Sidebar enableInlineSearch …/> : <CommandPalette …/> (或简单通过) enableInlineSearch 只有铁路支线.
角色游戏
accessibleNavItems(user, roleRouteTable, translate) 构建 NavItem[] 用户的作用
解锁, 重用 resolveAccessibleRoutes 从 @dloizides/auth-web (最特权第一,
无时为空)——没有重复的角色逻辑.
许可证
麻省理工学院