/**
* Toolbox.stories.ts - Stories demonstrating toolbox customization.
*
* This file demonstrates how to set custom icons for all available tools
* in the toolbox using the tool settings configuration.
*/
import type { Meta, StoryObj } from '@storybook/html-vite';
import { waitFor, expect } from 'storybook/test';
import { Header } from '../tools/header';
import { Paragraph } from '../tools/paragraph';
import { createEditorContainer, simulateClick, waitForToolbar, TOOLBAR_TESTID } from './helpers';
import type { EditorFactoryOptions } from './helpers';
import type { OutputData, ToolSettings, BlockToolConstructable } from '@/types';
interface ToolboxArgs extends EditorFactoryOptions {
minHeight: number;
data: OutputData | undefined;
}
// Constants
const BLOCK_TESTID = '[data-blok-testid="block-wrapper"]';
const PLUS_BUTTON_TESTID = '[data-blok-testid="plus-button"]';
const TOOLBOX_OPENED_SELECTOR = '[data-blok-toolbox-opened="true"]';
const POPOVER_ITEM_TESTID = '[data-blok-testid="popover-item"]';
const TIMEOUT_INIT = { timeout: 5000 };
const TIMEOUT_ACTION = { timeout: 5000 };
// Custom SVG icons for demonstration
const CustomIcons = {
// Star icon for Paragraph
star: ``,
// Crown icon for Heading
crown: ``,
};
const sampleData: OutputData = {
time: Date.now(),
version: '1.0.0',
blocks: [
{
id: 'toolbox-block-1',
type: 'paragraph',
data: { text: 'Click the plus button to see the toolbox with custom icons.' },
},
],
};
const createEditor = (args: ToolboxArgs): HTMLElement => createEditorContainer(args);
const meta: Meta = {
title: 'Components/Toolbox',
tags: ['autodocs'],
args: {
minHeight: 300,
width: 450,
data: sampleData,
},
render: createEditor,
};
export default meta;
type Story = StoryObj;
/**
* Toolbox with custom icons for all tools.
*
* This story demonstrates how to override the default toolbox icons
* for both Paragraph and Header tools using the `toolbox` configuration
* in tool settings.
*
* To customize icons, use the `toolbox` property in tool settings:
* ```typescript
* tools: {
* paragraph: {
* class: Paragraph,
* toolbox: {
* icon: '',
* title: 'Custom Title'
* }
* }
* }
* ```
*/
export const CustomIconsForAllTools: Story = {
args: {
data: sampleData,
tools: {
paragraph: {
class: Paragraph as unknown as BlockToolConstructable,
toolbox: {
icon: CustomIcons.star,
title: 'Paragraph',
},
} as ToolSettings,
header: {
class: Header as unknown as BlockToolConstructable,
toolbox: {
icon: CustomIcons.crown,
title: 'Header',
},
} as ToolSettings,
},
},
parameters: {
chromatic: { delay: 500 },
},
play: async ({ canvasElement, step }) => {
await step('Wait for editor and toolbar to initialize', async () => {
await waitFor(
() => {
const block = canvasElement.querySelector(BLOCK_TESTID);
expect(block).toBeInTheDocument();
},
TIMEOUT_INIT
);
await waitForToolbar(canvasElement);
});
await step('Click block to show toolbar', async () => {
const block = canvasElement.querySelector(BLOCK_TESTID);
if (block) {
simulateClick(block);
}
await waitFor(
() => {
const toolbar = canvasElement.querySelector(TOOLBAR_TESTID);
expect(toolbar).toHaveAttribute('data-blok-opened', 'true');
},
TIMEOUT_ACTION
);
});
await step('Open toolbox to see custom icons', async () => {
const plusButton = canvasElement.querySelector(PLUS_BUTTON_TESTID);
if (plusButton) {
simulateClick(plusButton);
}
await waitFor(
() => {
const editor = canvasElement.querySelector(TOOLBOX_OPENED_SELECTOR);
expect(editor).toBeInTheDocument();
// Verify popover items are rendered
const items = document.querySelectorAll(POPOVER_ITEM_TESTID);
expect(items.length).toBeGreaterThan(0);
},
TIMEOUT_ACTION
);
});
},
};