高亮
Storybook 的 Highlight 功能是可视化调试组件的有用工具。它允许你在直接使用或增强插件(例如 可访问性插件)时高亮故事中的特定 DOM 节点,以告知你组件中的可访问性问题。
¥Storybook's Highlight feature is a helpful tool for visually debugging your components. It allows you to highlight specific DOM nodes within your story when used directly or enhancing addons such as the Accessibility addon to inform you of accessibility issues within your components.

高亮 DOM 元素
¥Highlighting DOM Elements
要使用该功能高亮 DOM 元素,你需要在故事或插件中发出 HIGHLIGHT 事件。事件负载必须包含一个 selectors 属性,该属性分配给与要高亮的元素匹配的选择器数组。例如:
¥To highlight DOM elements with the feature, you'll need to emit the HIGHLIGHT event from within a story or an addon. The event payload must contain a selectors property assigned to an array of selectors matching the elements you want to highlight. For example:
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
import { useChannel } from 'storybook/preview-api';
import { HIGHLIGHT } from 'storybook/highlight';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Highlighted: Story = {
decorators: [
(storyFn) => {
const emit = useChannel({});
emit(HIGHLIGHT, {
selectors: ['h2', 'a', '.storybook-button'],
});
return storyFn();
},
],
};我们建议选择最具体的选择器,以避免高亮其他插件使用的元素。这是因为该功能会尝试将选择器与整个 DOM 树进行匹配。
¥We recommend choosing the most specific selector possible to avoid highlighting elements other addons use. This is because the feature tries to match selectors against the entire DOM tree.
自定义样式
¥Customize style
默认情况下,高亮元素会应用标准轮廓样式。但是,你可以通过扩展有效负载对象并添加其他属性来启用自定义样式,从而自定义高亮元素的外观。例如:
¥By default, highlighted elements contain a standard outline style applied to the selected elements. However, you can enable your custom style by extending the payload object with additional properties to customize the appearance of the highlighted elements. For example:
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
import { useChannel } from 'storybook/preview-api';
import { HIGHLIGHT } from 'storybook/highlight';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const StyledHighlight: Story = {
decorators: [
(storyFn) => {
const emit = useChannel({});
emit(HIGHLIGHT, {
selectors: ['h2', 'a', '.storybook-button'],
styles: {
backgroundColor: `color-mix(in srgb, hotpink, transparent 90%)`,
outline: '3px solid hotpink',
animation: 'pulse 3s linear infinite',
transition: 'outline-offset 0.2s ease-in-out',
},
hoverStyles: {
outlineOffset: '3px',
},
focusStyles: {
backgroundColor: 'transparent',
},
keyframes: `@keyframes pulse {
0% { outline-color: rgba(255, 105, 180, 1); }
50% { outline-color: rgba(255, 105, 180, 0.2); }
100% { outline-color: rgba(255, 105, 180, 1); }
}`,
});
return storyFn();
},
],
};这些属性是可选的,你可以使用它们来自定义高亮元素的外观。建议将 hoverStyles 和 focusStyles 属性与 menu 属性一起使用。不支持伪类和伪元素。
¥These properties are optional, and you can use them to customize the appearance of the highlighted elements. The hoverStyles and focusStyles properties are recommended for use with the menu property. Pseudo-classes and pseudo-elements are not supported.
高亮菜单
¥Highlight menu
高亮功能包含一个内置调试选项,允许你在点击高亮显示的元素时选中它们。这对于检查受该功能影响的元素特别有用,因为它可以预览与你提供的选择器匹配的元素列表。要启用它,请在有效负载对象中添加一个 menu 属性,其中包含有关元素或触发器操作的附加信息。每个菜单项必须包含一个 id 和一个 title,你还可以提供一个可选的 selectors 属性,以将菜单项限制为特定的高亮元素。
¥The Highlight feature includes a built-in debugging option, allowing you to select the highlighted elements when you click them. This is particularly useful for inspecting the elements affected by the feature, as it lets you preview a list of elements matching the selector you provided. To enable it, add a menu property in the payload object containing additional information about the elements or trigger actions. Each item must include an id and a title, and you can also provide an optional selectors property to limit the menu item to specific highlighted elements.

// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
import { useChannel } from 'storybook/preview-api';
import { HIGHLIGHT } from 'storybook/highlight';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const StyledHighlight: Story = {
decorators: [
(storyFn) => {
const emit = useChannel({});
emit(HIGHLIGHT, {
selectors: ['h2', 'a', '.storybook-button'],
menu: [
[
{
id: 'button-name',
title: 'Login',
description: 'Navigate to the login page',
clickEvent: 'my-menu-click-event',
},
{
id: 'h2-home',
title: 'Acme',
description: 'Navigate to the home page',
},
],
],
});
return storyFn();
},
],
};启用后,当你点击与你提供的选择器匹配的选定元素时,将显示菜单。但是,如果你不想显示任何信息,可以省略这些项目或将 menu 属性设置为空数组以显示默认菜单。
¥When enabled, the menu will be displayed when you click on the selected element matching your provided selectors. However, if you don't want to show any information, you can omit the items or set the menu property to an empty array to show the default menu.

