Pricing

OverflowActions handbook

v1.1.1 · @snowui-design-system/components

License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.

Overview

Show action buttons within the available width and move those that do not fit into a More menu, keeping toolbars compact and usable.

When to use it

Use OverflowActions when a group of actions must move progressively into a More menu as width shrinks. Compose OverflowAction and Separator instead of repeating width measurement and menu allocation in the page.

  • items contains actions and separators with unique IDs. Explicit children replace items.

  • Compose OverflowAction as="item" and Separator as="separator" directly. compact, overflow, and overflowFrom control how actions move into the menu.

Quick start

This example shows the recommended basic composition. See the sections below for more cases and composition limits.

<script lang="ts">	import { OverflowActions, Text } from '@snowui-design-system/components';	const websiteActions = [		{ id: 'preview', label: 'Preview site', icon: 'code', href: '/components/showcase' },		{ id: 'copy-install', label: 'Copy install', icon: 'copy' },		{ id: 'edit-page', label: 'Edit page', icon: 'pencil-simple' },		{ type: 'separator' as const, id: 'content-tools' },		{ id: 'translate', label: 'Translate', icon: 'translate' },		{ id: 'theme', label: 'Switch theme', icon: 'sun' },		{ id: 'github', label: 'SnowUI on GitHub', icon: 'github-logo', href: 'https://github.com/SnowUI' },		{ type: 'separator' as const, id: 'publishing-tools' },		{ id: 'publish', label: 'Publish update', icon: 'upload' },		{ id: 'delete-draft', label: 'Delete draft', icon: 'trash' }	];</script> <div style="display: flex; flex-direction: column; align-items: center; width: 100%; gap: var(--gap-4) var(--gap-3);">	<OverflowActions items={websiteActions} moreLabel="More website actions" style="justify-content: center;" /></div>

API

Keyword Type Default Description
items OverflowActionsItem[] [] Built-in action and separator items. Actions provide unique id and label, with optional icon, disabled, href, target, rel, onAction, buttonProps, and parts. Separators provide type="separator" and id. Explicit children replace these items.
compact "auto" | "none" "auto" auto first hides all labels when width is insufficient and every action has an icon and label. none skips compact mode and moves actions according to overflow.
overflow "all" | "progressive" "all" all moves every action to More when they no longer fit. progressive moves them one by one from overflowFrom, leaving actions that fit visible. Layout is frozen while the menu is open.
overflowFrom "start" | "end" "end" The progressive mode transfers operations from the beginning or the end of the data/combination sequence in turn; the all mode does not distinguish the direction.
availableWidth number — Available width for the action group in pixels. When supplied, the component stops observing its own size; DataTable can pass its column width.
maxVisible number — Maximum directly visible actions, excluding More and separators. Omitted or non-finite values impose no count limit; finite values are floored and clamped to zero. Width may move more actions into the menu. Layout freezes while the menu is open.
moreLabel string LocaleProvider Accessible name of the More button. When omitted, LocaleProvider supplies the label for the current language.
align "start" | "end" "end" Listbox horizontal alignment
disabled boolean false Disable every action.
buttonProps GlobalButtonProps — Button default Props shared by all Action, More and hidden measurement copies; support variant/size/bare/emphasis/class/style, and exclude the content, role, click, link, disable and name fields taken over by the operation group.
children Snippet — Declare the direct OverflowAction as="item" and Separator as="separator"; replace the built-in operation of items when they exist, and the structure item is not considered as an independent overflow candidate.
parts Parts — Configure the default generated Button, SelectButton, Listbox, MenuItem, Separator; More's parts.SelectButton is higher than the group-level parts.Button. The public Parts structure and overlay priority are as follows.
onAction (event: OverflowActionsActionEvent) => void — Called after an action runs. id is its stable ID, source is "button" or "menu", item is the matching built-in data (usually absent in explicit mode), and originalEvent is an optional mouse event.

See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.

Usage boundaries and details

Usage

The default built-in mode generates Button, Separator, SelectButton, Listbox and MenuItem through stable data:

<OverflowActions  items={[    { type: "action", id: "edit", label: "Edit", icon: "pencil-simple" },    { type: "separator", id: "main-separator" },    { type: "action", id: "delete", label: "Delete", icon: "trash" },  ]}  onAction={({ id }) => runAction(id)}/>

