@xsolla/xui-segmented 0.99.0 → 0.101.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 +207 -26
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,47 +1,228 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Segmented
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A cross-platform React segmented control component for switching between related views or filters. Similar to iOS's UISegmentedControl.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
+
npm install @xsolla/xui-segmented
|
|
9
|
+
# or
|
|
8
10
|
yarn add @xsolla/xui-segmented
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## Demo
|
|
14
|
+
|
|
15
|
+
### Basic Segmented
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import * as React from 'react';
|
|
19
|
+
import { Segmented } from '@xsolla/xui-segmented';
|
|
20
|
+
|
|
21
|
+
export default function BasicSegmented() {
|
|
22
|
+
const [active, setActive] = React.useState('day');
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Segmented
|
|
26
|
+
items={[
|
|
27
|
+
{ id: 'day', label: 'Day' },
|
|
28
|
+
{ id: 'week', label: 'Week' },
|
|
29
|
+
{ id: 'month', label: 'Month' },
|
|
30
|
+
]}
|
|
31
|
+
activeId={active}
|
|
32
|
+
onChange={setActive}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### With Icons
|
|
12
39
|
|
|
13
40
|
```tsx
|
|
41
|
+
import * as React from 'react';
|
|
42
|
+
import { Segmented } from '@xsolla/xui-segmented';
|
|
43
|
+
import { Grid, List } from '@xsolla/xui-icons-base';
|
|
44
|
+
|
|
45
|
+
export default function IconSegmented() {
|
|
46
|
+
const [active, setActive] = React.useState('grid');
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Segmented
|
|
50
|
+
items={[
|
|
51
|
+
{ id: 'grid', label: 'Grid', icon: <Grid size={16} /> },
|
|
52
|
+
{ id: 'list', label: 'List', icon: <List size={16} /> },
|
|
53
|
+
]}
|
|
54
|
+
activeId={active}
|
|
55
|
+
onChange={setActive}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Full Width
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import * as React from 'react';
|
|
65
|
+
import { Segmented } from '@xsolla/xui-segmented';
|
|
66
|
+
|
|
67
|
+
export default function FullWidthSegmented() {
|
|
68
|
+
const [active, setActive] = React.useState('all');
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div style={{ width: 400 }}>
|
|
72
|
+
<Segmented
|
|
73
|
+
fullWidth={true}
|
|
74
|
+
items={[
|
|
75
|
+
{ id: 'all', label: 'All' },
|
|
76
|
+
{ id: 'active', label: 'Active' },
|
|
77
|
+
{ id: 'completed', label: 'Completed' },
|
|
78
|
+
]}
|
|
79
|
+
activeId={active}
|
|
80
|
+
onChange={setActive}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Anatomy
|
|
88
|
+
|
|
89
|
+
```jsx
|
|
14
90
|
import { Segmented } from '@xsolla/xui-segmented';
|
|
15
91
|
|
|
16
92
|
<Segmented
|
|
17
|
-
items={[
|
|
18
|
-
{ id: '
|
|
19
|
-
{ id: '
|
|
20
|
-
{ id: 'month', label: 'Month' },
|
|
93
|
+
items={[ // Array of segment items
|
|
94
|
+
{ id: 'a', label: 'A' },
|
|
95
|
+
{ id: 'b', label: 'B' },
|
|
21
96
|
]}
|
|
22
|
-
activeId="
|
|
23
|
-
onChange={
|
|
97
|
+
activeId="a" // Currently active item ID
|
|
98
|
+
onChange={handleChange} // Selection change handler
|
|
99
|
+
size="md" // Size variant
|
|
100
|
+
stroke={false} // Show border around container
|
|
101
|
+
fullWidth={false} // Expand to container width
|
|
24
102
|
/>
|
|
25
103
|
```
|
|
26
104
|
|
|
27
|
-
##
|
|
105
|
+
## Examples
|
|
106
|
+
|
|
107
|
+
### Segmented Sizes
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import * as React from 'react';
|
|
111
|
+
import { Segmented } from '@xsolla/xui-segmented';
|
|
112
|
+
|
|
113
|
+
export default function SegmentedSizes() {
|
|
114
|
+
const items = [
|
|
115
|
+
{ id: 'a', label: 'Option A' },
|
|
116
|
+
{ id: 'b', label: 'Option B' },
|
|
117
|
+
{ id: 'c', label: 'Option C' },
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
|
|
122
|
+
<Segmented size="sm" items={items} activeId="a" />
|
|
123
|
+
<Segmented size="md" items={items} activeId="a" />
|
|
124
|
+
<Segmented size="lg" items={items} activeId="a" />
|
|
125
|
+
<Segmented size="xl" items={items} activeId="a" />
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### With Stroke Border
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import * as React from 'react';
|
|
135
|
+
import { Segmented } from '@xsolla/xui-segmented';
|
|
136
|
+
|
|
137
|
+
export default function StrokeSegmented() {
|
|
138
|
+
const [active, setActive] = React.useState('left');
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<Segmented
|
|
142
|
+
stroke={true}
|
|
143
|
+
items={[
|
|
144
|
+
{ id: 'left', label: 'Left' },
|
|
145
|
+
{ id: 'center', label: 'Center' },
|
|
146
|
+
{ id: 'right', label: 'Right' },
|
|
147
|
+
]}
|
|
148
|
+
activeId={active}
|
|
149
|
+
onChange={setActive}
|
|
150
|
+
/>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### With Disabled Items
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import * as React from 'react';
|
|
159
|
+
import { Segmented } from '@xsolla/xui-segmented';
|
|
160
|
+
|
|
161
|
+
export default function DisabledItemSegmented() {
|
|
162
|
+
const [active, setActive] = React.useState('enabled1');
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<Segmented
|
|
166
|
+
items={[
|
|
167
|
+
{ id: 'enabled1', label: 'Enabled' },
|
|
168
|
+
{ id: 'disabled', label: 'Disabled', disabled: true },
|
|
169
|
+
{ id: 'enabled2', label: 'Enabled' },
|
|
170
|
+
]}
|
|
171
|
+
activeId={active}
|
|
172
|
+
onChange={setActive}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## API Reference
|
|
28
179
|
|
|
29
180
|
### Segmented
|
|
30
181
|
|
|
182
|
+
**Segmented Props:**
|
|
183
|
+
|
|
31
184
|
| Prop | Type | Default | Description |
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
185
|
+
| :--- | :--- | :------ | :---------- |
|
|
186
|
+
| items | `SegmentedItemType[]` | - | **Required.** Array of segment items. |
|
|
187
|
+
| activeId | `string` | - | ID of the currently active item. |
|
|
188
|
+
| onChange | `(id: string) => void` | - | Selection change handler. |
|
|
189
|
+
| size | `"xl" \| "lg" \| "md" \| "sm"` | `"md"` | Size variant. |
|
|
190
|
+
| stroke | `boolean` | `false` | Show border around container. |
|
|
191
|
+
| fullWidth | `boolean` | `false` | Expand segments to fill container width. |
|
|
192
|
+
| id | `string` | - | HTML id attribute. |
|
|
193
|
+
| testID | `string` | - | Test identifier. |
|
|
194
|
+
|
|
195
|
+
**SegmentedItemType:**
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
interface SegmentedItemType {
|
|
199
|
+
id: string; // Unique identifier
|
|
200
|
+
label: string; // Display text
|
|
201
|
+
icon?: ReactNode; // Optional icon
|
|
202
|
+
disabled?: boolean; // Disabled state
|
|
203
|
+
"aria-label"?: string; // Accessible label
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Keyboard Navigation
|
|
208
|
+
|
|
209
|
+
| Key | Action |
|
|
210
|
+
| :-- | :----- |
|
|
211
|
+
| Arrow Right/Down | Move to next item |
|
|
212
|
+
| Arrow Left/Up | Move to previous item |
|
|
213
|
+
| Enter/Space | Select focused item |
|
|
214
|
+
|
|
215
|
+
## Behavior
|
|
216
|
+
|
|
217
|
+
- Active segment has elevated background
|
|
218
|
+
- Disabled segments show reduced opacity
|
|
219
|
+
- Keyboard navigation wraps around
|
|
220
|
+
- Hover effect on non-active segments
|
|
221
|
+
|
|
222
|
+
## Accessibility
|
|
223
|
+
|
|
224
|
+
- Uses `role="radiogroup"` on container
|
|
225
|
+
- Each segment has `role="radio"`
|
|
226
|
+
- `aria-checked` indicates selection state
|
|
227
|
+
- `aria-disabled` for disabled items
|
|
228
|
+
- Roving tabindex for keyboard navigation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-segmented",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.101.0",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"build:native": "PLATFORM=native tsup"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@xsolla/xui-badge": "0.
|
|
14
|
-
"@xsolla/xui-core": "0.
|
|
15
|
-
"@xsolla/xui-primitives-core": "0.
|
|
13
|
+
"@xsolla/xui-badge": "0.101.0",
|
|
14
|
+
"@xsolla/xui-core": "0.101.0",
|
|
15
|
+
"@xsolla/xui-primitives-core": "0.101.0"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
18
|
"react": ">=16.8.0",
|