@xsolla/xui-button
v0.162.0
Published
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.
Readme
Button
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.
Installation
npm install @xsolla/xui-buttonDemo
Basic Button
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function BasicButton() {
return <Button onPress={() => console.log("Pressed!")}>Click me</Button>;
}Button Variants
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function ButtonVariants() {
return (
<div style={{ display: "flex", gap: 16 }}>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
</div>
);
}Button Tones
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function ButtonTones() {
return (
<div style={{ display: "flex", gap: 16 }}>
<Button tone="brand">Brand</Button>
<Button tone="brandExtra">Brand Extra</Button>
<Button tone="alert">Alert</Button>
<Button tone="mono">Mono</Button>
</div>
);
}Button Sizes
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function ButtonSizes() {
return (
<div style={{ display: "flex", gap: 16, alignItems: "center" }}>
<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="xl">Extra Large</Button>
</div>
);
}Button with Icons
import * as React from "react";
import { Button } from "@xsolla/xui-button";
import { Plus, ChevronDown, FileDownloadOut } from "@xsolla/xui-icons-base";
import { ArrowRight } from "@xsolla/xui-icons";
export default function ButtonWithIcons() {
return (
<div style={{ display: "flex", gap: 16 }}>
<Button iconLeft={<Plus />}>Add Item</Button>
<Button iconRight={<ArrowRight />}>Next Step</Button>
<Button iconLeft={<FileDownloadOut />} iconRight={<ChevronDown />}>
Download
</Button>
</div>
);
}Loading Button
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function LoadingButton() {
const [loading, setLoading] = React.useState(false);
const handlePress = () => {
setLoading(true);
setTimeout(() => setLoading(false), 2000);
};
return (
<Button loading={loading} onPress={handlePress}>
{loading ? "Processing..." : "Submit"}
</Button>
);
}Anatomy
Import the component and use it directly:
import { Button, IconButton, FlexButton, ButtonGroup } from '@xsolla/xui-button';
import { Plus } from '@xsolla/xui-icons-base';
// Basic button
<Button>Label</Button>
// Icon-only button
<IconButton icon={<Plus />} aria-label="Add item" />
// Flexible styling button
<FlexButton variant="brand">Label</FlexButton>
// Group of buttons
<ButtonGroup>
<Button>First</Button>
<Button>Second</Button>
</ButtonGroup>Examples
Full Width Button
Use the fullWidth prop to make the button span the entire container width.
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function FullWidthButton() {
return (
<div style={{ width: 300 }}>
<Button fullWidth>Full Width Button</Button>
</div>
);
}Disabled Button
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function DisabledButton() {
return (
<div style={{ display: "flex", gap: 16 }}>
<Button disabled>Disabled Primary</Button>
<Button variant="secondary" disabled>
Disabled Secondary
</Button>
</div>
);
}Icon Button
Use IconButton for buttons that contain only an icon.
import * as React from "react";
import { IconButton } from "@xsolla/xui-button";
import { Plus, TrashCan } from "@xsolla/xui-icons-base";
import { Settings } from "@xsolla/xui-icons";
export default function IconButtonExample() {
return (
<div style={{ display: "flex", gap: 16 }}>
<IconButton icon={<Plus />} aria-label="Add" size="md" />
<IconButton icon={<TrashCan />} aria-label="Delete" tone="alert" />
<IconButton
icon={<Settings />}
aria-label="Settings"
variant="secondary"
/>
</div>
);
}Button Group
Use ButtonGroup to group related buttons together.
import * as React from "react";
import { Button, ButtonGroup } from "@xsolla/xui-button";
export default function ButtonGroupExample() {
return (
<ButtonGroup orientation="horizontal" size="md">
<Button variant="secondary">Cancel</Button>
<Button>Confirm</Button>
</ButtonGroup>
);
}Vertical Button Group
import * as React from "react";
import { Button, ButtonGroup } from "@xsolla/xui-button";
export default function VerticalButtonGroup() {
return (
<ButtonGroup orientation="vertical" size="md">
<Button fullWidth>Option 1</Button>
<Button fullWidth>Option 2</Button>
<Button fullWidth>Option 3</Button>
</ButtonGroup>
);
}Flex Button
FlexButton provides more flexible styling options with different background modes.
import * as React from "react";
import { FlexButton } from "@xsolla/xui-button";
import { Link } from "@xsolla/xui-icons-base";
export default function FlexButtonExample() {
return (
<div style={{ display: "flex", gap: 16 }}>
<FlexButton variant="brand" background>
With Background
</FlexButton>
<FlexButton variant="brand">Text Only</FlexButton>
<FlexButton variant="tertiary" iconLeft={<Link />}>
Link Style
</FlexButton>
</div>
);
}Form Submit Button
import * as React from "react";
import { Button } from "@xsolla/xui-button";
export default function FormSubmitButton() {
return (
<form
onSubmit={(e) => {
e.preventDefault();
console.log("Form submitted");
}}
>
<Button type="submit">Submit Form</Button>
</form>
);
}Button with Sublabel
Use the sublabel prop to add secondary text inline with the main label.
import * as React from "react";
import { Button } from "@xsolla/xui-button";
import { Apple } from "@xsolla/xui-icons-brand";
export default function ButtonWithSublabel() {
return (
<Button iconLeft={<Apple />} sublabel="$39.99" labelAlignment="left">
Buy Now
</Button>
);
}Button with Custom Content
Use customContent to add badges, tags, or other elements inside the button.
import * as React from "react";
import { Button } from "@xsolla/xui-button";
import { Tag } from "@xsolla/xui-tag";
import { ArrowRight } from "@xsolla/xui-icons-base";
export default function ButtonWithCustomContent() {
return (
<Button iconRight={<ArrowRight />} customContent={<Tag size="sm">5x</Tag>}>
Claim Reward
</Button>
);
}Tertiary Variant
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).
import * as React from "react";
import { Button, IconButton } from "@xsolla/xui-button";
import { Settings, ArrowRight } from "@xsolla/xui-icons-base";
export default function TertiaryButtons() {
return (
<div style={{ display: "flex", gap: 16 }}>
<Button variant="tertiary" tone="brand" size="xs">
Activate
</Button>
<Button
variant="tertiary"
tone="brand"
size="xs"
iconRight={<ArrowRight />}
>
Details
</Button>
<Button variant="tertiary">Learn More</Button>
<IconButton
variant="tertiary"
icon={<Settings />}
aria-label="Settings"
/>
</div>
);
}API Reference
Button
The main button component. Renders a semantic <button> element.
Button Props:
| Prop | Type | Default | Description |
| :--------------- | :--------------------------------------------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------ |
| testID | string | — | Test ID for testing frameworks. On web this renders as data-testid; on React Native it renders as testID. |
| children | ReactNode | - | The button label content. |
| variant | "primary" \| "secondary" \| "tertiary" \| "ghost" | "primary" | The visual style variant. |
| tone | "brand" \| "brandExtra" \| "alert" \| "mono" | "brand" | The color tone of the button. |
| size | "xl" \| "lg" \| "md" \| "sm" \| "xs" | "md" | The size of the button. |
| disabled | boolean | false | Whether the button is disabled. |
| loading | boolean | false | Whether to show loading spinner. Disables interaction when true. |
| onPress | () => void | - | Callback fired when button is pressed. |
| iconLeft | ReactNode | - | Icon to display on the left side. |
| iconRight | ReactNode | - | Icon to display on the right side. |
| sublabel | string | - | Secondary label text displayed inline with main label at 40% opacity. |
| labelIcon | ReactNode | - | Small icon displayed directly next to the label text. |
| labelAlignment | "left" \| "center" | "center" | Alignment of the label content within the button. |
| customContent | ReactNode | - | Custom content slot for badges, tags, or other elements. |
| fullWidth | boolean | false | Whether button should span full container width. |
| type | "button" \| "submit" \| "reset" | "button" | The HTML button type attribute. |
| aria-label | string | - | Accessible label for the button. |
| aria-describedby | string | - | ID of element that describes the button. |
| aria-expanded | boolean | - | Indicates if controlled element is expanded. |
| aria-haspopup | boolean \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog" | - | Indicates popup type triggered by button. |
| aria-pressed | boolean \| "mixed" | - | Indicates pressed state for toggle buttons. |
| aria-controls | string | - | ID of element controlled by this button. |
| testID | string | - | Test identifier for testing frameworks. |
| id | string | - | HTML id attribute. |
IconButton
A button variant that displays only an icon. Requires aria-label for accessibility.
IconButton Props:
| Prop | Type | Default | Description |
| :--------- | :-------------------------------------------------- | :---------- | :--------------------------------------------- |
| icon | ReactNode | - | Required. The icon to display. |
| aria-label | string | - | Required. Accessible label for the button. |
| variant | "primary" \| "secondary" \| "tertiary" \| "ghost" | "primary" | The visual style variant. |
| tone | "brand" \| "brandExtra" \| "alert" \| "mono" | "brand" | The color tone of the button. |
| size | "xl" \| "lg" \| "md" \| "sm" \| "xs" | "md" | The size of the button. |
| disabled | boolean | false | Whether the button is disabled. |
| loading | boolean | false | Whether to show loading spinner. |
| onPress | () => void | - | Callback fired when button is pressed. |
| type | "button" \| "submit" \| "reset" | "button" | The HTML button type attribute. |
FlexButton
A flexible button with more granular control over background and styling.
FlexButton Props:
| Prop | Type | Default | Description |
| :--------- | :------------------------------------------------------------------------------- | :--------- | :------------------------------------- |
| children | ReactNode | - | The button label content. |
| variant | "brand" \| "primary" \| "secondary" \| "tertiary" \| "brandExtra" \| "inverse" | "brand" | The visual style variant. |
| size | "xl" \| "lg" \| "md" \| "sm" \| "xs" | "md" | The size of the button. |
| background | boolean | false | Whether to show background fill. |
| disabled | boolean | false | Whether the button is disabled. |
| loading | boolean | false | Whether to show loading spinner. |
| iconLeft | ReactNode | - | Icon to display on the left side. |
| iconRight | ReactNode | - | Icon to display on the right side. |
| onPress | () => void | - | Callback fired when button is pressed. |
| type | "button" \| "submit" \| "reset" | "button" | The HTML button type attribute. |
ButtonGroup
A container for grouping related buttons together.
ButtonGroup Props:
| Prop | Type | Default | Description |
| :--------------- | :------------------------------------- | :------------- | :--------------------------------------------------- |
| children | ReactNode | - | Required. Button children to group. |
| orientation | "horizontal" \| "vertical" | "horizontal" | Layout direction of the buttons. |
| size | "xl" \| "lg" \| "md" \| "sm" \| "xs" | "md" | Size applied to the group spacing. |
| gap | number | - | Custom gap between buttons (overrides size default). |
| description | string | - | Description text shown below the group. |
| error | string | - | Error message (replaces description when present). |
| aria-label | string | - | Accessible label for the button group. |
| aria-labelledby | string | - | ID of element labeling the group. |
| aria-describedby | string | - | ID of element describing the group. |
| id | string | - | HTML id attribute. |
| testID | string | - | Test identifier for testing frameworks. |
ButtonGroup Gap Defaults:
| Size | Vertical Gap | Horizontal Gap | | :--- | :----------- | :------------- | | xl | 16 | 16 | | lg | 16 | 16 | | md | 12 | 16 | | sm | 8 | 12 | | xs | 4 | 12 |
Accessibility
- All buttons use semantic
<button>elements IconButtonrequiresaria-labelfor screen reader supportButtonGroupusesrole="group"with proper ARIA attributes- Focus indicators follow WCAG guidelines
- Disabled buttons are properly announced to assistive technology
- Loading state is communicated via
aria-busyattribute