Explicit composition declares an actionable item with OverflowAction as="item" and a structural item with Separator as="separator" column:

<OverflowActions overflow="progressive" overflowFrom="end">  <OverflowAction as="item" id="edit" label="Edit" icon="pencil-simple" onclick={edit} />  <Separator as="separator" column />  <OverflowAction as="item" id="delete" label="Delete" icon="trash" onclick={remove} /></OverflowActions>

Responsive rules

The preferred group gap is --gap-2 (8px by default), with at least 4 CSS px between independent actions. Larger --snowui-overflow-actions-gap-override values remain effective. The existing width solver reads the actual computed gap, so smaller fonts or gap scales may move actions into the menu slightly earlier without changing their order.

The components adapt to the available width in the following order:

  1. Full display of Icon + Text.

  2. With compact="auto", if every action has both icon and label, hide all labels together and show icons only.

  3. When it still can't be put down, the More button is displayed, and the operation is transferred according to overflow:

    • all: All operations are transferred to the menu.

    • progressive: Move actions one at a time into the menu from the side selected by overflowFrom="start" | "end".

As width approaches an overflow threshold, the action about to enter More fades over a fixed --size-5 width interval. Widening restores opacity based on the current width; More and the group background do not fade. If More first appears with several actions moved at once, they fade together. Once effective width (prefer availableWidth) stops changing for 1 second, a shared recovery controller restores retained buttons to full opacity. Narrowing again continues from their current opacity. Moved actions remain hidden while More and retained buttons settle into position. An open menu freezes allocation but not opacity recovery. A full-to-compact change only hides labels, not whole buttons. Reduced motion switches immediately. This follows the Table responsive-item rule in specs/maintainers/MotionPresetSpec.md.

When the visible action set changes, retained buttons and More translate horizontally to their native Flex positions with RESIZE_MOTION. Continuous width changes do not restart motion; reversing direction continues from the current visual position. The private adapter is src/lib/overflow-actions-motion.ts; it does not scale button contents. Reduced motion applies the final layout immediately.

Structural items are not independent overflow candidates. A Separator remains in the main action area only when visible actions exist on both sides; leading, trailing, or repeated separators are hidden. More/Listbox renders only contiguous MenuItems, never source separators. Separator width still counts in main-area layout measurement.

More uses SelectButton selectionMode="action" with a direct Listbox and MenuItem composition, without Popover. While its menu is open, allocation freezes so changing column or container width cannot remove the trigger.

API

OverflowAction accepts a resource icon name or Snippet for icon; MenuItem reuses it. Built-in icons use MenuItem’s 16px default and text uses its 14px/20px default, rather than inheriting the icon-only More trigger size. Custom Snippets keep their own appearance. Menu item icon/text size is not separately configurable. An href action is a link when visible and navigates to the same URL from the menu. IDs must be unique within the group.

buttonProps provides group-wide Button defaults to full actions, icon-only actions, hidden measurement copies, and More. parts.Button overrides all actions and More; parts.SelectButton overrides More only and has higher priority. Visible More and its hidden measurement copy use identical final props, so changing variant, size, bare, class, or style does not skew measurement.

The priority of Action is buttonProps → parts.Button → sub-item parts.Button → OverflowAction Direct Props; the priority of More is buttonProps → parts.Button → parts.SelectButton → More controlled behavior field, the later the higher the priority. When the More style is not specified separately, it uses the same Button style as the group-level Action; if there is no group-level style, the default variant="gray" and size="sm" of the Button are used. The direct Props of the explicit OverflowAction as="item" only belong to the external Action, and the parent component will not reverse read these sub-items to infer the More style; therefore, all external Actions only directly specify the style by themselves, and when the parent level does not have a group-level style, More still uses the Button default style.

Data types and inheritance boundaries

OverflowActionsItem is a union: an action is { type?: "action"; id: string; label: string; icon?: string | Snippet; disabled?: boolean; href?: string; target?: string; rel?: string; onAction?: () => void }; a structural item is { type: "separator"; id: string }. Item onAction runs before group onAction. External-link target and rel apply both to visible links and More-menu navigation; new windows always force noopener. Explicit OverflowActions support the same behavior.

