@xsolla/xui-button 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 +501 -47
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,79 +1,533 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Button
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A cross-platform React button component with primary/secondary variants, multiple color tones, sizes, loading states, and icon support. Works on both React (web) and React Native.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
+
npm install @xsolla/xui-button
|
|
9
|
+
# or
|
|
8
10
|
yarn add @xsolla/xui-button
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## Demo
|
|
14
|
+
|
|
15
|
+
### Basic Button
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import * as React from 'react';
|
|
19
|
+
import { Button } from '@xsolla/xui-button';
|
|
20
|
+
|
|
21
|
+
export default function BasicButton() {
|
|
22
|
+
return (
|
|
23
|
+
<Button onPress={() => console.log('Pressed!')}>
|
|
24
|
+
Click me
|
|
25
|
+
</Button>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Button Variants
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import * as React from 'react';
|
|
34
|
+
import { Button } from '@xsolla/xui-button';
|
|
35
|
+
|
|
36
|
+
export default function ButtonVariants() {
|
|
37
|
+
return (
|
|
38
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
39
|
+
<Button variant="primary">Primary</Button>
|
|
40
|
+
<Button variant="secondary">Secondary</Button>
|
|
41
|
+
<Button variant="tertiary">Tertiary</Button>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Button Tones
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import * as React from 'react';
|
|
51
|
+
import { Button } from '@xsolla/xui-button';
|
|
52
|
+
|
|
53
|
+
export default function ButtonTones() {
|
|
54
|
+
return (
|
|
55
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
56
|
+
<Button tone="brand">Brand</Button>
|
|
57
|
+
<Button tone="brandExtra">Brand Extra</Button>
|
|
58
|
+
<Button tone="alert">Alert</Button>
|
|
59
|
+
<Button tone="mono">Mono</Button>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Button Sizes
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import * as React from 'react';
|
|
69
|
+
import { Button } from '@xsolla/xui-button';
|
|
70
|
+
|
|
71
|
+
export default function ButtonSizes() {
|
|
72
|
+
return (
|
|
73
|
+
<div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
|
|
74
|
+
<Button size="xs">Extra Small</Button>
|
|
75
|
+
<Button size="sm">Small</Button>
|
|
76
|
+
<Button size="md">Medium</Button>
|
|
77
|
+
<Button size="lg">Large</Button>
|
|
78
|
+
<Button size="xl">Extra Large</Button>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Button with Icons
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import * as React from 'react';
|
|
88
|
+
import { Button } from '@xsolla/xui-button';
|
|
89
|
+
import { Plus, ChevronDown, FileDownloadOut } from '@xsolla/xui-icons-base';
|
|
90
|
+
import { ArrowRight } from '@xsolla/xui-icons';
|
|
91
|
+
|
|
92
|
+
export default function ButtonWithIcons() {
|
|
93
|
+
return (
|
|
94
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
95
|
+
<Button iconLeft={<Plus />}>
|
|
96
|
+
Add Item
|
|
97
|
+
</Button>
|
|
98
|
+
<Button iconRight={<ArrowRight />}>
|
|
99
|
+
Next Step
|
|
100
|
+
</Button>
|
|
101
|
+
<Button
|
|
102
|
+
iconLeft={<FileDownloadOut />}
|
|
103
|
+
iconRight={<ChevronDown />}
|
|
104
|
+
>
|
|
105
|
+
Download
|
|
106
|
+
</Button>
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Loading Button
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import * as React from 'react';
|
|
116
|
+
import { Button } from '@xsolla/xui-button';
|
|
117
|
+
|
|
118
|
+
export default function LoadingButton() {
|
|
119
|
+
const [loading, setLoading] = React.useState(false);
|
|
120
|
+
|
|
121
|
+
const handlePress = () => {
|
|
122
|
+
setLoading(true);
|
|
123
|
+
setTimeout(() => setLoading(false), 2000);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Button loading={loading} onPress={handlePress}>
|
|
128
|
+
{loading ? 'Processing...' : 'Submit'}
|
|
129
|
+
</Button>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Anatomy
|
|
135
|
+
|
|
136
|
+
Import the component and use it directly:
|
|
137
|
+
|
|
138
|
+
```jsx
|
|
139
|
+
import { Button, IconButton, FlexButton, ButtonGroup } from '@xsolla/xui-button';
|
|
140
|
+
import { Plus } from '@xsolla/xui-icons-base';
|
|
141
|
+
|
|
142
|
+
// Basic button
|
|
143
|
+
<Button>Label</Button>
|
|
144
|
+
|
|
145
|
+
// Icon-only button
|
|
146
|
+
<IconButton icon={<Plus />} aria-label="Add item" />
|
|
147
|
+
|
|
148
|
+
// Flexible styling button
|
|
149
|
+
<FlexButton variant="brand">Label</FlexButton>
|
|
150
|
+
|
|
151
|
+
// Group of buttons
|
|
152
|
+
<ButtonGroup>
|
|
153
|
+
<Button>First</Button>
|
|
154
|
+
<Button>Second</Button>
|
|
155
|
+
</ButtonGroup>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Examples
|
|
159
|
+
|
|
160
|
+
### Full Width Button
|
|
161
|
+
|
|
162
|
+
Use the `fullWidth` prop to make the button span the entire container width.
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import * as React from 'react';
|
|
166
|
+
import { Button } from '@xsolla/xui-button';
|
|
167
|
+
|
|
168
|
+
export default function FullWidthButton() {
|
|
169
|
+
return (
|
|
170
|
+
<div style={{ width: 300 }}>
|
|
171
|
+
<Button fullWidth>Full Width Button</Button>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Disabled Button
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import * as React from 'react';
|
|
181
|
+
import { Button } from '@xsolla/xui-button';
|
|
182
|
+
|
|
183
|
+
export default function DisabledButton() {
|
|
184
|
+
return (
|
|
185
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
186
|
+
<Button disabled>Disabled Primary</Button>
|
|
187
|
+
<Button variant="secondary" disabled>Disabled Secondary</Button>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Icon Button
|
|
194
|
+
|
|
195
|
+
Use `IconButton` for buttons that contain only an icon.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import * as React from 'react';
|
|
199
|
+
import { IconButton } from '@xsolla/xui-button';
|
|
200
|
+
import { Plus, TrashCan } from '@xsolla/xui-icons-base';
|
|
201
|
+
import { Settings } from '@xsolla/xui-icons';
|
|
202
|
+
|
|
203
|
+
export default function IconButtonExample() {
|
|
204
|
+
return (
|
|
205
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
206
|
+
<IconButton
|
|
207
|
+
icon={<Plus />}
|
|
208
|
+
aria-label="Add"
|
|
209
|
+
size="md"
|
|
210
|
+
/>
|
|
211
|
+
<IconButton
|
|
212
|
+
icon={<TrashCan />}
|
|
213
|
+
aria-label="Delete"
|
|
214
|
+
tone="alert"
|
|
215
|
+
/>
|
|
216
|
+
<IconButton
|
|
217
|
+
icon={<Settings />}
|
|
218
|
+
aria-label="Settings"
|
|
219
|
+
variant="secondary"
|
|
220
|
+
/>
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Button Group
|
|
227
|
+
|
|
228
|
+
Use `ButtonGroup` to group related buttons together.
|
|
12
229
|
|
|
13
230
|
```tsx
|
|
231
|
+
import * as React from 'react';
|
|
232
|
+
import { Button, ButtonGroup } from '@xsolla/xui-button';
|
|
233
|
+
|
|
234
|
+
export default function ButtonGroupExample() {
|
|
235
|
+
return (
|
|
236
|
+
<ButtonGroup orientation="horizontal" size="md">
|
|
237
|
+
<Button variant="secondary">Cancel</Button>
|
|
238
|
+
<Button>Confirm</Button>
|
|
239
|
+
</ButtonGroup>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Vertical Button Group
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
import * as React from 'react';
|
|
248
|
+
import { Button, ButtonGroup } from '@xsolla/xui-button';
|
|
249
|
+
|
|
250
|
+
export default function VerticalButtonGroup() {
|
|
251
|
+
return (
|
|
252
|
+
<ButtonGroup orientation="vertical" size="md">
|
|
253
|
+
<Button fullWidth>Option 1</Button>
|
|
254
|
+
<Button fullWidth>Option 2</Button>
|
|
255
|
+
<Button fullWidth>Option 3</Button>
|
|
256
|
+
</ButtonGroup>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Flex Button
|
|
262
|
+
|
|
263
|
+
`FlexButton` provides more flexible styling options with different background modes.
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import * as React from 'react';
|
|
267
|
+
import { FlexButton } from '@xsolla/xui-button';
|
|
268
|
+
import { Link } from '@xsolla/xui-icons-base';
|
|
269
|
+
|
|
270
|
+
export default function FlexButtonExample() {
|
|
271
|
+
return (
|
|
272
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
273
|
+
<FlexButton variant="brand" background>
|
|
274
|
+
With Background
|
|
275
|
+
</FlexButton>
|
|
276
|
+
<FlexButton variant="brand">
|
|
277
|
+
Text Only
|
|
278
|
+
</FlexButton>
|
|
279
|
+
<FlexButton variant="tertiary" iconLeft={<Link />}>
|
|
280
|
+
Link Style
|
|
281
|
+
</FlexButton>
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Form Submit Button
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
import * as React from 'react';
|
|
291
|
+
import { Button } from '@xsolla/xui-button';
|
|
292
|
+
|
|
293
|
+
export default function FormSubmitButton() {
|
|
294
|
+
return (
|
|
295
|
+
<form onSubmit={(e) => {
|
|
296
|
+
e.preventDefault();
|
|
297
|
+
console.log('Form submitted');
|
|
298
|
+
}}>
|
|
299
|
+
<Button type="submit">Submit Form</Button>
|
|
300
|
+
</form>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Button with Sublabel
|
|
306
|
+
|
|
307
|
+
Use the `sublabel` prop to add secondary text inline with the main label.
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
import * as React from 'react';
|
|
14
311
|
import { Button } from '@xsolla/xui-button';
|
|
312
|
+
import { Apple } from '@xsolla/xui-icons-brand';
|
|
15
313
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
314
|
+
export default function ButtonWithSublabel() {
|
|
315
|
+
return (
|
|
316
|
+
<Button
|
|
317
|
+
iconLeft={<Apple />}
|
|
318
|
+
sublabel="$39.99"
|
|
319
|
+
labelAlignment="left"
|
|
320
|
+
>
|
|
321
|
+
Buy Now
|
|
322
|
+
</Button>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
19
325
|
```
|
|
20
326
|
|
|
21
|
-
|
|
327
|
+
### Button with Divider
|
|
328
|
+
|
|
329
|
+
The `divider` prop controls whether a separator line appears between icons and content.
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
import * as React from 'react';
|
|
333
|
+
import { Button } from '@xsolla/xui-button';
|
|
334
|
+
import { ArrowRight } from '@xsolla/xui-icons-base';
|
|
335
|
+
|
|
336
|
+
export default function ButtonWithDivider() {
|
|
337
|
+
return (
|
|
338
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
339
|
+
<Button iconRight={<ArrowRight />} divider>
|
|
340
|
+
With Divider
|
|
341
|
+
</Button>
|
|
342
|
+
<Button iconRight={<ArrowRight />} divider={false}>
|
|
343
|
+
No Divider
|
|
344
|
+
</Button>
|
|
345
|
+
</div>
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
```
|
|
22
349
|
|
|
23
|
-
|
|
24
|
-
- **IconButton** — Square icon-only button; requires `aria-label`.
|
|
25
|
-
- **FlexButton** — Compact inline button designed for use inside modals and popups.
|
|
26
|
-
- **ButtonGroup** — Container for grouping related buttons with optional description and error text.
|
|
350
|
+
### Button with Custom Content
|
|
27
351
|
|
|
28
|
-
|
|
352
|
+
Use `customContent` to add badges, tags, or other elements inside the button.
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
import * as React from 'react';
|
|
356
|
+
import { Button } from '@xsolla/xui-button';
|
|
357
|
+
import { Tag } from '@xsolla/xui-tag';
|
|
358
|
+
import { ArrowRight } from '@xsolla/xui-icons-base';
|
|
359
|
+
|
|
360
|
+
export default function ButtonWithCustomContent() {
|
|
361
|
+
return (
|
|
362
|
+
<Button
|
|
363
|
+
iconRight={<ArrowRight />}
|
|
364
|
+
customContent={<Tag size="sm">5x</Tag>}
|
|
365
|
+
divider
|
|
366
|
+
>
|
|
367
|
+
Claim Reward
|
|
368
|
+
</Button>
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Tertiary Variant
|
|
374
|
+
|
|
375
|
+
The tertiary variant provides a minimal, text-like button style.
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
import * as React from 'react';
|
|
379
|
+
import { Button, IconButton } from '@xsolla/xui-button';
|
|
380
|
+
import { Settings } from '@xsolla/xui-icons-base';
|
|
381
|
+
|
|
382
|
+
export default function TertiaryButtons() {
|
|
383
|
+
return (
|
|
384
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
385
|
+
<Button variant="tertiary">Learn More</Button>
|
|
386
|
+
<IconButton
|
|
387
|
+
variant="tertiary"
|
|
388
|
+
icon={<Settings />}
|
|
389
|
+
aria-label="Settings"
|
|
390
|
+
/>
|
|
391
|
+
</div>
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## API Reference
|
|
29
397
|
|
|
30
398
|
### Button
|
|
31
399
|
|
|
400
|
+
The main button component. Renders a semantic `<button>` element.
|
|
401
|
+
|
|
402
|
+
**Button Props:**
|
|
403
|
+
|
|
32
404
|
| Prop | Type | Default | Description |
|
|
33
|
-
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
405
|
+
| :--- | :--- | :------ | :---------- |
|
|
406
|
+
| children | `ReactNode` | - | The button label content. |
|
|
407
|
+
| variant | `"primary" \| "secondary" \| "tertiary"` | `"primary"` | The visual style variant. |
|
|
408
|
+
| tone | `"brand" \| "brandExtra" \| "alert" \| "mono"` | `"brand"` | The color tone of the button. |
|
|
409
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the button. |
|
|
410
|
+
| disabled | `boolean` | `false` | Whether the button is disabled. |
|
|
411
|
+
| loading | `boolean` | `false` | Whether to show loading spinner. Disables interaction when true. |
|
|
412
|
+
| onPress | `() => void` | - | Callback fired when button is pressed. |
|
|
413
|
+
| iconLeft | `ReactNode` | - | Icon to display on the left side. |
|
|
414
|
+
| iconRight | `ReactNode` | - | Icon to display on the right side. |
|
|
415
|
+
| divider | `boolean` | `true` when icon present | Whether to show divider between icon and label. |
|
|
416
|
+
| sublabel | `string` | - | Secondary label text displayed inline with main label at 40% opacity. |
|
|
417
|
+
| labelIcon | `ReactNode` | - | Small icon displayed directly next to the label text. |
|
|
418
|
+
| labelAlignment | `"left" \| "center"` | `"center"` | Alignment of the label content within the button. |
|
|
419
|
+
| customContent | `ReactNode` | - | Custom content slot for badges, tags, or other elements. |
|
|
420
|
+
| fullWidth | `boolean` | `false` | Whether button should span full container width. |
|
|
421
|
+
| type | `"button" \| "submit" \| "reset"` | `"button"` | The HTML button type attribute. |
|
|
422
|
+
| aria-label | `string` | - | Accessible label for the button. |
|
|
423
|
+
| aria-describedby | `string` | - | ID of element that describes the button. |
|
|
424
|
+
| aria-expanded | `boolean` | - | Indicates if controlled element is expanded. |
|
|
425
|
+
| aria-haspopup | `boolean \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog"` | - | Indicates popup type triggered by button. |
|
|
426
|
+
| aria-pressed | `boolean \| "mixed"` | - | Indicates pressed state for toggle buttons. |
|
|
427
|
+
| aria-controls | `string` | - | ID of element controlled by this button. |
|
|
428
|
+
| testID | `string` | - | Test identifier for testing frameworks. |
|
|
429
|
+
| id | `string` | - | HTML id attribute. |
|
|
430
|
+
|
|
431
|
+
---
|
|
44
432
|
|
|
45
433
|
### IconButton
|
|
46
434
|
|
|
435
|
+
A button variant that displays only an icon. Requires `aria-label` for accessibility.
|
|
436
|
+
|
|
437
|
+
**IconButton Props:**
|
|
438
|
+
|
|
47
439
|
| Prop | Type | Default | Description |
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
440
|
+
| :--- | :--- | :------ | :---------- |
|
|
441
|
+
| icon | `ReactNode` | - | **Required.** The icon to display. |
|
|
442
|
+
| aria-label | `string` | - | **Required.** Accessible label for the button. |
|
|
443
|
+
| variant | `"primary" \| "secondary" \| "tertiary"` | `"primary"` | The visual style variant. |
|
|
444
|
+
| tone | `"brand" \| "brandExtra" \| "alert" \| "mono"` | `"brand"` | The color tone of the button. |
|
|
445
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the button. |
|
|
446
|
+
| disabled | `boolean` | `false` | Whether the button is disabled. |
|
|
447
|
+
| loading | `boolean` | `false` | Whether to show loading spinner. |
|
|
448
|
+
| onPress | `() => void` | - | Callback fired when button is pressed. |
|
|
449
|
+
| type | `"button" \| "submit" \| "reset"` | `"button"` | The HTML button type attribute. |
|
|
450
|
+
|
|
451
|
+
---
|
|
57
452
|
|
|
58
453
|
### FlexButton
|
|
59
454
|
|
|
455
|
+
A flexible button with more granular control over background and styling.
|
|
456
|
+
|
|
457
|
+
**FlexButton Props:**
|
|
458
|
+
|
|
60
459
|
| Prop | Type | Default | Description |
|
|
61
|
-
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
| `
|
|
68
|
-
|
|
|
69
|
-
|
|
|
460
|
+
| :--- | :--- | :------ | :---------- |
|
|
461
|
+
| children | `ReactNode` | - | The button label content. |
|
|
462
|
+
| variant | `"brand" \| "primary" \| "secondary" \| "tertiary" \| "brandExtra" \| "inverse"` | `"brand"` | The visual style variant. |
|
|
463
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the button. |
|
|
464
|
+
| background | `boolean` | `false` | Whether to show background fill. |
|
|
465
|
+
| disabled | `boolean` | `false` | Whether the button is disabled. |
|
|
466
|
+
| loading | `boolean` | `false` | Whether to show loading spinner. |
|
|
467
|
+
| iconLeft | `ReactNode` | - | Icon to display on the left side. |
|
|
468
|
+
| iconRight | `ReactNode` | - | Icon to display on the right side. |
|
|
469
|
+
| onPress | `() => void` | - | Callback fired when button is pressed. |
|
|
470
|
+
| type | `"button" \| "submit" \| "reset"` | `"button"` | The HTML button type attribute. |
|
|
471
|
+
|
|
472
|
+
---
|
|
70
473
|
|
|
71
474
|
### ButtonGroup
|
|
72
475
|
|
|
476
|
+
A container for grouping related buttons together.
|
|
477
|
+
|
|
478
|
+
**ButtonGroup Props:**
|
|
479
|
+
|
|
73
480
|
| Prop | Type | Default | Description |
|
|
74
|
-
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
481
|
+
| :--- | :--- | :------ | :---------- |
|
|
482
|
+
| children | `ReactNode` | - | **Required.** Button children to group. |
|
|
483
|
+
| orientation | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction of the buttons. |
|
|
484
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | Size applied to the group spacing. |
|
|
485
|
+
| gap | `number` | - | Custom gap between buttons (overrides size default). |
|
|
486
|
+
| description | `string` | - | Description text shown below the group. |
|
|
487
|
+
| error | `string` | - | Error message (replaces description when present). |
|
|
488
|
+
| aria-label | `string` | - | Accessible label for the button group. |
|
|
489
|
+
| aria-labelledby | `string` | - | ID of element labeling the group. |
|
|
490
|
+
| aria-describedby | `string` | - | ID of element describing the group. |
|
|
491
|
+
| id | `string` | - | HTML id attribute. |
|
|
492
|
+
| testID | `string` | - | Test identifier for testing frameworks. |
|
|
493
|
+
|
|
494
|
+
**ButtonGroup Gap Defaults:**
|
|
495
|
+
|
|
496
|
+
| Size | Vertical Gap | Horizontal Gap |
|
|
497
|
+
| :--- | :----------- | :------------- |
|
|
498
|
+
| xl | 16 | 16 |
|
|
499
|
+
| lg | 16 | 16 |
|
|
500
|
+
| md | 12 | 16 |
|
|
501
|
+
| sm | 8 | 12 |
|
|
502
|
+
| xs | 4 | 12 |
|
|
503
|
+
|
|
504
|
+
## Theming
|
|
505
|
+
|
|
506
|
+
Button components use the design system theme for colors and sizing:
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
// Colors accessed via theme
|
|
510
|
+
theme.colors.control.[tone].[variant].bg // Background color
|
|
511
|
+
theme.colors.control.[tone].[variant].bgHover // Hover background
|
|
512
|
+
theme.colors.control.[tone].[variant].bgPress // Pressed background
|
|
513
|
+
theme.colors.control.[tone].[variant].text // Text color
|
|
514
|
+
theme.colors.control.[tone].[variant].border // Border color
|
|
515
|
+
|
|
516
|
+
// Sizing accessed via theme
|
|
517
|
+
theme.sizing.button(size).height
|
|
518
|
+
theme.sizing.button(size).paddingHorizontal
|
|
519
|
+
theme.sizing.button(size).fontSize
|
|
520
|
+
theme.sizing.button(size).iconSize
|
|
521
|
+
|
|
522
|
+
// Border radius
|
|
523
|
+
theme.radius.button
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Accessibility
|
|
527
|
+
|
|
528
|
+
- All buttons use semantic `<button>` elements
|
|
529
|
+
- `IconButton` requires `aria-label` for screen reader support
|
|
530
|
+
- `ButtonGroup` uses `role="group"` with proper ARIA attributes
|
|
531
|
+
- Focus indicators follow WCAG guidelines
|
|
532
|
+
- Disabled buttons are properly announced to assistive technology
|
|
533
|
+
- Loading state is communicated via `aria-busy` attribute
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-button",
|
|
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",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"test:coverage": "vitest run --coverage"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@xsolla/xui-core": "0.
|
|
17
|
-
"@xsolla/xui-icons": "0.
|
|
18
|
-
"@xsolla/xui-primitives-core": "0.
|
|
16
|
+
"@xsolla/xui-core": "0.101.0",
|
|
17
|
+
"@xsolla/xui-icons": "0.101.0",
|
|
18
|
+
"@xsolla/xui-primitives-core": "0.101.0"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"react": ">=16.8.0",
|