import React, { ReactNode } from 'react';
import { ThemeOverrideProps } from '@xsolla/xui-core';
interface ButtonProps extends ThemeOverrideProps {
/** Visual variant of the button */
variant?: "primary" | "secondary" | "tertiary" | "ghost";
/** Color tone of the button */
tone?: "brand" | "brandExtra" | "alert" | "mono";
/** Size of the button */
size?: "xl" | "lg" | "md" | "sm" | "xs";
/** Whether the button is disabled */
disabled?: boolean;
/** Whether the button is in a loading state */
loading?: boolean;
/** Button content */
children: React.ReactNode;
/**
* Activation handler. Invoked on click, or on Enter/Space when the button is
* focused. Not called while `disabled` or `loading`.
*/
onPress?: () => void;
/**
* Icon to display on the left side.
* Size and color are automatically set based on button size/state.
* To override, specify size/color on the icon: `iconLeft={ }`
*/
iconLeft?: React.ReactNode;
/**
* Icon to display on the right side.
* Size and color are automatically set based on button size/state.
* To override, specify size/color on the icon: `iconRight={ }`
*/
iconRight?: React.ReactNode;
/** Secondary text displayed inline with the main label (e.g., price), shown with 40% opacity */
sublabel?: string;
/** Alignment of the label text */
labelAlignment?: "left" | "center";
/**
* Small icon displayed directly to the left of the label text.
* Size and color are automatically set based on button size/state.
* To override, specify size/color on the icon: `labelIcon={ }`
*/
labelIcon?: React.ReactNode;
/**
* Small icon displayed directly to the right of the label text.
* Size and color are automatically set based on button size/state.
* To override, specify size/color on the icon: `labelIconRight={ }`
*/
labelIconRight?: React.ReactNode;
/** Custom content slot for badges, tags, or other elements */
customContent?: React.ReactNode;
/** Accessible label for screen readers (use for icon-only buttons) */
"aria-label"?: string;
/** ID of element that describes this button */
"aria-describedby"?: string;
/** Indicates the button controls an expandable element */
"aria-expanded"?: boolean;
/** Indicates the type of popup triggered by the button */
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
/** Indicates the button is pressed (for toggle buttons) */
"aria-pressed"?: boolean | "mixed";
/** ID of the element this button controls */
"aria-controls"?: string;
testID?: string;
id?: string;
/** HTML type attribute for the button */
type?: "button" | "submit" | "reset";
/** Whether the button should stretch to fill the full width of its container */
fullWidth?: boolean;
}
/**
* Button - An accessible button component
*
* Renders as a semantic `` element with full ARIA support.
* Supports various visual variants, sizes, and states including loading.
*
* ## Accessibility Features
*
* - **Semantic HTML**: Renders as a native `` element
* - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space
* - **ARIA States**: Properly announces disabled and loading states
* - **Focus Indicator**: Visible focus ring for keyboard navigation
* - **Screen Reader Support**: Announces button label, state, and any associated descriptions
*
*/
declare const Button: React.FC;
interface IconButtonProps extends ThemeOverrideProps {
/** Visual variant of the button */
variant?: "primary" | "secondary" | "tertiary";
/** Color tone of the button */
tone?: "brand" | "brandExtra" | "alert" | "mono";
/** Size of the button */
size?: "xl" | "lg" | "md" | "sm" | "xs";
/** Whether the button is disabled */
disabled?: boolean;
/** Whether the button is in a loading state */
loading?: boolean;
/**
* Icon to display in the button (required).
* Size and color are automatically set based on button size/state.
* To override, specify size/color on the icon: `icon={ }`
*/
icon: React.ReactNode;
/**
* Optional badge rendered absolutely at the top-right corner.
* Pass a `` element from `@xsolla/xui-badge`.
*/
badge?: React.ReactNode;
/** Click handler */
onPress?: () => void;
/**
* Accessible label for screen readers (REQUIRED for icon-only buttons)
* Since icon buttons have no visible text, this label is essential for accessibility.
* @example aria-label="Close dialog"
* @example aria-label="Open settings menu"
*/
"aria-label": string;
/** ID of element that describes this button */
"aria-describedby"?: string;
/** Indicates the button controls an expandable element */
"aria-expanded"?: boolean;
/** Indicates the type of popup triggered by the button */
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
/** Indicates the button is pressed (for toggle buttons) */
"aria-pressed"?: boolean | "mixed";
/** ID of the element this button controls */
"aria-controls"?: string;
testID?: string;
id?: string;
/** HTML type attribute for the button */
type?: "button" | "submit" | "reset";
/** Override the hover background color. Pass "none" to remove it entirely. */
hoverBackground?: string | "none";
}
/**
* IconButton - An accessible icon-only button component
*
* Renders as a semantic `` element with full ARIA support.
* Supports various visual variants, sizes, and states including loading.
*
* ## Accessibility Features
*
* - **Semantic HTML**: Renders as a native `` element
* - **Required aria-label**: Ensures screen readers can announce the button's purpose
* - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space
* - **ARIA States**: Properly announces disabled and loading states
* - **Focus Indicator**: Visible focus ring for keyboard navigation
* - **Screen Reader Support**: Announces button label, state, and any associated descriptions
*
* ## Usage
*
* ```tsx
* // Basic usage - aria-label is required
* } aria-label="Close dialog" onPress={handleClose} />
*
* // Toggle button
* }
* aria-label="Toggle menu"
* aria-expanded={isOpen}
* aria-controls="menu-id"
* onPress={toggleMenu}
* />
*
* // Loading state
* } aria-label="Save changes" loading />
* ```
*/
declare const IconButton: React.FC;
interface FlexButtonProps extends Omit, "type">, ThemeOverrideProps {
/**
* Button label. Omit for icon-only buttons (provide `aria-label`).
*
* An icon may also be passed directly as `children` instead of via
* `iconLeft`/`iconRight`. When `children` carries no text, the button is
* treated as icon-only and renders as a square sized from the design-system
* height token for `size`.
*/
children?: ReactNode;
/** Visual variant of the button */
variant?: "brand" | "primary" | "secondary" | "tertiary" | "brandExtra" | "inverse";
/** Size of the button */
size?: "xl" | "lg" | "md" | "sm" | "xs";
/** Whether to show background fill */
background?: boolean;
/**
* Whether to show the hover/press background color.
* When `false`, the button background stays transparent in all interactive
* states, producing a text-only appearance with no hover fill.
* @default true
*/
hoverBackground?: boolean;
/**
* Remove the button's internal padding so it sits flush against its content.
* The component applies padding via an inline style, which overrides any CSS
* class or `style` prop a consumer passes, so this prop is the supported way
* to render a zero-padding FlexButton (e.g. an inline text action).
*
* Icon-only buttons keep their square dimensions when `noPadding` is set —
* only the inner padding is removed.
* @default false
*/
noPadding?: boolean;
/** Whether the button is disabled */
disabled?: boolean;
/** Whether the button is in a loading state */
loading?: boolean;
/** Icon to display on the left side */
iconLeft?: ReactNode;
/** Icon to display on the right side */
iconRight?: ReactNode;
/** Click handler */
onPress?: () => void;
/** HTML type attribute for the button */
type?: "button" | "submit" | "reset";
/** Accessible label for screen readers */
"aria-label"?: string;
/** ID of element that describes this button */
"aria-describedby"?: string;
/** Indicates the button controls an expandable element */
"aria-expanded"?: boolean;
/** Indicates the type of popup triggered by the button */
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
/** Indicates the button is pressed (for toggle buttons) */
"aria-pressed"?: boolean | "mixed";
/** ID of the element this button controls */
"aria-controls"?: string;
testID?: string;
}
/**
* Total hit-area size of an icon-only `FlexButton`, in px. `noPadding` does not
* change it — only the inner padding is removed.
*/
declare const getFlexButtonBoxSize: (size?: NonNullable) => number;
/**
* FlexButton - A compact button component designed for use in modals and popups.
*
* Renders as a semantic `` element with full ARIA support.
*
* ## Icon-only buttons
*
* A FlexButton is icon-only when it has no text label and an icon is supplied
* either as `children` or via `iconLeft`/`iconRight`. Icon-only buttons render
* as a square whose side equals `theme.sizing.flexButton(size).height`, so they
* line up with the Modal header icon slots (36x36 at `size="xl"`).
*
* ```tsx
*
*
*
* ```
*
* ## Accessibility Features
*
* - **Semantic HTML**: Renders as a native `` element
* - **Keyboard Navigation**: Focusable via Tab, activated with Enter or Space
* - **ARIA States**: Properly announces disabled and loading states
* - **Focus Indicator**: Visible focus ring for keyboard navigation
* - **Screen Reader Support**: Announces button label, state, and any associated descriptions
*/
declare const FlexButton: React.ForwardRefExoticComponent>;
interface AppButtonProps extends ThemeOverrideProps {
/** Size of the button */
size?: "xl" | "lg" | "md" | "sm" | "xs";
/** Whether the button is disabled */
disabled?: boolean;
/** Whether the button is in a loading state */
loading?: boolean;
/** Button content */
children: React.ReactNode;
/** Click handler */
onPress?: () => void;
/** Icon to display on the left side */
iconLeft?: React.ReactNode;
/** Icon to display on the right side */
iconRight?: React.ReactNode;
/** Secondary text displayed inline with the main label */
sublabel?: string;
/** Alignment of the label text */
labelAlignment?: "left" | "center";
/** Small icon displayed directly next to the label text */
labelIcon?: React.ReactNode;
/** Custom content slot for badges, tags, or other elements */
customContent?: React.ReactNode;
/** Accessible label for screen readers */
"aria-label"?: string;
/** ID of element that describes this button */
"aria-describedby"?: string;
/** Indicates the button controls an expandable element */
"aria-expanded"?: boolean;
/** Indicates the type of popup triggered by the button */
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
/** Indicates the button is pressed (for toggle buttons) */
"aria-pressed"?: boolean | "mixed";
/** ID of the element this button controls */
"aria-controls"?: string;
testID?: string;
id?: string;
/** HTML type attribute for the button */
type?: "button" | "submit" | "reset";
/** Whether the button should stretch to fill the full width of its container */
fullWidth?: boolean;
}
/**
* AppButton - A prominent filled button for app-level actions.
*
* Uses the `control.appButton` theme tokens for styling.
* Supports all the same layout features as Button (icons, sublabels, etc.).
*/
declare const AppButton: React.FC;
interface ButtonGroupProps extends ThemeOverrideProps {
/**
* Layout orientation of the buttons
* @default 'horizontal'
*/
orientation?: "horizontal" | "vertical";
/**
* Force or suppress the split ("space-between") layout, in which the first
* button is pinned to the left edge and the remaining buttons are grouped
* on the right.
*
* When omitted, the layout is chosen by child count: horizontal groups with
* 3 or more buttons split, smaller groups do not. Set `split` to override
* that heuristic in either direction:
*
* - `split` — split a 2-button group (buttons keep their natural width
* instead of stretching to fill the row)
* - `split={false}` — opt a 3+ button group out of the split layout
*
* Has no effect when `orientation="vertical"` or when the group has fewer
* than 2 children.
*/
split?: boolean;
/**
* Size of the button group, determines default gap between buttons
* @default 'md'
*/
size?: "xl" | "lg" | "md" | "sm" | "xs";
/**
* Buttons to be grouped
*/
children: React.ReactNode;
/**
* Optional description text below the buttons
*/
description?: string;
/**
* Optional error message text below the buttons
*/
error?: string;
/**
* Custom gap between buttons (in pixels). If not provided, uses size and orientation based default.
*/
gap?: number;
/**
* Accessible label for the button group
*/
"aria-label"?: string;
/**
* ID of element that labels this button group
*/
"aria-labelledby"?: string;
/**
* ID of element that describes this button group
*/
"aria-describedby"?: string;
id?: string;
testID?: string;
}
/**
* ButtonGroup - A container for grouping related buttons
*
* Provides semantic grouping for related actions with proper accessibility support.
*
* ## Accessibility Features
*
* - **Semantic Grouping**: Uses `role="group"` to indicate related buttons
* - **Accessible Name**: Supports `aria-label` or `aria-labelledby` to describe the group's purpose
* - **Error Announcements**: Errors are announced to screen readers via `aria-live`
* - **Description Support**: Optional description text for additional context
*
*/
declare const ButtonGroup: React.FC;
export { AppButton, type AppButtonProps, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, FlexButton, type FlexButtonProps, IconButton, type IconButtonProps, getFlexButtonBoxSize };