import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
import type { MintProp } from '../../mint/index.js';
import type { ComponentIntent, ComponentSize, ComponentVariant, InteractiveTier } from '../../utils/index.js';
import type { ButtonVariants } from '../Button/button.variants.js';
import type { ButtonGroupSlots } from './buttongroup.variants.js';
export type ButtonGroupSelection = 'none' | 'single' | 'multiple';
export type ButtonGroupOrientation = 'horizontal' | 'vertical';
export type ButtonGroupValue = string | string[] | undefined;
/**
* @summary Related buttons as one control, optionally with a selected state.
* @description Groups related buttons with shared styling, layout, and optional selection behaviour.
* Supports single-select (radio), multi-select (checkbox), or no selection.
* Note the default `variant` is `outlined`, not `filled` as on a lone Button: a connected group
* with a selected state reads as a segmented control, which needs an outline to sit in and a
* filled active segment to stand out — three filled buttons side by side carry no hierarchy.
* Pass `variant="filled"` explicitly for a row of equally weighted actions.
*
* @tag action
* @related Button
* @related Toolbar
*
* @example
* ```svelte
*
*
*
*
* ```
*
* @example
* ```svelte
*
*
*
*
*
* ```
*/
export interface ButtonGroupProps extends Omit, 'children'> {
/** Button children to group. */
children?: Snippet;
/** Stack direction. */
orientation?: ButtonGroupOrientation;
/** Visually connect buttons (overlapping borders, shared rounding). When `false`, buttons are spaced with a small gap. */
connected?: boolean;
/** Size propagated to child Buttons (the group value wins over a Button's own `size`). */
size?: ComponentSize;
/** Semantic colour propagated to child Buttons. */
intent?: ComponentIntent;
/** Visual weight propagated to child Buttons. */
variant?: ButtonVariants['variant'];
/**
* Semantic radius tier propagated to child Buttons. `commit` → pill caps for
* the group; `modify` → soft caps. Inherits from a wrapping Toolbar via
* TierContext when not set explicitly. The unset default is `commit`, except
* on a connected vertical group, where the pill cap domes the stack into a
* lozenge — that one defaults to `modify`. Set `tier="commit"` explicitly to
* get the capsule back (right for a narrow, icon-only stack).
* @summary Corner rounding for the group: pill caps, or soft ones.
*/
tier?: InteractiveTier;
/** Disable the entire group and all child Buttons. */
disabled?: boolean;
/** Selection mode. `"single"` = radio-group, `"multiple"` = checkbox-group, `"none"` = no selection. */
selection?: ButtonGroupSelection;
/** Current selection value. Bind with `bind:value` for two-way sync. String for single, string[] for multiple. */
value?: ButtonGroupValue;
/**
* Micro-interaction preset applied to each child Button (per-item via
* context); overrides each button's own `mint` prop.
*
* The `'none'` default also flattens each button's press sink, so a connected
* group's shared seam stays still on click instead of one segment shrinking
* away from its neighbours. Buttons keep reporting the press in depth and
* colour. Name any real mint here to give the whole group its movement back.
* @default 'none'
* @summary Decorative feedback effect on every button in the group.
*/
mint?: MintProp;
/** Fired when selection changes. Receives the new value and an array of all selected values. */
onSelectionChange?: (value: ButtonGroupValue, selectedValues: string[]) => void;
/** Extra classes merged onto the root element. */
class?: string;
/** Remove all default tv classes. */
unstyled?: boolean;
/** Per-slot class overrides. Slots: base */
slotClasses?: Partial>;
/**
* Apply a named preset registered via ``.
* Prefer this over `class` overrides when the requested look falls outside the
* semantic intent palette — presets keep hover/active/dark-mode logic coherent
* and make the custom look reusable across the project.
*/
preset?: string;
/** Accessible label for the group (prefer this over `aria-label` for correct HTML attribute). */
ariaLabel?: string;
/** ID of the element that labels the group. */
ariaLabelledBy?: string;
}
/** Reactive context exposed to child Button components via `getButtonGroupContext()`. */
export interface ButtonGroupContext {
readonly orientation: ButtonGroupOrientation;
readonly connected: boolean;
readonly size: ComponentSize;
readonly intent: ComponentIntent;
readonly variant: ComponentVariant;
readonly selection: ButtonGroupSelection;
readonly disabled: boolean;
readonly mint: MintProp;
readonly selectedValues: Set;
registerButton: (value: string | undefined) => {
readonly isSelected: boolean;
onClick: () => void;
getButtonProps: () => {
role?: 'radio' | 'checkbox';
'aria-checked'?: boolean;
/**
* The Button's selection value, exposed on the element so the group can
* resolve the selected radio by matching value instead of by position
* (robust against duplicate values and runtime add/remove).
*/
'data-value'?: string;
};
};
}
export { default as ButtonGroup } from './ButtonGroup.svelte';
export { type ButtonGroupVariants, buttonGroupVariants } from './buttongroup.variants.js';