Communitygithub.com

Cratis/AI

Free, MIT-licensed AI skills, rules, and agent guidance for building event-sourced and CQRS applications with the Cratis ecosystem (preview).

AI とは?

AI is a Claude Code agent skill that free, MIT-licensed AI skills, rules, and agent guidance for building event-sourced and CQRS applications with the Cratis ecosystem (preview).

対応~Claude Code~Codex CLI~Cursor
npx skills add Cratis/AI

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

When to use the Toolbar

The Toolbar component is designed for canvas-style tool panels — the kind you find in drawing or diagram editors. It groups ToolbarButton elements into a pill-shaped bar with hover tooltips and active highlights. Use it when you need:

  • A tool selector with an "active tool" state
  • A set of action buttons that animate between tool modes
  • A toolbar that fans out sub-panels for grouped tools

For a standard page action menu (Create / Edit / Delete over a data table), use DataPage.MenuItems instead.


Component overview

ComponentPurpose
ToolbarContainer — renders a pill-shaped bar of buttons
ToolbarButtonIcon or text button with tooltip and optional active state
ToolbarSeparatorVisual divider between button groups
ToolbarSectionAnimated section that transitions between named contexts
ToolbarContextNamed set of buttons inside a ToolbarSection
ToolbarFanOutItemButton that slides out a horizontal sub-panel on click

All components import from the @cratis/components/Toolbar subpath (never the root barrel — see components.md):

import { Toolbar, ToolbarButton, ToolbarSeparator, ToolbarSection, ToolbarContext, ToolbarFanOutItem } from '@cratis/components/Toolbar';

Step 1 — Basic vertical toolbar

Place ToolbarButton elements inside Toolbar. The default orientation is vertical.

import { Toolbar, ToolbarButton } from '@cratis/components/Toolbar';

export const DrawingToolbar = () => (
    <Toolbar>
        <ToolbarButton icon='pi pi-arrow-up-left' tooltip='Select' />
        <ToolbarButton icon='pi pi-pencil' tooltip='Draw' />
        <ToolbarButton icon='pi pi-stop' tooltip='Rectangle' />
    </Toolbar>
);

Step 2 — Active state (selected tool)

Use the active prop to highlight the currently selected tool. Drive it from state:

import { useState } from 'react';
import { Toolbar, ToolbarButton } from '@cratis/components/Toolbar';

export const DrawingToolbar = () => {
    const [activeTool, setActiveTool] = useState('select');

    return (
        <Toolbar>
            <ToolbarButton
                icon='pi pi-arrow-up-left'
                tooltip='Select'
                active={activeTool === 'select'}
                onClick={() => setActiveTool('select')}
            />
            <ToolbarButton
                icon='pi pi-pencil'
                tooltip='Draw'
                active={activeTool === 'draw'}
                onClick={() => setActiveTool('draw')}
            />
            <ToolbarButton
                icon='pi pi-stop'
                tooltip='Rectangle'
                active={activeTool === 'rect'}
                onClick={() => setActiveTool('rect')}
            />
        </Toolbar>
    );
};

Step 3 — Separators

ToolbarSeparator draws a thin divider line between groups. Pass the same orientation as the enclosing Toolbar:

<Toolbar>
    <ToolbarButton icon='pi pi-pencil' tooltip='Draw' />
    <ToolbarButton icon='pi pi-stop' tooltip='Rectangle' />
    <ToolbarSeparator />
    <ToolbarButton icon='pi pi-undo' tooltip='Undo' />
    <ToolbarButton icon='pi pi-refresh' tooltip='Redo' />
</Toolbar>

Step 4 — Horizontal toolbar with text buttons

Pass orientation='horizontal' for a horizontal layout. Use text for buttons that display a value (e.g. zoom percentage):

import { useState } from 'react';
import { Toolbar, ToolbarButton, ToolbarSeparator } from '@cratis/components/Toolbar';

export const ZoomToolbar = () => {
    const [zoom, setZoom] = useState(100);

    return (
        <Toolbar orientation='horizontal'>
            <ToolbarButton icon='pi pi-minus' tooltip='Zoom out' tooltipPosition='bottom' onClick={() => setZoom(z => z - 10)} />
            <ToolbarButton text={`${zoom}%`} tooltip='Reset zoom' tooltipPosition='bottom' onClick={() => setZoom(100)} />
            <ToolbarButton icon='pi pi-plus' tooltip='Zoom in' tooltipPosition='bottom' onClick={() => setZoom(z => z + 10)} />
            <ToolbarSeparator orientation='horizontal' />
            <ToolbarButton icon='pi pi-question-circle' tooltip='Help' tooltipPosition='bottom' />
        </Toolbar>
    );
};

For horizontal toolbars, set tooltipPosition='bottom' (or 'top') so tooltips do not overlap the toolbar.


Step 5 — Animated context switching

