EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
Table·component·@astryxdesign/core

Table Selection Toolbar

Selection-aware bulk-action surface built on Toolbar. Pass selectionState from useTableSelectionState so count, visibility, and complete clearing stay synchronized with the Table selection plugin. The component owns no table or sticky layout: place it in flow or apply caller-owned positioning through xstyle.

Open in Playground @astryxdesign/core/Table

Showcases and examples

12 documented examples · Context from Table

Table — Column Settings

Table with a column visibility picker in the toolbar. Toggle columns on and off.

Preview loads on approachPreview loads on approach
Exact source · table-column-settings-table
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {useState} from 'react';
import {
  Table,
  useTableColumnSettings,
  useTableColumnSettingsState,
  proportional,
} from '@astryxdesign/core/Table';
import type {TableColumn} from '@astryxdesign/core/Table';
import {MultiSelector} from '@astryxdesign/core/MultiSelector';
import {VStack} from '@astryxdesign/core/Layout';
import {Toolbar} from '@astryxdesign/core/Toolbar';
import {Text} from '@astryxdesign/core/Text';

interface User extends Record<string, unknown> {
  id: string;
  name: string;
  email: string;
  role: string;
  department: string;
  status: string;
}

const users: User[] = [
  {
    id: '1',
    name: 'Alice Johnson',
    email: 'alice@example.com',
    role: 'Engineer',
    department: 'Platform',
    status: 'Active',
  },
  {
    id: '2',
    name: 'Bob Smith',
    email: 'bob@example.com',
    role: 'Designer',
    department: 'Product',
    status: 'Active',
  },
  {
    id: '3',
    name: 'Charlie Brown',
    email: 'charlie@example.com',
    role: 'Manager',
    department: 'Platform',
    status: 'Away',
  },
  {
    id: '4',
    name: 'Diana Prince',
    email: 'diana@example.com',
    role: 'Engineer',
    department: 'Infra',
    status: 'Active',
  },
  {
    id: '5',
    name: 'Eve Davis',
    email: 'eve@example.com',
    role: 'Admin',
    department: 'Operations',
    status: 'Inactive',
  },
];

const allColumns: TableColumn<User>[] = [
  {key: 'name', header: 'Name', width: proportional(1)},
  {key: 'email', header: 'Email', width: proportional(2)},
  {key: 'role', header: 'Role', width: proportional(1)},
  {key: 'department', header: 'Department', width: proportional(1)},
  {key: 'status', header: 'Status', width: proportional(1)},
];

const columnOptions = [
  {key: 'name' as const, label: 'Name', isAlwaysVisible: true},
  {key: 'email' as const, label: 'Email'},
  {key: 'role' as const, label: 'Role'},
  {key: 'department' as const, label: 'Department'},
  {key: 'status' as const, label: 'Status'},
];

const allKeys: string[] = ['name', 'email', 'role', 'department', 'status'];

export default function TableColumnSettingsTable() {
  const [activeKeys, setActiveKeys] = useState<string[]>(allKeys);

  const state = useTableColumnSettingsState({
    columns: columnOptions,
    activeColumnKeys: activeKeys,
    onChangeActiveColumnKeys: keys => setActiveKeys([...keys]),
  });

  const plugin = useTableColumnSettings<User>(state.columnSettingsConfig);

  const selectorOptions = columnOptions.map(c => ({
    value: c.key,
    label: c.label,
    disabled: c.isAlwaysVisible === true,
  }));

  return (
    <VStack gap={3} width="100%">
      <Toolbar
        label="Table actions"
        startContent={<Text type="label">Team</Text>}
        endContent={
          <MultiSelector
            label="Columns"
            isLabelHidden
            options={selectorOptions}
            value={[...state.activeColumnKeys]}
            onChange={state.setActiveColumnKeys}
          />
        }
      />
      <Table
        data={users}
        columns={allColumns}
        idKey="id"
        hasHover
        plugins={{columnSettings: plugin}}
      />
    </VStack>
  );
}

Usage

Pass both outputs of useTableSelectionState to their matching consumers: selectionConfig to useTableSelection and selectionState to TableSelectionToolbar. Render product actions through startContent. Keep fixed or floating placement in the surrounding layout.

  • Pass selectionState directly from useTableSelectionState so the count and clear action stay synchronized with row selection.
  • Provide product actions as startContent instead of encoding them as configuration objects.
  • Inject the toolbar through the Table plugin or its horizontal scroll wrapper.

Typed props

PropType and behavior
selectionTableSelectionState · required
Shared selection state returned by useTableSelectionState: selectedKeys, selectedCount, hasSelection, and clearSelection.
startContentReactNode
Product-owned action controls aligned to the logical start. Child controls inherit the toolbar size.
labelstring · default Bulk actions
Accessible name for the action surface.
renderSelectionLabel(selectedCount: number) => ReactNode · default count => `${count} selected`
Overrides the visible count text for localisation or domain-specific copy.
clearLabelstring · default Unselect All
Visible label for the command that clears the complete controlled selection.
size'sm' | 'md' | 'lg' · default sm
Toolbar size. Cascades to product action controls and the clear action.
variantSectionVariant · default muted
Toolbar surface variant.
xstyleStyleXStyles
Caller-owned layout styles, including sticky positioning for floating compositions.