GlobalButtonProps excludes children / as / iconOnly / disabled / href / onclick / aria-label / title for Button Props. Parts is ComponentPartsOf<{ Button: typeof Button; SelectButton: typeof SelectButton; Listbox: typeof Listbox; MenuItem: typeof MenuItem; Separator: typeof Separator }>. Each key configuration corresponds to the public Props of the default subcomponent, and the complete override order is shown above.

The rest are compatible with Frame Props through the root container. For shared keywords, please refer to the public API of Frame; the combination layer does not repeat the sharing behavior.

Visible action limit and per-item styles

maxVisible?: number limits directly visible actions, excluding More and separators. By default there is no count limit. Finite values are floored and clamped to zero; NaN and Infinity use the default. Zero shows only More when actions exist; an empty group has no More. The limit applies to full and compact modes, and width may hide additional actions. With all, overflow still moves every action to the menu. An open menu freezes layout until close. Data items support direct Button settings through buttonProps and owned-button settings through parts.Button. Priority is group defaults, group parts, item parts, then item buttonProps; item settings do not alter More.

This section is protected. An AI must request user review before modifying it.



OverflowActions style overlay

Read the full LICENSE first; reuse that review for the same task, version, and scope.

First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.

Variable Purpose and default reference
--snowui-overflow-actions-gap-override Action / Separator / More spacing (default var(--gap-2) = 8px)

Design Guide · Token · Combination Boundary

OverflowActions Type and Status

Required Props: no named required Props.

Bindable Props: this component declares no named two-way binding; handle state updates through public callbacks or its host.

Inheritance: Omit<FrameProps, "children">. Consult the base class public documentation; fields excluded by Omit cannot be passed through unchanged.

Share Frame API · Return API

The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.

OverflowActionsItem

Source: components/src/components/OverflowActions.svelte

export type OverflowActionsItem =        | OverflowActionsActionItem        | OverflowActionsSeparatorItem;

OverflowActionsActionItem

Source: components/src/components/OverflowActions.svelte

export interface OverflowActionsActionItem {        type?: "action";        id: string;        label: string;        icon?: OverflowActionIcon;        disabled?: boolean;        href?: string;        target?: string;        rel?: string;        onAction?: () => void;        buttonProps?: GlobalButtonProps;        parts?: ComponentProps<typeof OverflowAction>["parts"];    }

OverflowActionIcon

Source: components/src/logic/overflow-actions.svelte.ts

export type OverflowActionIcon = string | Snippet;

GlobalButtonProps

Source: components/src/components/OverflowActions.svelte

export type GlobalButtonProps = Omit<ButtonProps, ControlledGlobalButtonKeys>;

ButtonProps

Source: components/src/components/OverflowActions.svelte

type ButtonProps = ComponentProps<typeof Button>;

ControlledGlobalButtonKeys

Source: components/src/components/OverflowActions.svelte

type ControlledGlobalButtonKeys =        | "children"        | "as"        | "iconOnly"        | "disabled"        | "href"        | "onclick"        | "aria-label"        | "title";

OverflowActionsSeparatorItem

Source: components/src/components/OverflowActions.svelte

export interface OverflowActionsSeparatorItem {        type: "separator";        id: string;    }

Parts

Source: components/src/components/OverflowActions.svelte

type Parts = ComponentPartsOf<{        Button: typeof Button;        SelectButton: typeof SelectButton;        Listbox: typeof Listbox;        MenuItem: typeof MenuItem;        Separator: typeof Separator;    }>;

ComponentPartsOf

Source: components/src/logic/component-parts.svelte.ts

export type ComponentPartsOf<    T extends Record<string, Component<any>>,> = {    [K in keyof T]?: ConfigurableComponentPartProps<T[K]>;};

ConfigurableComponentPartProps

Source: components/src/logic/component-parts.svelte.ts

export type ConfigurableComponentPartProps<C extends Component<any>> = Partial<    Omit<ComponentProps<C>, ComponentPartControlledKey>>;

ComponentPartControlledKey

Source: components/src/logic/component-parts.svelte.ts

export type ComponentPartControlledKey =    | "children"    | "as"    | "value"    | "defaultValue"    | "open"    | "selected"    | "checked"    | "disabled"    | "readonly"    | "id"    | `on${string}`    | `aria-${string}`;