ToolbarSection + ToolbarContext allows the toolbar to show different sets of buttons depending on the active mode. When activeContext changes, the buttons fade out, the section morphs to the new size, and the new buttons fade in.

import { useState } from 'react';
import { Toolbar, ToolbarButton, ToolbarSection, ToolbarContext } from '@cratis/components/Toolbar';

export const ContextualToolbar = () => {
    const [mode, setMode] = useState<'drawing' | 'text'>('drawing');

    return (
        <Toolbar>
            <ToolbarButton icon='pi pi-arrow-up-left' tooltip='Select' />
            <ToolbarSection activeContext={mode}>
                <ToolbarContext name='drawing'>
                    <ToolbarButton icon='pi pi-pencil' tooltip='Draw' />
                    <ToolbarButton icon='pi pi-stop' tooltip='Rectangle' />
                    <ToolbarButton icon='pi pi-circle' tooltip='Circle' />
                </ToolbarContext>
                <ToolbarContext name='text'>
                    <ToolbarButton icon='pi pi-align-left' tooltip='Align Left' />
                    <ToolbarButton icon='pi pi-align-center' tooltip='Align Center' />
                    <ToolbarButton icon='pi pi-align-right' tooltip='Align Right' />
                </ToolbarContext>
            </ToolbarSection>
            <ToolbarButton icon='pi pi-undo' tooltip='Undo' />
        </Toolbar>
    );
};

Only the ToolbarSection transitions. Buttons outside the section are unaffected.


Step 6 — Fan-out sub-panel

ToolbarFanOutItem replaces a regular button with one that fans out a horizontal panel of additional tools. Clicking the button again or anywhere outside closes the panel.

import { Toolbar, ToolbarButton, ToolbarFanOutItem } from '@cratis/components/Toolbar';

export const ShapesToolbar = () => (
    <Toolbar>
        <ToolbarButton icon='pi pi-arrow-up-left' tooltip='Select' />
        <ToolbarFanOutItem icon='pi pi-th-large' tooltip='Shapes'>
            <ToolbarButton icon='pi pi-stop' tooltip='Rectangle' />
            <ToolbarButton icon='pi pi-circle' tooltip='Circle' />
            <ToolbarButton icon='pi pi-minus' tooltip='Line' />
        </ToolbarFanOutItem>
    </Toolbar>
);

When the toolbar is on the right side of the screen, fan out to the left:

<ToolbarFanOutItem icon='pi pi-th-large' tooltip='Shapes' fanOutDirection='left'>
    ...
</ToolbarFanOutItem>

Props reference

Toolbar

PropTypeDefaultDescription
childrenReactNodeToolbarButton, ToolbarSeparator, ToolbarSection, or ToolbarFanOutItem elements
orientation'vertical' | 'horizontal''vertical'Layout direction

ToolbarButton

PropTypeDefaultDescription
iconstringPrimeIcons CSS class (e.g. 'pi pi-pencil')
textstringText shown inside the button (use for values like zoom %)
tooltipstringrequiredTooltip text on hover
activebooleanfalseHighlights the button as selected
onClick() => voidClick handler
tooltipPosition'top' | 'right' | 'bottom' | 'left''right'Tooltip position

ToolbarSeparator

PropTypeDefaultDescription
orientation'vertical' | 'horizontal''vertical'Match the enclosing Toolbar orientation

ToolbarSection

PropTypeDefaultDescription
activeContextstringfirst context nameName of the active ToolbarContext
childrenToolbarContext[]ToolbarContext children
orientation'vertical' | 'horizontal''vertical'Match the enclosing Toolbar

ToolbarContext

PropTypeDefaultDescription
namestringrequiredIdentifier matched by ToolbarSection.activeContext
childrenReactNodeToolbarButton elements for this context

ToolbarFanOutItem

PropTypeDefaultDescription
iconstringrequiredPrimeIcons CSS class for the trigger button
tooltipstringrequiredTooltip for the trigger button
tooltipPosition'top' | 'right' | 'bottom' | 'left''right'Tooltip position
fanOutDirection'right' | 'left''right'Direction the sub-panel slides out
childrenReactNodeToolbarButton elements inside the fan-out panel

Multiple toolbar groups

Render separate Toolbar instances to create distinct groups:

<div className='flex flex-column gap-2'>
    <Toolbar>
        <ToolbarButton icon='pi pi-arrow-up-left' tooltip='Select' />
        <ToolbarButton icon='pi pi-pencil' tooltip='Draw' />
    </Toolbar>
    <Toolbar>
        <ToolbarButton icon='pi pi-undo' tooltip='Undo' />
        <ToolbarButton icon='pi pi-refresh' tooltip='Redo' />
    </Toolbar>
</div>

Validation

After creating or modifying a Toolbar component, run:

yarn lint
npx tsc -b

Fix all errors before proceeding.

関連スキル