@xsolla/xui-tabs 0.174.3 → 0.176.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 +75 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
# Tabs
|
|
2
2
|
|
|
3
3
|
A cross-platform React tab list with two visual variants — `line` (default underlined) and `segmented` (button-group with sliding indicator on web). Implements the WAI-ARIA tablist pattern with full keyboard navigation.
|
|
4
|
+
<!-- BEGIN:xui-mcp-instructions:tabs -->
|
|
5
|
+
A horizontal navigation bar that divides related content into labelled sections. The user switches between sections by clicking a tab item; only one section is active at a time. Each tab can optionally carry a numeric counter badge. Tabs support 2 to 7 items, four sizes, and two alignment modes.
|
|
6
|
+
|
|
7
|
+
### When to use
|
|
8
|
+
|
|
9
|
+
To organise content that belongs to the same context into distinct, peer-level views — for example, *"Overview"*, *"Activity"*, *"Settings"* on a profile page
|
|
10
|
+
|
|
11
|
+
When users need to switch between views without leaving the current page or losing their position in the layout
|
|
12
|
+
|
|
13
|
+
When the number of views is small (2–7) and all labels fit horizontally without truncation
|
|
14
|
+
|
|
15
|
+
### When not to use
|
|
16
|
+
|
|
17
|
+
- When the sections represent a sequence or progression — use a Stepper instead
|
|
18
|
+
- When there are more than 7 tabs — consider a a sidebar navigation, or collapsing less-used items into an overflow menu
|
|
19
|
+
- When the content under each tab is very long and users will rarely switch between them — use anchored sections with a sticky sidebar nav instead
|
|
20
|
+
- As the primary page-level navigation — use a Navigation bar or Sidebar for top-level routing
|
|
21
|
+
|
|
22
|
+
### Content guidelines
|
|
23
|
+
|
|
24
|
+
Tab labels — use short nouns or noun phrases: *"Overview"*, *"Activity"*, *"Members"*, *"Settings"*, *"Billing"*. Avoid verbs (*"Manage settings"*) and questions (*"What's new?"*).
|
|
25
|
+
|
|
26
|
+
Label length — aim for 1–2 words per label. Three words is a maximum. Never truncate a tab label with an ellipsis — if the label is too long, shorten it.
|
|
27
|
+
|
|
28
|
+
Consistency — all labels in the same Tabs instance should follow the same grammatical form and approximate length. Mixing a single-word label (*"Users"*) with a long phrase (*"Billing & Payments"*) in the same bar looks unbalanced.
|
|
29
|
+
|
|
30
|
+
Counter values — show only counts that are directly actionable or informative. Avoid counters that show total records (e.g. *"1,452 transactions"*) — that belongs in the panel content, not the tab.
|
|
31
|
+
|
|
32
|
+
Show the counter only when the number is meaningful — when it communicates something actionable (unread messages, pending approvals, new results)
|
|
33
|
+
- Do not show a counter of 0 — hide the badge entirely when the count is zero
|
|
34
|
+
- Cap the display at 99+. Display *"99+"* for values ≥ 100 rather than showing a 3-digit number
|
|
35
|
+
- The counter palette should match the tab's contextual state: use Brand on the active tab, Default on inactive tabs
|
|
36
|
+
- Badge rendered at the far right of the tab item. Enable with badge=true. Unlike the counter, it carries no number — it signals only that something new or unseen exists in that section.
|
|
37
|
+
- Hide the counter entirely when the count is zero — do not show *"0"*
|
|
38
|
+
|
|
39
|
+
### Behaviour guidelines
|
|
40
|
+
|
|
41
|
+
Tab switching — clicking a Default tab immediately switches the active view: the clicked tab transitions to State=Active, the previously active tab returns to State=Default, and the associated content panel below is shown/hidden accordingly. There is no transition animation on the content unless the product design calls for it.
|
|
42
|
+
|
|
43
|
+
Active state persistence — the active tab should be preserved across filter changes, searches, and other in-page interactions. Only navigate away from the active tab if the user explicitly clicks a different one.
|
|
44
|
+
|
|
45
|
+
Disabled tabs — use State=Disable only when a section is temporarily inaccessible (e.g. insufficient permissions, feature not yet available). Always provide a tooltip or nearby explanation for why the tab is disabled. Never disable all tabs simultaneously.
|
|
46
|
+
|
|
47
|
+
Counter updates — counter values should update in real time when new data arrives (e.g. a new message). Update the .counter-tab-item value without remounting the Tabs component. If the count drops to 0, remove the badge rather than showing *"0"*.
|
|
48
|
+
|
|
49
|
+
Overflow handling — the Tabs component does not support horizontal scrolling or overflow menus natively. If the number of items exceeds 7 or the labels overflow their containers, this is a design problem — shorten the labels or reduce the item count rather than implementing a scroll container.
|
|
50
|
+
|
|
51
|
+
URL routing — when tabs represent different routes or states that should be bookmarkable or shareable, reflect the active tab in the URL (query param or path segment). On page load, restore the active tab from the URL.
|
|
52
|
+
|
|
53
|
+
Align left with dynamic content — when Align left=True and tab labels can change at runtime (e.g. localised strings of varying length), ensure the container has a minimum width and the tab bar does not collapse narrower than the shortest label.
|
|
54
|
+
|
|
55
|
+
### Accessibility
|
|
56
|
+
|
|
57
|
+
The Tabs container must use role=*"tablist"* with an aria-label describing the group (e.g. aria-label=*"Account sections"*).
|
|
58
|
+
|
|
59
|
+
Each .tab-item must use role=*"tab"* with aria-selected=*"true"* for the active tab and aria-selected=*"false"* for all others. Disabled tabs must also have aria-disabled=*"true"*.
|
|
60
|
+
|
|
61
|
+
Each tab must have aria-controls pointing to the id of its associated content panel. The content panel must have role=*"tabpanel"* and aria-labelledby pointing back to the tab's id.
|
|
62
|
+
Keyboard navigation within the tab list:
|
|
63
|
+
- ← / → arrows move focus between tabs (automatic activation or manual activation depending on product preference)
|
|
64
|
+
- Home moves focus to the first tab; End moves focus to the last tab
|
|
65
|
+
- Enter / Space activates the focused tab in manual-activation mode
|
|
66
|
+
- Tab moves focus out of the tab list into the active panel's content
|
|
67
|
+
|
|
68
|
+
← / → arrows move focus between tabs (automatic activation or manual activation depending on product preference)
|
|
69
|
+
- Home moves focus to the first tab; End moves focus to the last tab
|
|
70
|
+
- Enter / Space activates the focused tab in manual-activation mode
|
|
71
|
+
- Tab moves focus out of the tab list into the active panel's content
|
|
72
|
+
- When a counter is present, include its value in the tab's aria-label — e.g. aria-label=*"Activity, 5 unread"* — so screen readers announce the count without requiring navigation to the badge.
|
|
73
|
+
- When a badge is present (dot only, no number), include a qualitative description in aria-label — e.g. aria-label=*"Messages, new"*.
|
|
74
|
+
- Icon-only tabs (label=false) must have aria-label with the tab name — the icon alone is not sufficient for screen readers.
|
|
75
|
+
- Decorative icons within a tab (when a label is also present) must have aria-hidden=*"true"* so they are not announced redundantly alongside the label.
|
|
76
|
+
- Disabled tabs must remain focusable (do not use tabindex=*"-1"* on disabled tabs) so keyboard users can discover them. Announce the reason they are disabled via aria-describedby.
|
|
77
|
+
- The active indicator underline must not be communicated by colour alone — the aria-selected attribute is the primary signal for assistive technology.
|
|
78
|
+
<!-- END:xui-mcp-instructions:tabs -->
|
|
4
79
|
|
|
5
80
|
## Installation
|
|
6
81
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-tabs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.176.0",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"test:watch": "vitest"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@xsolla/xui-badge": "0.
|
|
16
|
-
"@xsolla/xui-core": "0.
|
|
17
|
-
"@xsolla/xui-primitives-core": "0.
|
|
15
|
+
"@xsolla/xui-badge": "0.176.0",
|
|
16
|
+
"@xsolla/xui-core": "0.176.0",
|
|
17
|
+
"@xsolla/xui-primitives-core": "0.176.0"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"react": ">=16.8.0",
|