移除高亮
¥Remove highlights
如果你需要从特定元素中删除高亮显示,你可以通过发出 REMOVE_HIGHLIGHT 事件并提供要删除的高亮显示的 id 来实现。例如:
¥If you need to remove a highlight from a specific element, you can do so by emitting the REMOVE_HIGHLIGHT event and providing the id of the highlight you want to remove. For example:
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
import { useChannel } from 'storybook/preview-api';
import { HIGHLIGHT, REMOVE_HIGHLIGHT } from 'storybook/highlight';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const RemoveHighlight: Story = {
decorators: [
(storyFn) => {
const emit = useChannel({});
emit(HIGHLIGHT, {
id: 'my-unique-id',
selectors: ['header', 'section', 'footer'],
});
emit(REMOVE_HIGHLIGHT, 'my-unique-id');
return storyFn();
},
],
};从 useChannel API 钩子派生的 emit 函数在 Storybook 的 UI 中创建了一个通信通道,以监听事件并相应地更新 UI。高亮功能使用此通道监听自定义事件并相应地更新高亮显示的元素(如果有)。
¥The emit function derived from the useChannel API hook creates a communication channel in Storybook's UI to listen for events and update the UI accordingly. The Highlight feature uses this channel to listen to custom events and update the highlighted elements (if any) accordingly.
重置高亮的元素
¥Reset highlighted elements
开箱即用,Storybook 会在故事之间转换时自动删除高亮的元素。但是,如果你需要手动清除它们,则可以在故事或插件中发出 RESET_HIGHLIGHT 事件。这将删除所有高亮显示,即使是由其他插件创建的。例如:
¥Out of the box, Storybook automatically removes highlighted elements when transitioning between stories. However, if you need to clear them manually, you can emit the RESET_HIGHLIGHT event from within a story or an addon. This removes all highlights, even ones created by other addons. For example:
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
import { useChannel } from 'storybook/preview-api';
import { HIGHLIGHT, RESET_HIGHLIGHT } from 'storybook/highlight';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const ResetHighlight: Story = {
decorators: [
(storyFn) => {
const emit = useChannel({});
emit(RESET_HIGHLIGHT); //👈 Remove previously highlighted elements
emit(HIGHLIGHT, {
selectors: ['header', 'section', 'footer'],
});
return storyFn();
},
],
};将元素滚动到视图中
¥Scroll element into view
高亮功能允许你将元素滚动到视图中并高亮显示它。要启用它,请从故事或插件中发出 SCROLL_INTO_VIEW 事件。事件负载必须包含一个 selector 属性,以定位你想要滚动到视图中的元素。当元素可见时,它将短暂高亮显示。
¥The Highlight feature allows you to scroll an element into view and highlight it. To enable it, emit the SCROLL_INTO_VIEW event from within a story or an addon. The event payload must contain a selector property to target the element you want to scroll into view. When the element is visible, it will be highlighted for a brief moment.
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
import type { Meta, StoryObj } from '@storybook/your-framework';
import { useChannel } from 'storybook/preview-api';
import { SCROLL_INTO_VIEW } from 'storybook/highlight';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const ScrollIntoView: Story = {
decorators: [
(storyFn) => {
const emit = useChannel({});
emit(SCROLL_INTO_VIEW, '#footer');
return storyFn();
},
],
};API
参数
¥Parameters
此功能将以下 参数 贡献给 Storybook,位于 highlight 命名空间下:
¥This feature contributes the following parameters to Storybook, under the highlight namespace:
disable
类型:boolean
¥Type: boolean
禁用此功能的行为。如果你希望为整个 Storybook 关闭此功能,你应该 在主配置文件中执行此操作。
¥Disable this feature's behavior. If you wish to turn off this feature for the entire Storybook, you should do so in your main configuration file.
此参数最有用,允许在更具体的级别进行覆盖。例如,如果此参数在项目级别设置为 true,则可以通过在元(组件)或故事级别将其设置为 false 来重新启用它。
¥This parameter is most useful to allow overriding at more specific levels. For example, if this parameter is set to true at the project level, it could be re-enabled by setting it to false at the meta (component) or story level.
导出
¥Exports
此功能将以下导出贡献给 Storybook:
¥This feature contributes the following exports to Storybook:
import { HIGHLIGHT, REMOVE_HIGHLIGHT, RESET_HIGHLIGHT, SCROLL_INTO_VIEW } from 'storybook/highlight';HIGHLIGHT
一个事件,用于高亮显示 DOM 元素。事件负载必须包含一个 selectors 属性,该属性分配给与要高亮的元素匹配的选择器数组。它可以通过包含其他配置选项的可选对象进行扩展。请参阅上面的 使用示例。
¥An event to highlight DOM elements. The event payload must contain a selectors property assigned to an array of selectors matching the elements you want to highlight. It can be extended with an optional object containing additional configuration options. See the usage example above.
import { HIGHLIGHT, type HighlightOptions } from 'storybook/highlight';
channel.emit(
HIGHLIGHT,
options // The available configuration options inheriting from the HighlightOptions API
);options 对象包含以下属性:
¥The options object contains the following properties:
interface HighlightOptions {
/** Unique identifier for the highlight, required if you want to remove the highlight later */
id?: string;
/** HTML selectors of the elements */
selectors: string[];
/** Priority of the highlight, higher takes precedence, defaults to 0 */
priority?: number;
/** CSS styles to apply to the highlight */
styles?: Record<string, string>;
/** CSS styles to apply to the highlight when it is hovered */
hoverStyles?: Record<string, string>;
/** CSS styles to apply to the highlight when it is focused or selected */
focusStyles?: Record<string, string>;
/** Keyframes required for animations */
keyframes?: string;
/** Groups of menu items to show when the highlight is selected */
menu?: HighlightMenuItem[][];
}
interface HighlightMenuItem {
/** Unique identifier for the menu item */
id: string;
/** Title of the menu item */
title: string;
/** Description of the menu item */
description?: string;
/** Icon for the menu item, left side */
iconLeft?: "chevronLeft" | "chevronRight" | "info" | "shareAlt";
/** Icon for the menu item, right side */
iconRight?: "chevronLeft" | "chevronRight" | "info" | "shareAlt";
/** Name for a channel event to trigger when the menu item is clicked */
clickEvent?: string;
/** HTML selectors for which this menu item should show (subset of HighlightOptions['selectors']) */
selectors?: HighlightOptions['selectors'];
}菜单项可以指定在点击菜单项时在通道上发出的 clickEvent 事件。channel 事件将接收两个参数:菜单项 id 和具有以下属性的 ClickEventDetails 对象:
¥Menu items can specify a clickEvent to be emitted on the channel when the item is clicked. The channel event will receive two arguments: the menu item id and a ClickEventDetails object with the following properties:
interface ClickEventDetails {
// Position and dimensions of the element on the page
top: number;
left: number;
width: number;
height: number;
// Selector(s) which matched the element
selectors: string[];
// DOM element details
element: {
attributes: Record<string, string>;
localName: string;
tagName: string;
outerHTML: string;
};
}要监听此事件(假设 clickEvent: 'MY_CLICK_EVENT'):
¥To listen for this event (assuming clickEvent: 'MY_CLICK_EVENT'):
import type { ClickEventDetails } from 'storybook/highlight';
const handleClickEvent = (itemId: string, details: ClickEventDetails) => {
// Handle the menu item click event
}
// When you have a channel instance:
channel.on('MY_CLICK_EVENT', handleClickEvent)
// Or from a decorator:
useChannel({
MY_CLICK_EVENT: handleClickEvent,
}, [handleClickEvent])REMOVE_HIGHLIGHT
一个事件,用于移除先前创建的高亮显示。事件负载必须包含一个 id 属性,该属性分配给你想要移除的高亮显示的 ID。请参阅上面的 使用示例。
¥An event that removes a previously created highlight. The event payload must contain an id property assigned to the id of the highlight you want to remove. See the usage example above.
import { REMOVE_HIGHLIGHT } from 'storybook/highlight';
channel.emit(
REMOVE_HIGHLIGHT,
id // The id of the previously created highlight to be removed
);RESET_HIGHLIGHT
清除高亮元素的所有高亮的事件。请参阅上面的 使用示例。
¥An event to clear all highlights from highlighted elements. See the usage example above.
import { RESET_HIGHLIGHT } from 'storybook/highlight';
channel.emit(RESET_HIGHLIGHT);SCROLL_INTO_VIEW
一个事件,用于将 DOM 元素滚动到视图中并短暂高亮显示。事件负载必须包含一个 selector 属性,该属性分配给你想要滚动到视图中的元素的选择器。你可以选择提供一个 options 对象来自定义滚动行为。请参阅上面的 使用示例。
¥An event to scroll a DOM element into view and briefly highlight it. The event payload must contain a selector property assigned to the selector of the element you want to scroll into view. Optionally, you can provide a options object to customize the scroll behavior. See the usage example above.
import { SCROLL_INTO_VIEW } from 'storybook/highlight';
channel.emit(
SCROLL_INTO_VIEW,
selector // Element selector to scroll into view
options // An object inheriting from ScrollIntoViewOptions API to customize the scroll behavior
);