@xsolla/xui-button 0.148.0 → 0.148.2-pr235.1777605920
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 +523 -0
- package/package.json +4 -4
- package/web/index.js +4 -0
- package/web/index.js.map +1 -1
- package/web/index.mjs +4 -0
- package/web/index.mjs.map +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @xsolla/xui-button
|
|
9
|
+
# or
|
|
10
|
+
yarn add @xsolla/xui-button
|
|
11
|
+
```
|
|
12
|
+
|
|
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.
|
|
229
|
+
|
|
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';
|
|
311
|
+
import { Button } from '@xsolla/xui-button';
|
|
312
|
+
import { Apple } from '@xsolla/xui-icons-brand';
|
|
313
|
+
|
|
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
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Button with Custom Content
|
|
328
|
+
|
|
329
|
+
Use `customContent` to add badges, tags, or other elements inside the button.
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
import * as React from 'react';
|
|
333
|
+
import { Button } from '@xsolla/xui-button';
|
|
334
|
+
import { Tag } from '@xsolla/xui-tag';
|
|
335
|
+
import { ArrowRight } from '@xsolla/xui-icons-base';
|
|
336
|
+
|
|
337
|
+
export default function ButtonWithCustomContent() {
|
|
338
|
+
return (
|
|
339
|
+
<Button
|
|
340
|
+
iconRight={<ArrowRight />}
|
|
341
|
+
customContent={<Tag size="sm">5x</Tag>}
|
|
342
|
+
>
|
|
343
|
+
Claim Reward
|
|
344
|
+
</Button>
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Tertiary Variant
|
|
350
|
+
|
|
351
|
+
The tertiary variant is a subtle filled button with a muted background and border. It is commonly used for secondary actions inside content cards (e.g. "Activate" in game cards).
|
|
352
|
+
|
|
353
|
+
```tsx
|
|
354
|
+
import * as React from 'react';
|
|
355
|
+
import { Button, IconButton } from '@xsolla/xui-button';
|
|
356
|
+
import { Settings, ArrowRight } from '@xsolla/xui-icons-base';
|
|
357
|
+
|
|
358
|
+
export default function TertiaryButtons() {
|
|
359
|
+
return (
|
|
360
|
+
<div style={{ display: 'flex', gap: 16 }}>
|
|
361
|
+
<Button variant="tertiary" tone="brand" size="xs">
|
|
362
|
+
Activate
|
|
363
|
+
</Button>
|
|
364
|
+
<Button variant="tertiary" tone="brand" size="xs" iconRight={<ArrowRight />}>
|
|
365
|
+
Details
|
|
366
|
+
</Button>
|
|
367
|
+
<Button variant="tertiary">Learn More</Button>
|
|
368
|
+
<IconButton
|
|
369
|
+
variant="tertiary"
|
|
370
|
+
icon={<Settings />}
|
|
371
|
+
aria-label="Settings"
|
|
372
|
+
/>
|
|
373
|
+
</div>
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## API Reference
|
|
379
|
+
|
|
380
|
+
### Button
|
|
381
|
+
|
|
382
|
+
The main button component. Renders a semantic `<button>` element.
|
|
383
|
+
|
|
384
|
+
**Button Props:**
|
|
385
|
+
|
|
386
|
+
| Prop | Type | Default | Description |
|
|
387
|
+
| :--- | :--- | :------ | :---------- |
|
|
388
|
+
| children | `ReactNode` | - | The button label content. |
|
|
389
|
+
| variant | `"primary" \| "secondary" \| "tertiary" \| "ghost"` | `"primary"` | The visual style variant. |
|
|
390
|
+
| tone | `"brand" \| "brandExtra" \| "alert" \| "mono"` | `"brand"` | The color tone of the button. |
|
|
391
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the button. |
|
|
392
|
+
| disabled | `boolean` | `false` | Whether the button is disabled. |
|
|
393
|
+
| loading | `boolean` | `false` | Whether to show loading spinner. Disables interaction when true. |
|
|
394
|
+
| onPress | `() => void` | - | Callback fired when button is pressed. |
|
|
395
|
+
| iconLeft | `ReactNode` | - | Icon to display on the left side. |
|
|
396
|
+
| iconRight | `ReactNode` | - | Icon to display on the right side. |
|
|
397
|
+
| sublabel | `string` | - | Secondary label text displayed inline with main label at 40% opacity. |
|
|
398
|
+
| labelIcon | `ReactNode` | - | Small icon displayed directly next to the label text. |
|
|
399
|
+
| labelAlignment | `"left" \| "center"` | `"center"` | Alignment of the label content within the button. |
|
|
400
|
+
| customContent | `ReactNode` | - | Custom content slot for badges, tags, or other elements. |
|
|
401
|
+
| fullWidth | `boolean` | `false` | Whether button should span full container width. |
|
|
402
|
+
| type | `"button" \| "submit" \| "reset"` | `"button"` | The HTML button type attribute. |
|
|
403
|
+
| aria-label | `string` | - | Accessible label for the button. |
|
|
404
|
+
| aria-describedby | `string` | - | ID of element that describes the button. |
|
|
405
|
+
| aria-expanded | `boolean` | - | Indicates if controlled element is expanded. |
|
|
406
|
+
| aria-haspopup | `boolean \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog"` | - | Indicates popup type triggered by button. |
|
|
407
|
+
| aria-pressed | `boolean \| "mixed"` | - | Indicates pressed state for toggle buttons. |
|
|
408
|
+
| aria-controls | `string` | - | ID of element controlled by this button. |
|
|
409
|
+
| testID | `string` | - | Test identifier for testing frameworks. |
|
|
410
|
+
| id | `string` | - | HTML id attribute. |
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
### IconButton
|
|
415
|
+
|
|
416
|
+
A button variant that displays only an icon. Requires `aria-label` for accessibility.
|
|
417
|
+
|
|
418
|
+
**IconButton Props:**
|
|
419
|
+
|
|
420
|
+
| Prop | Type | Default | Description |
|
|
421
|
+
| :--- | :--- | :------ | :---------- |
|
|
422
|
+
| icon | `ReactNode` | - | **Required.** The icon to display. |
|
|
423
|
+
| aria-label | `string` | - | **Required.** Accessible label for the button. |
|
|
424
|
+
| variant | `"primary" \| "secondary" \| "tertiary" \| "ghost"` | `"primary"` | The visual style variant. |
|
|
425
|
+
| tone | `"brand" \| "brandExtra" \| "alert" \| "mono"` | `"brand"` | The color tone of the button. |
|
|
426
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the button. |
|
|
427
|
+
| disabled | `boolean` | `false` | Whether the button is disabled. |
|
|
428
|
+
| loading | `boolean` | `false` | Whether to show loading spinner. |
|
|
429
|
+
| onPress | `() => void` | - | Callback fired when button is pressed. |
|
|
430
|
+
| type | `"button" \| "submit" \| "reset"` | `"button"` | The HTML button type attribute. |
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
### FlexButton
|
|
435
|
+
|
|
436
|
+
A flexible button with more granular control over background and styling.
|
|
437
|
+
|
|
438
|
+
**FlexButton Props:**
|
|
439
|
+
|
|
440
|
+
| Prop | Type | Default | Description |
|
|
441
|
+
| :--- | :--- | :------ | :---------- |
|
|
442
|
+
| children | `ReactNode` | - | The button label content. |
|
|
443
|
+
| variant | `"brand" \| "primary" \| "secondary" \| "tertiary" \| "brandExtra" \| "inverse"` | `"brand"` | The visual style variant. |
|
|
444
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the button. |
|
|
445
|
+
| background | `boolean` | `false` | Whether to show background fill. |
|
|
446
|
+
| disabled | `boolean` | `false` | Whether the button is disabled. |
|
|
447
|
+
| loading | `boolean` | `false` | Whether to show loading spinner. |
|
|
448
|
+
| iconLeft | `ReactNode` | - | Icon to display on the left side. |
|
|
449
|
+
| iconRight | `ReactNode` | - | Icon to display on the right side. |
|
|
450
|
+
| onPress | `() => void` | - | Callback fired when button is pressed. |
|
|
451
|
+
| type | `"button" \| "submit" \| "reset"` | `"button"` | The HTML button type attribute. |
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
### ButtonGroup
|
|
456
|
+
|
|
457
|
+
A container for grouping related buttons together.
|
|
458
|
+
|
|
459
|
+
**ButtonGroup Props:**
|
|
460
|
+
|
|
461
|
+
| Prop | Type | Default | Description |
|
|
462
|
+
| :--- | :--- | :------ | :---------- |
|
|
463
|
+
| children | `ReactNode` | - | **Required.** Button children to group. |
|
|
464
|
+
| orientation | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction of the buttons. |
|
|
465
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | Size applied to the group spacing. |
|
|
466
|
+
| gap | `number` | - | Custom gap between buttons (overrides size default). |
|
|
467
|
+
| description | `string` | - | Description text shown below the group. |
|
|
468
|
+
| error | `string` | - | Error message (replaces description when present). |
|
|
469
|
+
| aria-label | `string` | - | Accessible label for the button group. |
|
|
470
|
+
| aria-labelledby | `string` | - | ID of element labeling the group. |
|
|
471
|
+
| aria-describedby | `string` | - | ID of element describing the group. |
|
|
472
|
+
| id | `string` | - | HTML id attribute. |
|
|
473
|
+
| testID | `string` | - | Test identifier for testing frameworks. |
|
|
474
|
+
|
|
475
|
+
**ButtonGroup Gap Defaults:**
|
|
476
|
+
|
|
477
|
+
| Size | Vertical Gap | Horizontal Gap |
|
|
478
|
+
| :--- | :----------- | :------------- |
|
|
479
|
+
| xl | 16 | 16 |
|
|
480
|
+
| lg | 16 | 16 |
|
|
481
|
+
| md | 12 | 16 |
|
|
482
|
+
| sm | 8 | 12 |
|
|
483
|
+
| xs | 4 | 12 |
|
|
484
|
+
|
|
485
|
+
## Theming
|
|
486
|
+
|
|
487
|
+
Button components use the design system theme for colors and sizing:
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
// Colors accessed via theme
|
|
491
|
+
theme.colors.control.[tone].[variant].bg // Background color
|
|
492
|
+
theme.colors.control.[tone].[variant].bgHover // Hover background
|
|
493
|
+
theme.colors.control.[tone].[variant].bgPress // Pressed background
|
|
494
|
+
theme.colors.control.[tone].[variant].bgDisable // Disabled background
|
|
495
|
+
theme.colors.control.[tone].[variant].border // Border color
|
|
496
|
+
theme.colors.control.[tone].[variant].borderHover // Hover border
|
|
497
|
+
theme.colors.control.[tone].[variant].borderPress // Pressed border
|
|
498
|
+
theme.colors.control.[tone].[variant].borderDisable // Disabled border
|
|
499
|
+
|
|
500
|
+
// Text colors are at the tone level, mapped by variant name
|
|
501
|
+
theme.colors.control.[tone].text.primary // Text color for primary variant
|
|
502
|
+
theme.colors.control.[tone].text.secondary // Text color for secondary variant
|
|
503
|
+
theme.colors.control.[tone].text.tertiary // Text color for tertiary variant
|
|
504
|
+
theme.colors.control.[tone].text.disable // Text color for disabled state
|
|
505
|
+
|
|
506
|
+
// Sizing accessed via theme
|
|
507
|
+
theme.sizing.button(size).height
|
|
508
|
+
theme.sizing.button(size).paddingHorizontal
|
|
509
|
+
theme.sizing.button(size).fontSize
|
|
510
|
+
theme.sizing.button(size).iconSize
|
|
511
|
+
|
|
512
|
+
// Border radius
|
|
513
|
+
theme.radius.button
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Accessibility
|
|
517
|
+
|
|
518
|
+
- All buttons use semantic `<button>` elements
|
|
519
|
+
- `IconButton` requires `aria-label` for screen reader support
|
|
520
|
+
- `ButtonGroup` uses `role="group"` with proper ARIA attributes
|
|
521
|
+
- Focus indicators follow WCAG guidelines
|
|
522
|
+
- Disabled buttons are properly announced to assistive technology
|
|
523
|
+
- 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.148.
|
|
3
|
+
"version": "0.148.2-pr235.1777605920",
|
|
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.148.
|
|
17
|
-
"@xsolla/xui-icons": "0.148.
|
|
18
|
-
"@xsolla/xui-primitives-core": "0.148.
|
|
16
|
+
"@xsolla/xui-core": "0.148.2-pr235.1777605920",
|
|
17
|
+
"@xsolla/xui-icons": "0.148.2-pr235.1777605920",
|
|
18
|
+
"@xsolla/xui-primitives-core": "0.148.2-pr235.1777605920"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"react": ">=16.8.0",
|
package/web/index.js
CHANGED
|
@@ -226,6 +226,8 @@ var Box = import_react2.default.forwardRef(
|
|
|
226
226
|
as,
|
|
227
227
|
src,
|
|
228
228
|
alt,
|
|
229
|
+
onError,
|
|
230
|
+
onLoad,
|
|
229
231
|
type,
|
|
230
232
|
disabled,
|
|
231
233
|
id,
|
|
@@ -239,6 +241,8 @@ var Box = import_react2.default.forwardRef(
|
|
|
239
241
|
{
|
|
240
242
|
src,
|
|
241
243
|
alt: alt || "",
|
|
244
|
+
onError,
|
|
245
|
+
onLoad,
|
|
242
246
|
style: {
|
|
243
247
|
display: "block",
|
|
244
248
|
objectFit: "cover",
|