@dloizides/ui-nav 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +44 -0
- package/dist/index.d.mts +55 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +323 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +324 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.0
|
|
4
|
+
|
|
5
|
+
Give the `NavBar` the v1 `.gn-links` look + a full accessibility pass (and extend the
|
|
6
|
+
same a11y bar to `Sidebar`/`Topbar`).
|
|
7
|
+
|
|
8
|
+
**Look & hover (NavBar).** Each link is a rounded-pill target with the v1 hover
|
|
9
|
+
affordance — muted at rest, and on HOVER the text brightens to full contrast while a
|
|
10
|
+
subtle rounded-pill background appears; the ACTIVE link is a solid accent pill. All
|
|
11
|
+
theme-driven (rest = `textSecondary`, hover text = `text`, hover bg = `surfaceElevated`,
|
|
12
|
+
active/ring = `palette.primary`). Hover/focus are web-only (`onHoverIn/Out`, `onFocus/Blur`
|
|
13
|
+
via `Pressable`); native stays at the rest style. The hover cross-fade is cheap CSS and is
|
|
14
|
+
disabled under `prefers-reduced-motion: reduce` (new `useReducedMotion`). Backwards
|
|
15
|
+
compatible — the hover pill is the default (aml-v2 is the only `NavBar` consumer) and the
|
|
16
|
+
brand/right slots, responsive hamburger collapse, and `containerStyle` width behaviour are
|
|
17
|
+
unchanged.
|
|
18
|
+
|
|
19
|
+
**Accessibility.** NavBar toggle now carries `aria-controls` pointing at the collapsible
|
|
20
|
+
links region (id via `nativeID`), keeps `aria-expanded`, and gains a themed keyboard focus
|
|
21
|
+
ring; links keep `aria-current="page"` + `role="link"` and gain a focus ring; link/toggle
|
|
22
|
+
touch targets are now ≥44×44. `Sidebar` leaves gain `aria-current="page"` + a focus ring;
|
|
23
|
+
`Topbar` action buttons gain a focus ring (new internal `FocusableTouchable`). Focus rings
|
|
24
|
+
never remove the outline without a themed replacement.
|
|
25
|
+
|
|
26
|
+
## 1.2.0
|
|
27
|
+
|
|
28
|
+
Add `NavBar` — a config-driven **horizontal top navigation bar**, the top-bar
|
|
29
|
+
counterpart to `Sidebar`. It renders the same caller-supplied `NavItem[]` as inline
|
|
30
|
+
links across the top (brand left slot + inline links + free-form right slot), with
|
|
31
|
+
an active-link highlight (`aria-current="page"`) and a responsive collapse to a
|
|
32
|
+
hamburger toggle below a configurable breakpoint (`collapseBelow`, default `760`) —
|
|
33
|
+
mirroring the v1 AML console `.global-nav`. Theme-driven (UiProvider colours),
|
|
34
|
+
`role="navigation"` landmark, keyboard-operable links. Purely additive: `Sidebar`,
|
|
35
|
+
`Topbar`, `AppShell`, and the role-gating helpers are unchanged. New `NAV_TEST_IDS`
|
|
36
|
+
entries `navBarToggle` / `navBarLinks`.
|
|
37
|
+
|
|
3
38
|
## 1.0.0
|
|
4
39
|
|
|
5
40
|
Initial release. `Sidebar` (leaf + expandable items, active-route highlight, header/footer
|
package/README.md
CHANGED
|
@@ -46,6 +46,50 @@ const items: NavItem[] = buildItems(); // your role-filtered / grouped items
|
|
|
46
46
|
/>
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
### Horizontal top bar (`NavBar`)
|
|
50
|
+
|
|
51
|
+
Prefer the nav links **on top** (a horizontal menu bar) instead of the left rail?
|
|
52
|
+
`NavBar` renders the SAME `NavItem[]` model horizontally — brand slot on the left,
|
|
53
|
+
inline links, a free-form right slot (auth / user / logout) — and collapses the
|
|
54
|
+
links behind a hamburger below a configurable breakpoint (default `760`, matching
|
|
55
|
+
the v1 AML console `.global-nav`). It is purely additive; `Sidebar` is unchanged.
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { NavBar, type NavItem } from '@dloizides/ui-nav';
|
|
59
|
+
|
|
60
|
+
<NavBar
|
|
61
|
+
items={items} // same role-filtered NavItem[] as Sidebar
|
|
62
|
+
pathname={usePathname()}
|
|
63
|
+
onNavigate={(route) => router.push(route)}
|
|
64
|
+
regionLabel={FM('accessibility.navigationRegion')}
|
|
65
|
+
navigateHint={(label) => FM('menu.navigateToHint', label)}
|
|
66
|
+
brand={<BrandLogo />} // left slot
|
|
67
|
+
right={<AuthLink />} // right slot (auth / user / logout)
|
|
68
|
+
menuLabel={FM('menu.toggle')} // a11y label for the hamburger
|
|
69
|
+
menuHint={FM('menu.toggleHint')}
|
|
70
|
+
collapseBelow={760} // hamburger under this viewport width
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
An app that renders a `Sidebar` today switches to a top bar by swapping the
|
|
75
|
+
`Sidebar` element for `NavBar` (same `items` / `pathname` / `onNavigate`) — e.g.
|
|
76
|
+
the AML v2 app drops `NavBar` into the `AppShell` `header` (or `nav`) slot so its
|
|
77
|
+
links sit across the top like the rest of the console.
|
|
78
|
+
|
|
79
|
+
Each link is a rounded-pill target with the v1 `.gn-links` affordance: muted at
|
|
80
|
+
rest, brightening its text + showing a subtle pill background on **hover**, and a
|
|
81
|
+
solid accent pill when **active**. All colours are theme-driven (rest =
|
|
82
|
+
`textSecondary`, hover text = `text`, hover bg = `surfaceElevated`, active/ring =
|
|
83
|
+
`palette.primary`); hover/focus are web-only and the hover cross-fade honours
|
|
84
|
+
`prefers-reduced-motion`.
|
|
85
|
+
|
|
86
|
+
**Accessibility.** The container is a `role="navigation"` landmark named by
|
|
87
|
+
`regionLabel`; active links expose `aria-current="page"` + `role="link"`; the
|
|
88
|
+
responsive hamburger carries `role="button"`, `aria-expanded`, and `aria-controls`
|
|
89
|
+
pointing at the collapsible links region; every link/toggle is keyboard-operable
|
|
90
|
+
(Enter/Space) with a themed focus ring and a ≥44×44 touch target. `Sidebar` leaves
|
|
91
|
+
carry `aria-current="page"` and `Topbar` buttons a focus ring under the same bar.
|
|
92
|
+
|
|
49
93
|
### Role gating
|
|
50
94
|
|
|
51
95
|
`accessibleNavItems(user, roleRouteTable, translate)` builds the `NavItem[]` a user's roles
|
package/dist/index.d.mts
CHANGED
|
@@ -145,6 +145,56 @@ interface TopbarProps {
|
|
|
145
145
|
}
|
|
146
146
|
declare const Topbar: ({ left, language, notificationSlot, user, account, logout, containerStyle, }: TopbarProps) => React.ReactElement;
|
|
147
147
|
|
|
148
|
+
/**
|
|
149
|
+
* NavBar — the config-driven HORIZONTAL top navigation bar. It is the top-bar
|
|
150
|
+
* counterpart to `Sidebar`: it renders the SAME caller-supplied `NavItem[]`
|
|
151
|
+
* (already role-filtered / localized by the app) as inline links across the top
|
|
152
|
+
* instead of a left rail, with an optional brand slot on the left and a free-form
|
|
153
|
+
* right slot (auth link / user / logout). Below a configurable breakpoint it
|
|
154
|
+
* collapses the links behind a hamburger toggle — mirroring the v1 AML console's
|
|
155
|
+
* responsive `.global-nav`.
|
|
156
|
+
*
|
|
157
|
+
* Look + feel: each link is a rounded-pill target with the v1 `.gn-links a`
|
|
158
|
+
* affordance — muted at rest, brightening text + a subtle pill background on
|
|
159
|
+
* HOVER, and a solid accent pill when ACTIVE. All colours are THEME-DRIVEN from
|
|
160
|
+
* the `@dloizides/ui-feedback` UiProvider (rest=`textSecondary`, hover text=`text`,
|
|
161
|
+
* hover bg=`surfaceElevated`, active=`palette.primary`, ring=`palette.primary`).
|
|
162
|
+
* Hover/focus are web-only (react-native-web); native stays at the rest style.
|
|
163
|
+
*
|
|
164
|
+
* Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,
|
|
165
|
+
* icon set, or store imports. Labels are pre-localized strings, icons are render
|
|
166
|
+
* slots, and every colour is read from the theme. This is purely additive —
|
|
167
|
+
* `Sidebar`/`Topbar` are unchanged.
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
interface NavBarProps {
|
|
171
|
+
/** Nav entries — already role-filtered / grouped by the app. */
|
|
172
|
+
items: NavItem[];
|
|
173
|
+
/** Current active route/path. */
|
|
174
|
+
pathname: string;
|
|
175
|
+
/** Navigation callback — receives a `NavItem.route`. */
|
|
176
|
+
onNavigate: (route: string) => void;
|
|
177
|
+
/** Localized accessibility label for the navigation landmark. */
|
|
178
|
+
regionLabel: string;
|
|
179
|
+
/** a11y hint for a link, given its label. Defaults to the label. */
|
|
180
|
+
navigateHint?: (label: string) => string;
|
|
181
|
+
/** Left slot — typically the brand / tenant logo. */
|
|
182
|
+
brand?: React.ReactNode;
|
|
183
|
+
/** Right slot — free-form (auth link, user block, logout). */
|
|
184
|
+
right?: React.ReactNode;
|
|
185
|
+
/** Localized accessibility label for the responsive menu toggle. */
|
|
186
|
+
menuLabel?: string;
|
|
187
|
+
/** Localized accessibility hint for the responsive menu toggle. */
|
|
188
|
+
menuHint?: string;
|
|
189
|
+
/** Optional custom glyph renderer for the toggle; defaults to ☰. */
|
|
190
|
+
renderMenuIcon?: (color: string, open: boolean) => React.ReactNode;
|
|
191
|
+
/** Collapse the links behind a hamburger below this viewport width (default 760). */
|
|
192
|
+
collapseBelow?: number;
|
|
193
|
+
/** Extra container style overrides. */
|
|
194
|
+
containerStyle?: ViewStyle | ViewStyle[];
|
|
195
|
+
}
|
|
196
|
+
declare const NavBar: ({ items, pathname, onNavigate, regionLabel, navigateHint, brand, right, menuLabel, menuHint, renderMenuIcon, collapseBelow, containerStyle, }: NavBarProps) => React.ReactElement;
|
|
197
|
+
|
|
148
198
|
/** Content-width policy: a capped column, optionally wider past a viewport breakpoint, or full-bleed. */
|
|
149
199
|
type AppShellWidth = {
|
|
150
200
|
max: number;
|
|
@@ -229,6 +279,10 @@ declare const NAV_TEST_IDS: {
|
|
|
229
279
|
readonly accountPlan: "topbar-account-plan";
|
|
230
280
|
/** default testID for the rich header's upgrade action (overridable per-action). */
|
|
231
281
|
readonly accountUpgrade: "topbar-account-upgrade";
|
|
282
|
+
/** responsive hamburger toggle in the horizontal NavBar (shown below the breakpoint). */
|
|
283
|
+
readonly navBarToggle: "navbar-toggle";
|
|
284
|
+
/** links container in the horizontal NavBar. */
|
|
285
|
+
readonly navBarLinks: "navbar-links";
|
|
232
286
|
};
|
|
233
287
|
/** Suffixes appended to an `AppShell`'s required `testID` to name its regions. */
|
|
234
288
|
declare const APP_SHELL_SUFFIX: {
|
|
@@ -408,4 +462,4 @@ declare const NAV_ICON_SIZE = 14;
|
|
|
408
462
|
/** Chevron icon size for expandable sections. */
|
|
409
463
|
declare const CHEVRON_ICON_SIZE = 12;
|
|
410
464
|
|
|
411
|
-
export { ACTIVE_BORDER_RADIUS, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, NAV_ICON_SIZE, NAV_TEST_IDS, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavUser, type ShellMessage, Sidebar, type SidebarProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, expandableStyles, isRouteActive, navStyles, resolveContentMaxWidth, roleRoutesToNavItems, useContentMaxWidth };
|
|
465
|
+
export { ACTIVE_BORDER_RADIUS, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, NAV_ICON_SIZE, NAV_TEST_IDS, NavBar, type NavBarProps, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavUser, type ShellMessage, Sidebar, type SidebarProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, expandableStyles, isRouteActive, navStyles, resolveContentMaxWidth, roleRoutesToNavItems, useContentMaxWidth };
|
package/dist/index.d.ts
CHANGED
|
@@ -145,6 +145,56 @@ interface TopbarProps {
|
|
|
145
145
|
}
|
|
146
146
|
declare const Topbar: ({ left, language, notificationSlot, user, account, logout, containerStyle, }: TopbarProps) => React.ReactElement;
|
|
147
147
|
|
|
148
|
+
/**
|
|
149
|
+
* NavBar — the config-driven HORIZONTAL top navigation bar. It is the top-bar
|
|
150
|
+
* counterpart to `Sidebar`: it renders the SAME caller-supplied `NavItem[]`
|
|
151
|
+
* (already role-filtered / localized by the app) as inline links across the top
|
|
152
|
+
* instead of a left rail, with an optional brand slot on the left and a free-form
|
|
153
|
+
* right slot (auth link / user / logout). Below a configurable breakpoint it
|
|
154
|
+
* collapses the links behind a hamburger toggle — mirroring the v1 AML console's
|
|
155
|
+
* responsive `.global-nav`.
|
|
156
|
+
*
|
|
157
|
+
* Look + feel: each link is a rounded-pill target with the v1 `.gn-links a`
|
|
158
|
+
* affordance — muted at rest, brightening text + a subtle pill background on
|
|
159
|
+
* HOVER, and a solid accent pill when ACTIVE. All colours are THEME-DRIVEN from
|
|
160
|
+
* the `@dloizides/ui-feedback` UiProvider (rest=`textSecondary`, hover text=`text`,
|
|
161
|
+
* hover bg=`surfaceElevated`, active=`palette.primary`, ring=`palette.primary`).
|
|
162
|
+
* Hover/focus are web-only (react-native-web); native stays at the rest style.
|
|
163
|
+
*
|
|
164
|
+
* Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,
|
|
165
|
+
* icon set, or store imports. Labels are pre-localized strings, icons are render
|
|
166
|
+
* slots, and every colour is read from the theme. This is purely additive —
|
|
167
|
+
* `Sidebar`/`Topbar` are unchanged.
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
interface NavBarProps {
|
|
171
|
+
/** Nav entries — already role-filtered / grouped by the app. */
|
|
172
|
+
items: NavItem[];
|
|
173
|
+
/** Current active route/path. */
|
|
174
|
+
pathname: string;
|
|
175
|
+
/** Navigation callback — receives a `NavItem.route`. */
|
|
176
|
+
onNavigate: (route: string) => void;
|
|
177
|
+
/** Localized accessibility label for the navigation landmark. */
|
|
178
|
+
regionLabel: string;
|
|
179
|
+
/** a11y hint for a link, given its label. Defaults to the label. */
|
|
180
|
+
navigateHint?: (label: string) => string;
|
|
181
|
+
/** Left slot — typically the brand / tenant logo. */
|
|
182
|
+
brand?: React.ReactNode;
|
|
183
|
+
/** Right slot — free-form (auth link, user block, logout). */
|
|
184
|
+
right?: React.ReactNode;
|
|
185
|
+
/** Localized accessibility label for the responsive menu toggle. */
|
|
186
|
+
menuLabel?: string;
|
|
187
|
+
/** Localized accessibility hint for the responsive menu toggle. */
|
|
188
|
+
menuHint?: string;
|
|
189
|
+
/** Optional custom glyph renderer for the toggle; defaults to ☰. */
|
|
190
|
+
renderMenuIcon?: (color: string, open: boolean) => React.ReactNode;
|
|
191
|
+
/** Collapse the links behind a hamburger below this viewport width (default 760). */
|
|
192
|
+
collapseBelow?: number;
|
|
193
|
+
/** Extra container style overrides. */
|
|
194
|
+
containerStyle?: ViewStyle | ViewStyle[];
|
|
195
|
+
}
|
|
196
|
+
declare const NavBar: ({ items, pathname, onNavigate, regionLabel, navigateHint, brand, right, menuLabel, menuHint, renderMenuIcon, collapseBelow, containerStyle, }: NavBarProps) => React.ReactElement;
|
|
197
|
+
|
|
148
198
|
/** Content-width policy: a capped column, optionally wider past a viewport breakpoint, or full-bleed. */
|
|
149
199
|
type AppShellWidth = {
|
|
150
200
|
max: number;
|
|
@@ -229,6 +279,10 @@ declare const NAV_TEST_IDS: {
|
|
|
229
279
|
readonly accountPlan: "topbar-account-plan";
|
|
230
280
|
/** default testID for the rich header's upgrade action (overridable per-action). */
|
|
231
281
|
readonly accountUpgrade: "topbar-account-upgrade";
|
|
282
|
+
/** responsive hamburger toggle in the horizontal NavBar (shown below the breakpoint). */
|
|
283
|
+
readonly navBarToggle: "navbar-toggle";
|
|
284
|
+
/** links container in the horizontal NavBar. */
|
|
285
|
+
readonly navBarLinks: "navbar-links";
|
|
232
286
|
};
|
|
233
287
|
/** Suffixes appended to an `AppShell`'s required `testID` to name its regions. */
|
|
234
288
|
declare const APP_SHELL_SUFFIX: {
|
|
@@ -408,4 +462,4 @@ declare const NAV_ICON_SIZE = 14;
|
|
|
408
462
|
/** Chevron icon size for expandable sections. */
|
|
409
463
|
declare const CHEVRON_ICON_SIZE = 12;
|
|
410
464
|
|
|
411
|
-
export { ACTIVE_BORDER_RADIUS, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, NAV_ICON_SIZE, NAV_TEST_IDS, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavUser, type ShellMessage, Sidebar, type SidebarProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, expandableStyles, isRouteActive, navStyles, resolveContentMaxWidth, roleRoutesToNavItems, useContentMaxWidth };
|
|
465
|
+
export { ACTIVE_BORDER_RADIUS, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, NAV_ICON_SIZE, NAV_TEST_IDS, NavBar, type NavBarProps, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavUser, type ShellMessage, Sidebar, type SidebarProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, expandableStyles, isRouteActive, navStyles, resolveContentMaxWidth, roleRoutesToNavItems, useContentMaxWidth };
|