@xsolla/xui-b2b-sidebar 0.194.0 → 0.195.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Sidebar
2
2
 
3
- A composable navigation sidebar for B2B admin surfaces. Renders an expanded panel with grouped menu items and a parallel collapsed icon strip with hover popovers, both driven by the same `SidebarProvider` so the active route, link component, and collapsed state stay in sync.
3
+ A composable navigation sidebar for B2B admin surfaces. Renders an expanded panel with grouped menu items and a parallel collapsed icon strip with hover popovers, both driven by the same `SidebarProvider` so the active route, link component, collapsed state and label translations stay in sync.
4
4
 
5
5
  ## Installation
6
6
 
@@ -25,11 +25,20 @@ import {
25
25
  SidebarTrigger,
26
26
  SidebarChatButton,
27
27
  SidebarCollapsed,
28
+ SidebarPinnedList,
29
+ getPinnedCollapsedItem,
30
+ DEFAULT_SIDEBAR_LABELS,
31
+ resolveSidebarLabels,
28
32
  type SidebarProps,
29
33
  type SidebarProviderProps,
30
34
  type SidebarMenuItemProps,
31
35
  type SidebarMenuCollapsibleProps,
32
36
  type SidebarCollapsedProps,
37
+ type SidebarChatButtonProps,
38
+ type SidebarTriggerProps,
39
+ type SidebarPinnedItem,
40
+ type SidebarPinnedListProps,
41
+ type SidebarLabels,
33
42
  type SidebarItemType,
34
43
  type SidebarLinkProps,
35
44
  type SidebarLinkActiveCheck,
@@ -114,6 +123,80 @@ function AppShell({ pathname }: { pathname: string }) {
114
123
  }
115
124
  ```
116
125
 
126
+ ## Localisation
127
+
128
+ Menu labels, group headings and popover titles are consumer-supplied props, so they are localisable by construction. The strings the sidebar renders **on its own behalf** — the chat button, the collapse/expand toggle, the pin controls, the "Beta" tag and the navigation landmark — are collected in a single `SidebarLabels` map. Override any subset once on `SidebarProvider`:
129
+
130
+ ```tsx
131
+ import { SidebarProvider } from "@xsolla/xui-b2b-sidebar";
132
+ import { useTranslation } from "react-i18next";
133
+
134
+ function LocalisedShell({ children }: { children: React.ReactNode }) {
135
+ const { t } = useTranslation();
136
+
137
+ return (
138
+ <SidebarProvider
139
+ pathname={location.pathname}
140
+ labels={{
141
+ navigation: t("sidebar.navigation"),
142
+ expandSidebar: t("sidebar.expand"),
143
+ collapseSidebar: t("sidebar.collapse"),
144
+ chat: t("sidebar.chat"),
145
+ openChat: t("sidebar.openChat"),
146
+ pin: t("sidebar.pin"),
147
+ unpin: t("sidebar.unpin"),
148
+ pinItem: t("sidebar.pinItem"),
149
+ unpinItem: t("sidebar.unpinItem"),
150
+ beta: t("sidebar.beta"),
151
+ pinned: t("sidebar.pinned"),
152
+ }}
153
+ >
154
+ {children}
155
+ </SidebarProvider>
156
+ );
157
+ }
158
+ ```
159
+
160
+ Every key is optional — omitted keys keep their English default from `DEFAULT_SIDEBAR_LABELS`.
161
+
162
+ ### Label keys
163
+
164
+ | Key | Default | Where it appears |
165
+ | ----------------- | -------------------- | ----------------------------------------------------------------- |
166
+ | `navigation` | `"Sidebar navigation"` | `aria-label` on the root `role="navigation"` landmark. |
167
+ | `expandSidebar` | `"Expand sidebar"` | `aria-label` on the toggle while collapsed (both modes). |
168
+ | `collapseSidebar` | `"Collapse sidebar"` | `aria-label` on the toggle while expanded. |
169
+ | `chat` | `"Chat"` | Visible text on the expanded-mode `SidebarChatButton`. |
170
+ | `openChat` | `"Open chat"` | `aria-label` on the collapsed-mode icon-only chat button. |
171
+ | `pin` | `"Pin"` | Pin-toggle tooltip while the item is unpinned. |
172
+ | `unpin` | `"Unpin"` | Pin-toggle tooltip while the item is pinned. |
173
+ | `pinItem` | `"Pin item"` | Pin-toggle `aria-label` while unpinned. |
174
+ | `unpinItem` | `"Unpin item"` | Pin-toggle `aria-label` while pinned. |
175
+ | `beta` | `"Beta"` | Trailing tag rendered when `beta` is set on a menu item. |
176
+ | `pinned` | `"Pinned"` | Default title of the collapsed-mode pinned-shortcuts popover. |
177
+
178
+ ### Precedence
179
+
180
+ Per-instance props beat the provider, which beats the defaults:
181
+
182
+ ```
183
+ component prop > SidebarProvider labels > DEFAULT_SIDEBAR_LABELS
184
+ ```
185
+
186
+ Use a per-instance prop only when one occurrence needs to differ — e.g. two sidebars on one page needing distinct landmark names:
187
+
188
+ ```tsx
189
+ <Sidebar navigationLabel={t("sidebar.secondaryNavigation")}>{/* ... */}</Sidebar>
190
+ ```
191
+
192
+ ### `getPinnedCollapsedItem`
193
+
194
+ This helper is a plain function, not a component, so it cannot read provider context. Pass the translated title through `options.label`:
195
+
196
+ ```tsx
197
+ const pinnedItem = getPinnedCollapsedItem(pinnedItems, { label: t("sidebar.pinned") });
198
+ ```
199
+
117
200
  ## API Reference
118
201
 
119
202
  None of the sidebar components extend `ThemeOverrideProps` — they read theme via `useResolvedTheme()` from the surrounding provider. Wrap the app in a theme provider if you need to override mode or product context.
@@ -127,6 +210,7 @@ None of the sidebar components extend `ThemeOverrideProps` — they read theme v
127
210
  | `onCollapsedChange` | `(collapsed: boolean) => void` | — | Called when the user toggles via `SidebarTrigger` or the collapsed-mode toggle. |
128
211
  | `pathname` | `string` | `""` | Current route, used for active-state matching and `matchPaths` auto-expand. |
129
212
  | `linkComponent` | `ComponentType<SidebarLinkProps>` | plain `<a>` | Router link component. |
213
+ | `labels` | `Partial<SidebarLabels>` | English | Translations for the strings the sidebar renders itself. See [Localisation](#localisation). |
130
214
  | `children` | `ReactNode` | — | Sidebar tree. |
131
215
 
132
216
  ### `useSidebar()`
@@ -141,44 +225,53 @@ function useSidebar(): {
141
225
  LinkComponent: React.ComponentType<SidebarLinkProps>;
142
226
  expandedId: string | null;
143
227
  onExpandedIdChange: (id: string | null) => void;
228
+ labels: SidebarLabels;
144
229
  };
145
230
  ```
146
231
 
147
- `expandedId` / `onExpandedIdChange` coordinate which `SidebarMenuCollapsible` is open — only one at a time.
232
+ `expandedId` / `onExpandedIdChange` coordinate which `SidebarMenuCollapsible` is open — only one at a time. `labels` is always fully resolved (provider overrides merged over the defaults), so consumers can read it without null checks.
148
233
 
149
234
  ### `<Sidebar>`
150
235
 
151
- | Prop | Type | Default | Description |
152
- | ---------------------- | ------------------- | ------- | ------------------------------------------------------ |
153
- | `collapsedItems` | `SidebarItemType[]` | `[]` | Top icons in the collapsed strip. |
154
- | `collapsedToolItems` | `SidebarItemType[]` | `[]` | Tool icons rendered after a spacer. |
155
- | `collapsedBottomItems` | `SidebarItemType[]` | `[]` | Bottom icons (e.g. Settings, Billing). |
156
- | `showChat` | `boolean` | `true` | Render the chat button in the collapsed footer. |
157
- | `onChatClick` | `() => void` | — | Click handler for the chat button. |
158
- | `chatBadge` | `boolean` | `false` | Show an unread-indicator dot on the chat button. |
159
- | `children` | `ReactNode` | — | The expanded tree (`SidebarContent`, `SidebarFooter`). |
236
+ | Prop | Type | Default | Description |
237
+ | ---------------------- | ------------------- | -------------------- | ------------------------------------------------------ |
238
+ | `collapsedItems` | `SidebarItemType[]` | `[]` | Top icons in the collapsed strip. |
239
+ | `collapsedToolItems` | `SidebarItemType[]` | `[]` | Tool icons rendered after a spacer. |
240
+ | `collapsedBottomItems` | `SidebarItemType[]` | `[]` | Bottom icons (e.g. Settings, Billing). |
241
+ | `showChat` | `boolean` | `true` | Render the chat button in the collapsed footer. |
242
+ | `onChatClick` | `() => void` | — | Click handler for the chat button. |
243
+ | `chatBadge` | `boolean` | `false` | Show an unread-indicator dot on the chat button. |
244
+ | `navigationLabel` | `string` | `labels.navigation` | `aria-label` for the navigation landmark. |
245
+ | `children` | `ReactNode` | — | The expanded tree (`SidebarContent`, `SidebarFooter`). |
160
246
 
161
247
  ### `<SidebarMenuItem>`
162
248
 
163
- | Prop | Type | Default | Description |
164
- | ----------------- | ------------------------- | ------- | ----------------------------------------------------------------------------------- |
165
- | `to` | `string` | — | Route URL passed through to `linkComponent`. |
166
- | `label` | `ReactNode` | — | Text label. |
167
- | `icon` | `ReactNode` | — | Leading icon (hidden when `isNested`). |
168
- | `exact` | `boolean` | — | Exact-match flag forwarded to the link component. |
169
- | `external` | `boolean` | — | Marks the link as external (sets `target`/`rel`). |
170
- | `hasExternalIcon` | `boolean` | — | Shows the external-link icon at the trailing edge. |
171
- | `target` | `string \| null` | — | Anchor target. |
172
- | `onClick` | `SidebarLinkClickHandler` | — | Click handler. |
173
- | `dataId` | `string` | — | `data-id` attribute for tests/analytics. |
174
- | `isActive` | `SidebarLinkActiveCheck` | — | Custom active-check forwarded to the link. |
175
- | `isPinned` | `boolean` | — | Renders the icon at 12px to indicate a pinned item. |
176
- | `showBadge` | `boolean` | — | Shows a small alert dot next to the label. |
177
- | `hasTooltip` | `boolean` | — | Truncates labels longer than 20 chars and shows the full text on hover. |
178
- | `beta` | `boolean` | — | Renders a "Beta" tag at the trailing edge. |
179
- | `multiLine` | `boolean` | — | Allows the label to wrap to multiple lines. |
180
- | `extra` | `ReactNode` | — | Slot rendered between the icon and the label. |
181
- | `isNested` | `boolean` | `false` | Set when rendered inside `SidebarMenuSub` (drops the icon, indents under the rail). |
249
+ | Prop | Type | Default | Description |
250
+ | ----------------- | ------------------------- | ------------------ | ----------------------------------------------------------------------------------- |
251
+ | `to` | `string` | — | Route URL passed through to `linkComponent`. |
252
+ | `label` | `ReactNode` | — | Text label. |
253
+ | `icon` | `ReactNode` | — | Leading icon (hidden when `isNested`). |
254
+ | `exact` | `boolean` | — | Exact-match flag forwarded to the link component. |
255
+ | `external` | `boolean` | — | Marks the link as external (sets `target`/`rel`). |
256
+ | `hasExternalIcon` | `boolean` | — | Shows the external-link icon at the trailing edge. |
257
+ | `target` | `string \| null` | — | Anchor target. |
258
+ | `onClick` | `SidebarLinkClickHandler` | — | Click handler. |
259
+ | `dataId` | `string` | — | `data-id` attribute for tests/analytics. |
260
+ | `isActive` | `SidebarLinkActiveCheck` | — | Custom active-check forwarded to the link. |
261
+ | `isPinned` | `boolean` | — | Renders the icon at 12px to indicate a pinned item. |
262
+ | `onPinToggle` | `(e) => void` | — | Renders a pin/unpin toggle on hover (always visible when pinned). |
263
+ | `dragHandle` | `boolean` | — | On a pinned item, swaps the pin glyph for a drag handle on row hover. |
264
+ | `showBadge` | `boolean` | — | Shows a small alert dot next to the label. |
265
+ | `hasTooltip` | `boolean` | — | Truncates labels longer than 20 chars and shows the full text on hover. |
266
+ | `beta` | `boolean` | — | Renders a "Beta" tag at the trailing edge. |
267
+ | `multiLine` | `boolean` | — | Allows the label to wrap to multiple lines. |
268
+ | `extra` | `ReactNode` | — | Slot rendered between the icon and the label. |
269
+ | `isNested` | `boolean` | `false` | Set when rendered inside `SidebarMenuSub` (drops the icon, indents under the rail). |
270
+ | `pinLabel` | `string` | `labels.pin` | Pin-toggle tooltip while unpinned. |
271
+ | `unpinLabel` | `string` | `labels.unpin` | Pin-toggle tooltip while pinned. |
272
+ | `pinAriaLabel` | `string` | `labels.pinItem` | Pin-toggle `aria-label` while unpinned. |
273
+ | `unpinAriaLabel` | `string` | `labels.unpinItem` | Pin-toggle `aria-label` while pinned. |
274
+ | `betaLabel` | `string` | `labels.beta` | Text inside the trailing tag when `beta` is set. |
182
275
 
183
276
  ### `<SidebarMenuCollapsible>`
184
277
 
@@ -194,15 +287,17 @@ function useSidebar(): {
194
287
 
195
288
  Lower-level collapsed-strip renderer. The `<Sidebar>` component composes this for you; reach for it when you need to render the collapsed strip outside the standard layout.
196
289
 
197
- | Prop | Type | Default | Description |
198
- | ------------------ | ------------------- | ------- | -------------------------------------------------- |
199
- | `items` | `SidebarItemType[]` | — | Top icon items. |
200
- | `toolItems` | `SidebarItemType[]` | `[]` | Tool icons after a spacer. |
201
- | `bottomItems` | `SidebarItemType[]` | `[]` | Bottom icons. |
202
- | `onToggleCollapse` | `() => void` | — | Click handler for the toggle button in the footer. |
203
- | `onChatClick` | `() => void` | — | Click handler for the chat button. |
204
- | `showChat` | `boolean` | `true` | Render the chat button. |
205
- | `chatBadge` | `boolean` | `false` | Show the unread dot. |
290
+ | Prop | Type | Default | Description |
291
+ | ------------------ | ------------------- | ---------------------- | -------------------------------------------------- |
292
+ | `items` | `SidebarItemType[]` | — | Top icon items. |
293
+ | `toolItems` | `SidebarItemType[]` | `[]` | Tool icons after a spacer. |
294
+ | `bottomItems` | `SidebarItemType[]` | `[]` | Bottom icons. |
295
+ | `onToggleCollapse` | `() => void` | — | Click handler for the toggle button in the footer. |
296
+ | `onChatClick` | `() => void` | — | Click handler for the chat button. |
297
+ | `showChat` | `boolean` | `true` | Render the chat button. |
298
+ | `chatBadge` | `boolean` | `false` | Show the unread dot. |
299
+ | `chatAriaLabel` | `string` | `labels.openChat` | `aria-label` for the icon-only chat button. |
300
+ | `expandLabel` | `string` | `labels.expandSidebar` | `aria-label` for the expand toggle. |
206
301
 
207
302
  ### `<SidebarContent>`
208
303
 
@@ -216,9 +311,20 @@ Bordered footer row for the bottom of the sidebar; typically wraps the chat butt
216
311
 
217
312
  Collapse/expand toggle button. Reads/writes state from the surrounding `SidebarProvider`.
218
313
 
314
+ | Prop | Type | Default | Description |
315
+ | --------------- | -------- | ------------------------ | ------------------------------------ |
316
+ | `expandLabel` | `string` | `labels.expandSidebar` | `aria-label` used while collapsed. |
317
+ | `collapseLabel` | `string` | `labels.collapseSidebar` | `aria-label` used while expanded. |
318
+
219
319
  ### `<SidebarChatButton>`
220
320
 
221
- Branded chat button for the footer. Props: `onClick: () => void`, `badge?: boolean`.
321
+ Branded chat button for the footer.
322
+
323
+ | Prop | Type | Default | Description |
324
+ | --------- | ------------ | -------------- | -------------------------------------- |
325
+ | `onClick` | `() => void` | — | Click handler. |
326
+ | `badge` | `boolean` | `false` | Show the unread-indicator dot. |
327
+ | `label` | `string` | `labels.chat` | Visible button text. |
222
328
 
223
329
  ### `<SidebarGroup>`
224
330
 
@@ -235,6 +341,25 @@ Fragment used as a structural marker inside collapsibles to group nested menu it
235
341
  ### Types
236
342
 
237
343
  ```ts
344
+ interface SidebarLabels {
345
+ navigation: string;
346
+ expandSidebar: string;
347
+ collapseSidebar: string;
348
+ chat: string;
349
+ openChat: string;
350
+ pin: string;
351
+ unpin: string;
352
+ pinItem: string;
353
+ unpinItem: string;
354
+ beta: string;
355
+ pinned: string;
356
+ }
357
+
358
+ declare const DEFAULT_SIDEBAR_LABELS: SidebarLabels;
359
+ declare const resolveSidebarLabels: (
360
+ overrides?: Partial<SidebarLabels>
361
+ ) => SidebarLabels;
362
+
238
363
  type SidebarItemType = {
239
364
  to?: string;
240
365
  label: ReactNode;
@@ -415,8 +540,10 @@ const mainNavItems: SidebarItemType[] = [
415
540
 
416
541
  ## Accessibility
417
542
 
418
- - The root sidebar is `role="navigation"` with `aria-label="Sidebar navigation"`. The expanded and collapsed panes are toggled via `aria-hidden` so only one is announced at a time.
419
- - `SidebarTrigger` and the collapsed-mode toggle have `aria-pressed` and a context-aware `aria-label` (`"Expand sidebar"` / `"Collapse sidebar"`).
543
+ - The root sidebar is `role="navigation"` with an `aria-label` from `labels.navigation` (default `"Sidebar navigation"`, per-instance override via `navigationLabel`). The expanded and collapsed panes are toggled via `aria-hidden` so only one is announced at a time.
544
+ - `SidebarTrigger` and the collapsed-mode toggle have `aria-pressed` and a context-aware `aria-label` (`labels.expandSidebar` / `labels.collapseSidebar`).
545
+ - The pin toggle exposes `aria-pressed` plus `labels.pinItem` / `labels.unpinItem` as its `aria-label`, and a tooltip carrying `labels.pin` / `labels.unpin`.
546
+ - Every one of those strings is translatable through the provider's `labels` prop — assistive-technology users get the app's language, not English.
420
547
  - Each `SidebarMenuCollapsible` header is a `<button>` with `aria-expanded` and `aria-controls` linking to its region.
421
548
  - Collapsed icon items with children expose `aria-haspopup="menu"`; their popovers are keyboard-reachable (focus opens, blur closes after 150ms, Escape closes immediately). Leaf items (no children) render as native links and navigate on click or Enter.
422
549
  - Truncated labels (`hasTooltip`) fall back to a Tooltip with the full text.
@@ -427,3 +554,4 @@ const mainNavItems: SidebarItemType[] = [
427
554
  - Only one `SidebarMenuCollapsible` is open at a time; the section auto-expands when `pathname` matches one of `matchPaths` (a leading `/<merchantId>` numeric prefix is stripped before matching).
428
555
  - Hover popovers in collapsed mode are rendered into a portal on `document.body` and positioned with viewport-clamped `position: fixed` math.
429
556
  - Active route detection lives in the consumer's `linkComponent` — apply `activeClassName` when the link matches the current route.
557
+ - `labels` overrides are merged over the defaults once per provider render and serialised for memoisation, so passing an inline object literal does not thrash the context.
@@ -1,5 +1,56 @@
1
1
  import React, { MouseEvent, ReactNode } from 'react';
2
2
 
3
+ /**
4
+ * Every user-visible string the sidebar renders on its own behalf.
5
+ *
6
+ * Labels for menu items, groups and popovers come from the consumer as props,
7
+ * so they are already localisable. The strings collected here are the ones the
8
+ * component library hard-codes internally — visible text (`chat`, `beta`) and
9
+ * assistive-technology text (`navigation`, `expandSidebar`, `pinItem`, …).
10
+ *
11
+ * Override them once on `SidebarProvider`:
12
+ *
13
+ * ```tsx
14
+ * <SidebarProvider labels={{ chat: "Chat", expandSidebar: "Ouvrir le menu" }}>
15
+ * ```
16
+ *
17
+ * Every override is optional — omitted keys fall back to
18
+ * {@link DEFAULT_SIDEBAR_LABELS}. Individual components also accept per-instance
19
+ * label props that take precedence over the provider value.
20
+ */
21
+ interface SidebarLabels {
22
+ /** `aria-label` on the root `role="navigation"` landmark. */
23
+ navigation: string;
24
+ /** `aria-label` on the toggle when the sidebar is collapsed. */
25
+ expandSidebar: string;
26
+ /** `aria-label` on the toggle when the sidebar is expanded. */
27
+ collapseSidebar: string;
28
+ /** Visible text on the expanded-mode chat button. */
29
+ chat: string;
30
+ /** `aria-label` on the collapsed-mode icon-only chat button. */
31
+ openChat: string;
32
+ /** Pin-toggle tooltip when the item is not pinned. */
33
+ pin: string;
34
+ /** Pin-toggle tooltip when the item is pinned. */
35
+ unpin: string;
36
+ /** Pin-toggle `aria-label` when the item is not pinned. */
37
+ pinItem: string;
38
+ /** Pin-toggle `aria-label` when the item is pinned. */
39
+ unpinItem: string;
40
+ /** Visible text in the trailing "Beta" tag. */
41
+ beta: string;
42
+ /** Default label for the collapsed-mode pinned-shortcuts popover. */
43
+ pinned: string;
44
+ }
45
+ /** English defaults — used whenever a label is not overridden. */
46
+ declare const DEFAULT_SIDEBAR_LABELS: SidebarLabels;
47
+ /**
48
+ * Merge a partial override map over {@link DEFAULT_SIDEBAR_LABELS}. Returns the
49
+ * shared default object untouched when there is nothing to override, so the
50
+ * common case allocates nothing.
51
+ */
52
+ declare const resolveSidebarLabels: (overrides?: Partial<SidebarLabels>) => SidebarLabels;
53
+
3
54
  type SidebarLinkClickHandler = (event?: MouseEvent<HTMLElement>) => void;
4
55
  type SidebarLinkActiveCheck = (match: unknown, location: {
5
56
  pathname: string;
@@ -27,12 +78,20 @@ interface SidebarContextValue {
27
78
  LinkComponent: React.ComponentType<SidebarLinkProps>;
28
79
  expandedId: string | null;
29
80
  onExpandedIdChange: (id: string | null) => void;
81
+ /** Fully-resolved label set — provider overrides merged over the defaults. */
82
+ labels: SidebarLabels;
30
83
  }
31
84
  interface SidebarProviderProps {
32
85
  collapsed?: boolean;
33
86
  onCollapsedChange?: (collapsed: boolean) => void;
34
87
  pathname?: string;
35
88
  linkComponent?: React.ComponentType<SidebarLinkProps>;
89
+ /**
90
+ * Translations for the strings the sidebar renders on its own behalf
91
+ * (chat button, collapse/expand toggle, pin controls, "Beta" tag, nav
92
+ * landmark). Partial — omitted keys keep their English default.
93
+ */
94
+ labels?: Partial<SidebarLabels>;
36
95
  children: ReactNode;
37
96
  testID?: string;
38
97
  }
@@ -91,6 +150,10 @@ type SidebarItemType = {
91
150
  * </SidebarFooter>
92
151
  * </Sidebar>
93
152
  * </SidebarProvider>
153
+ *
154
+ * Strings the sidebar renders on its own behalf (nav landmark, chat button,
155
+ * collapse toggle, pin controls, "Beta" tag) are localised through the
156
+ * `labels` prop on `SidebarProvider`.
94
157
  */
95
158
 
96
159
  interface SidebarProps {
@@ -106,6 +169,12 @@ interface SidebarProps {
106
169
  onChatClick?: () => void;
107
170
  /** Whether the chat button shows a notification badge */
108
171
  chatBadge?: boolean;
172
+ /**
173
+ * `aria-label` for the navigation landmark. Defaults to the provider's
174
+ * `navigation` label; set this when a page renders more than one sidebar and
175
+ * each landmark needs a distinct name.
176
+ */
177
+ navigationLabel?: string;
109
178
  children: ReactNode;
110
179
  testID?: string;
111
180
  }
@@ -119,7 +188,14 @@ declare const SidebarFooter: React.FC<{
119
188
  children: ReactNode;
120
189
  }>;
121
190
 
122
- declare const SidebarTrigger: React.FC;
191
+ interface SidebarTriggerProps {
192
+ /** `aria-label` used while collapsed. Defaults to the provider's `expandSidebar` label. */
193
+ expandLabel?: string;
194
+ /** `aria-label` used while expanded. Defaults to the provider's `collapseSidebar` label. */
195
+ collapseLabel?: string;
196
+ testID?: string;
197
+ }
198
+ declare const SidebarTrigger: React.FC<SidebarTriggerProps>;
123
199
 
124
200
  interface SidebarGroupProps {
125
201
  label?: string;
@@ -158,6 +234,16 @@ interface SidebarMenuItemProps {
158
234
  extra?: ReactNode;
159
235
  /** Whether this item is inside a SidebarMenuSub (parent collapsible sets nested styling) */
160
236
  isNested?: boolean;
237
+ /** Pin-toggle tooltip while unpinned. Defaults to the provider's `pin` label. */
238
+ pinLabel?: string;
239
+ /** Pin-toggle tooltip while pinned. Defaults to the provider's `unpin` label. */
240
+ unpinLabel?: string;
241
+ /** Pin-toggle `aria-label` while unpinned. Defaults to the provider's `pinItem` label. */
242
+ pinAriaLabel?: string;
243
+ /** Pin-toggle `aria-label` while pinned. Defaults to the provider's `unpinItem` label. */
244
+ unpinAriaLabel?: string;
245
+ /** Text inside the trailing tag when `beta` is set. Defaults to the provider's `beta` label. */
246
+ betaLabel?: string;
161
247
  testID?: string;
162
248
  }
163
249
  declare const SidebarMenuItem: React.FC<SidebarMenuItemProps>;
@@ -185,6 +271,8 @@ declare const SidebarMenuSub: React.FC<{
185
271
  interface SidebarChatButtonProps {
186
272
  onClick?: () => void;
187
273
  badge?: boolean;
274
+ /** Visible button text. Defaults to the provider's `chat` label. */
275
+ label?: string;
188
276
  testID?: string;
189
277
  }
190
278
  declare const SidebarChatButton: React.FC<SidebarChatButtonProps>;
@@ -197,6 +285,10 @@ interface SidebarCollapsedProps {
197
285
  onChatClick?: () => void;
198
286
  showChat?: boolean;
199
287
  chatBadge?: boolean;
288
+ /** `aria-label` for the icon-only chat button. Defaults to the provider's `openChat` label. */
289
+ chatAriaLabel?: string;
290
+ /** `aria-label` for the expand toggle. Defaults to the provider's `expandSidebar` label. */
291
+ expandLabel?: string;
200
292
  testID?: string;
201
293
  }
202
294
  declare const SidebarCollapsed: React.FC<SidebarCollapsedProps>;
@@ -234,10 +326,14 @@ declare const SidebarPinnedList: React.FC<SidebarPinnedListProps>;
234
326
  * Helper for the collapsed sidebar: returns a single `SidebarItemType` whose
235
327
  * popover lists every pinned shortcut. Spread it into `collapsedItems` at the
236
328
  * position you want the Pin button to appear. Returns `null` when no items.
329
+ *
330
+ * This is a plain function rather than a component, so it cannot read the
331
+ * `SidebarProvider` labels — pass `options.label` with your translated string
332
+ * to localise the popover title (defaults to the English "Pinned").
237
333
  */
238
334
  declare const getPinnedCollapsedItem: (items: SidebarPinnedItem[], options?: {
239
335
  label?: string;
240
336
  dataId?: string;
241
337
  }) => SidebarItemType | null;
242
338
 
243
- export { Sidebar, SidebarChatButton, SidebarCollapsed, type SidebarCollapsedProps, SidebarContent, SidebarFooter, SidebarGroup, type SidebarItemType, type SidebarLinkActiveCheck, type SidebarLinkClickHandler, type SidebarLinkProps, SidebarMenu, SidebarMenuCollapsible, type SidebarMenuCollapsibleProps, SidebarMenuItem, type SidebarMenuItemProps, SidebarMenuSub, type SidebarPinnedItem, SidebarPinnedList, type SidebarPinnedListProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarTrigger, getPinnedCollapsedItem, useSidebar };
339
+ export { DEFAULT_SIDEBAR_LABELS, Sidebar, SidebarChatButton, type SidebarChatButtonProps, SidebarCollapsed, type SidebarCollapsedProps, SidebarContent, SidebarFooter, SidebarGroup, type SidebarItemType, type SidebarLabels, type SidebarLinkActiveCheck, type SidebarLinkClickHandler, type SidebarLinkProps, SidebarMenu, SidebarMenuCollapsible, type SidebarMenuCollapsibleProps, SidebarMenuItem, type SidebarMenuItemProps, SidebarMenuSub, type SidebarPinnedItem, SidebarPinnedList, type SidebarPinnedListProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarTrigger, type SidebarTriggerProps, getPinnedCollapsedItem, resolveSidebarLabels, useSidebar };
package/native/index.d.ts CHANGED
@@ -1,5 +1,56 @@
1
1
  import React, { MouseEvent, ReactNode } from 'react';
2
2
 
3
+ /**
4
+ * Every user-visible string the sidebar renders on its own behalf.
5
+ *
6
+ * Labels for menu items, groups and popovers come from the consumer as props,
7
+ * so they are already localisable. The strings collected here are the ones the
8
+ * component library hard-codes internally — visible text (`chat`, `beta`) and
9
+ * assistive-technology text (`navigation`, `expandSidebar`, `pinItem`, …).
10
+ *
11
+ * Override them once on `SidebarProvider`:
12
+ *
13
+ * ```tsx
14
+ * <SidebarProvider labels={{ chat: "Chat", expandSidebar: "Ouvrir le menu" }}>
15
+ * ```
16
+ *
17
+ * Every override is optional — omitted keys fall back to
18
+ * {@link DEFAULT_SIDEBAR_LABELS}. Individual components also accept per-instance
19
+ * label props that take precedence over the provider value.
20
+ */
21
+ interface SidebarLabels {
22
+ /** `aria-label` on the root `role="navigation"` landmark. */
23
+ navigation: string;
24
+ /** `aria-label` on the toggle when the sidebar is collapsed. */
25
+ expandSidebar: string;
26
+ /** `aria-label` on the toggle when the sidebar is expanded. */
27
+ collapseSidebar: string;
28
+ /** Visible text on the expanded-mode chat button. */
29
+ chat: string;
30
+ /** `aria-label` on the collapsed-mode icon-only chat button. */
31
+ openChat: string;
32
+ /** Pin-toggle tooltip when the item is not pinned. */
33
+ pin: string;
34
+ /** Pin-toggle tooltip when the item is pinned. */
35
+ unpin: string;
36
+ /** Pin-toggle `aria-label` when the item is not pinned. */
37
+ pinItem: string;
38
+ /** Pin-toggle `aria-label` when the item is pinned. */
39
+ unpinItem: string;
40
+ /** Visible text in the trailing "Beta" tag. */
41
+ beta: string;
42
+ /** Default label for the collapsed-mode pinned-shortcuts popover. */
43
+ pinned: string;
44
+ }
45
+ /** English defaults — used whenever a label is not overridden. */
46
+ declare const DEFAULT_SIDEBAR_LABELS: SidebarLabels;
47
+ /**
48
+ * Merge a partial override map over {@link DEFAULT_SIDEBAR_LABELS}. Returns the
49
+ * shared default object untouched when there is nothing to override, so the
50
+ * common case allocates nothing.
51
+ */
52
+ declare const resolveSidebarLabels: (overrides?: Partial<SidebarLabels>) => SidebarLabels;
53
+
3
54
  type SidebarLinkClickHandler = (event?: MouseEvent<HTMLElement>) => void;
4
55
  type SidebarLinkActiveCheck = (match: unknown, location: {
5
56
  pathname: string;
@@ -27,12 +78,20 @@ interface SidebarContextValue {
27
78
  LinkComponent: React.ComponentType<SidebarLinkProps>;
28
79
  expandedId: string | null;
29
80
  onExpandedIdChange: (id: string | null) => void;
81
+ /** Fully-resolved label set — provider overrides merged over the defaults. */
82
+ labels: SidebarLabels;
30
83
  }
31
84
  interface SidebarProviderProps {
32
85
  collapsed?: boolean;
33
86
  onCollapsedChange?: (collapsed: boolean) => void;
34
87
  pathname?: string;
35
88
  linkComponent?: React.ComponentType<SidebarLinkProps>;
89
+ /**
90
+ * Translations for the strings the sidebar renders on its own behalf
91
+ * (chat button, collapse/expand toggle, pin controls, "Beta" tag, nav
92
+ * landmark). Partial — omitted keys keep their English default.
93
+ */
94
+ labels?: Partial<SidebarLabels>;
36
95
  children: ReactNode;
37
96
  testID?: string;
38
97
  }
@@ -91,6 +150,10 @@ type SidebarItemType = {
91
150
  * </SidebarFooter>
92
151
  * </Sidebar>
93
152
  * </SidebarProvider>
153
+ *
154
+ * Strings the sidebar renders on its own behalf (nav landmark, chat button,
155
+ * collapse toggle, pin controls, "Beta" tag) are localised through the
156
+ * `labels` prop on `SidebarProvider`.
94
157
  */
95
158
 
96
159
  interface SidebarProps {
@@ -106,6 +169,12 @@ interface SidebarProps {
106
169
  onChatClick?: () => void;
107
170
  /** Whether the chat button shows a notification badge */
108
171
  chatBadge?: boolean;
172
+ /**
173
+ * `aria-label` for the navigation landmark. Defaults to the provider's
174
+ * `navigation` label; set this when a page renders more than one sidebar and
175
+ * each landmark needs a distinct name.
176
+ */
177
+ navigationLabel?: string;
109
178
  children: ReactNode;
110
179
  testID?: string;
111
180
  }
@@ -119,7 +188,14 @@ declare const SidebarFooter: React.FC<{
119
188
  children: ReactNode;
120
189
  }>;
121
190
 
122
- declare const SidebarTrigger: React.FC;
191
+ interface SidebarTriggerProps {
192
+ /** `aria-label` used while collapsed. Defaults to the provider's `expandSidebar` label. */
193
+ expandLabel?: string;
194
+ /** `aria-label` used while expanded. Defaults to the provider's `collapseSidebar` label. */
195
+ collapseLabel?: string;
196
+ testID?: string;
197
+ }
198
+ declare const SidebarTrigger: React.FC<SidebarTriggerProps>;
123
199
 
124
200
  interface SidebarGroupProps {
125
201
  label?: string;
@@ -158,6 +234,16 @@ interface SidebarMenuItemProps {
158
234
  extra?: ReactNode;
159
235
  /** Whether this item is inside a SidebarMenuSub (parent collapsible sets nested styling) */
160
236
  isNested?: boolean;
237
+ /** Pin-toggle tooltip while unpinned. Defaults to the provider's `pin` label. */
238
+ pinLabel?: string;
239
+ /** Pin-toggle tooltip while pinned. Defaults to the provider's `unpin` label. */
240
+ unpinLabel?: string;
241
+ /** Pin-toggle `aria-label` while unpinned. Defaults to the provider's `pinItem` label. */
242
+ pinAriaLabel?: string;
243
+ /** Pin-toggle `aria-label` while pinned. Defaults to the provider's `unpinItem` label. */
244
+ unpinAriaLabel?: string;
245
+ /** Text inside the trailing tag when `beta` is set. Defaults to the provider's `beta` label. */
246
+ betaLabel?: string;
161
247
  testID?: string;
162
248
  }
163
249
  declare const SidebarMenuItem: React.FC<SidebarMenuItemProps>;
@@ -185,6 +271,8 @@ declare const SidebarMenuSub: React.FC<{
185
271
  interface SidebarChatButtonProps {
186
272
  onClick?: () => void;
187
273
  badge?: boolean;
274
+ /** Visible button text. Defaults to the provider's `chat` label. */
275
+ label?: string;
188
276
  testID?: string;
189
277
  }
190
278
  declare const SidebarChatButton: React.FC<SidebarChatButtonProps>;
@@ -197,6 +285,10 @@ interface SidebarCollapsedProps {
197
285
  onChatClick?: () => void;
198
286
  showChat?: boolean;
199
287
  chatBadge?: boolean;
288
+ /** `aria-label` for the icon-only chat button. Defaults to the provider's `openChat` label. */
289
+ chatAriaLabel?: string;
290
+ /** `aria-label` for the expand toggle. Defaults to the provider's `expandSidebar` label. */
291
+ expandLabel?: string;
200
292
  testID?: string;
201
293
  }
202
294
  declare const SidebarCollapsed: React.FC<SidebarCollapsedProps>;
@@ -234,10 +326,14 @@ declare const SidebarPinnedList: React.FC<SidebarPinnedListProps>;
234
326
  * Helper for the collapsed sidebar: returns a single `SidebarItemType` whose
235
327
  * popover lists every pinned shortcut. Spread it into `collapsedItems` at the
236
328
  * position you want the Pin button to appear. Returns `null` when no items.
329
+ *
330
+ * This is a plain function rather than a component, so it cannot read the
331
+ * `SidebarProvider` labels — pass `options.label` with your translated string
332
+ * to localise the popover title (defaults to the English "Pinned").
237
333
  */
238
334
  declare const getPinnedCollapsedItem: (items: SidebarPinnedItem[], options?: {
239
335
  label?: string;
240
336
  dataId?: string;
241
337
  }) => SidebarItemType | null;
242
338
 
243
- export { Sidebar, SidebarChatButton, SidebarCollapsed, type SidebarCollapsedProps, SidebarContent, SidebarFooter, SidebarGroup, type SidebarItemType, type SidebarLinkActiveCheck, type SidebarLinkClickHandler, type SidebarLinkProps, SidebarMenu, SidebarMenuCollapsible, type SidebarMenuCollapsibleProps, SidebarMenuItem, type SidebarMenuItemProps, SidebarMenuSub, type SidebarPinnedItem, SidebarPinnedList, type SidebarPinnedListProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarTrigger, getPinnedCollapsedItem, useSidebar };
339
+ export { DEFAULT_SIDEBAR_LABELS, Sidebar, SidebarChatButton, type SidebarChatButtonProps, SidebarCollapsed, type SidebarCollapsedProps, SidebarContent, SidebarFooter, SidebarGroup, type SidebarItemType, type SidebarLabels, type SidebarLinkActiveCheck, type SidebarLinkClickHandler, type SidebarLinkProps, SidebarMenu, SidebarMenuCollapsible, type SidebarMenuCollapsibleProps, SidebarMenuItem, type SidebarMenuItemProps, SidebarMenuSub, type SidebarPinnedItem, SidebarPinnedList, type SidebarPinnedListProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarTrigger, type SidebarTriggerProps, getPinnedCollapsedItem, resolveSidebarLabels, useSidebar };