Storybook 8 Upgrade Follow Up (#214684)

## Summary

These Stories were missed in [Upgrade to Storybook 8
(#195148)](https://github.com/elastic/kibana/pull/195148) and should be
migrated to the same format as other stories for consistency and to make
future migrations easier. They technically work in SB8, I forgot to run
the migration script again later on while working on the original PR.

The changes have already been backported to #214680 and #214681
This commit is contained in:
Brad White 2025-03-24 12:28:19 -06:00 committed by GitHub
parent 80c782d863
commit 31aa294124
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 478 additions and 391 deletions

View file

@ -1566,6 +1566,7 @@
"@storybook/addon-a11y": "^8.6.3",
"@storybook/addon-actions": "^8.6.3",
"@storybook/addon-essentials": "^8.6.3",
"@storybook/addon-jest": "8.6.3",
"@storybook/addon-styling-webpack": "^1.0.1",
"@storybook/addon-webpack5-compiler-babel": "^3.0.5",
"@storybook/blocks": "^8.6.3",

View file

@ -9,7 +9,7 @@
import React from 'react';
import { action } from '@storybook/addon-actions';
import { Meta } from '@storybook/react';
import type { Meta, StoryObj } from '@storybook/react';
import { FieldDefinition } from '@kbn/management-settings-types';
import { getFieldDefinitions } from '@kbn/management-settings-field-definition';
import { getSettingsMock } from '@kbn/management-settings-utilities/mocks/settings.mock';
@ -66,30 +66,34 @@ interface FormStoryProps {
requirePageReload: boolean;
}
export const Form = ({ isSavingEnabled, requirePageReload }: FormStoryProps) => {
const fields: FieldDefinition[] = getFieldDefinitions(
getSettingsMock(requirePageReload),
uiSettingsClientMock
);
export const Form: StoryObj<FormStoryProps> = {
render: ({ isSavingEnabled, requirePageReload }) => {
const fields: FieldDefinition[] = getFieldDefinitions(
getSettingsMock(requirePageReload),
uiSettingsClientMock
);
const categorizedFields = categorizeFields(fields);
const categorizedFields = categorizeFields(fields);
const categoryCounts = Object.keys(categorizedFields).reduce(
(acc, category) => ({
...acc,
[category]: categorizedFields[category].count,
}),
{}
);
const categoryCounts = Object.keys(categorizedFields).reduce(
(acc, category) => ({
...acc,
[category]: categorizedFields[category].count,
}),
{}
);
const onClearQuery = () => {};
const onClearQuery = () => {};
return (
<Component {...{ fields, isSavingEnabled, categoryCounts, onClearQuery, scope: 'namespace' }} />
);
};
Form.args = {
isSavingEnabled: true,
requirePageReload: false,
return (
<Component
{...{ fields, isSavingEnabled, categoryCounts, onClearQuery, scope: 'namespace' }}
/>
);
},
args: {
isSavingEnabled: true,
requirePageReload: false,
},
};

View file

@ -8,7 +8,7 @@
*/
import React from 'react';
import type { Meta, StoryFn } from '@storybook/react';
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { Tab, type TabProps } from '../tab';
import { servicesMock } from '../../../__mocks__/services';
@ -47,38 +47,50 @@ const TabTemplate: StoryFn<TabProps> = (args) => (
/>
);
export const Default = TabTemplate.bind({});
Default.args = {
item: {
id: '1',
label: 'Tab 1',
export const Default: StoryObj<TabProps> = {
render: TabTemplate,
args: {
item: {
id: '1',
label: 'Tab 1',
},
isSelected: false,
},
isSelected: false,
};
export const Selected = TabTemplate.bind({});
Selected.args = {
item: {
id: '1',
label: 'Tab 1',
export const Selected: StoryObj<TabProps> = {
render: TabTemplate,
args: {
item: {
id: '1',
label: 'Tab 1',
},
isSelected: true,
},
isSelected: true,
};
export const WithLongLabel = TabTemplate.bind({});
WithLongLabel.args = {
item: {
id: '1',
label: 'Tab with a very long label that should be truncated',
export const WithLongLabel: StoryObj<TabProps> = {
render: TabTemplate,
args: {
item: {
id: '1',
label: 'Tab with a very long label that should be truncated',
},
isSelected: false,
},
isSelected: false,
};
export const WithLongLabelSelected = TabTemplate.bind({});
WithLongLabelSelected.args = {
item: {
id: '1',
label: 'Tab with a very long label that should be truncated',
export const WithLongLabelSelected: StoryObj<TabProps> = {
render: TabTemplate,
args: {
item: {
id: '1',
label: 'Tab with a very long label that should be truncated',
},
isSelected: true,
},
isSelected: true,
};

View file

@ -8,7 +8,7 @@
*/
import React from 'react';
import type { Meta, StoryFn } from '@storybook/react';
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { TabbedContent, type TabbedContentProps } from '../tabbed_content';
import { useNewTabProps } from '../../hooks/use_new_tab_props';
@ -42,31 +42,37 @@ const TabbedContentTemplate: StoryFn<TabbedContentProps> = (args) => {
);
};
export const Default = TabbedContentTemplate.bind({});
Default.args = {
initialItems: [
{
id: '1',
label: 'Tab 1',
},
],
export const Default: StoryObj<TabbedContentProps> = {
render: TabbedContentTemplate,
args: {
initialItems: [
{
id: '1',
label: 'Tab 1',
},
],
},
};
export const WithMultipleTabs = TabbedContentTemplate.bind({});
WithMultipleTabs.args = {
initialItems: [
{
id: '1',
label: 'Tab 1',
},
{
id: '2',
label: 'Tab 2',
},
{
id: '3',
label: 'Tab 3',
},
],
initialSelectedItemId: '3',
export const WithMultipleTabs: StoryObj<TabbedContentProps> = {
render: TabbedContentTemplate,
args: {
initialItems: [
{
id: '1',
label: 'Tab 1',
},
{
id: '2',
label: 'Tab 2',
},
{
id: '3',
label: 'Tab 3',
},
],
initialSelectedItemId: '3',
},
};

View file

@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { Meta } from '@storybook/react';
import type { Meta } from '@storybook/react';
import React, { EventHandler, FC, MouseEvent, useState, useEffect } from 'react';
import { of } from 'rxjs';

View file

@ -8,7 +8,7 @@
*/
import React from 'react';
import { Meta } from '@storybook/react';
import { Meta, StoryObj } from '@storybook/react';
import { EuiButton } from '@elastic/eui';
import { action } from '@storybook/addon-actions';
@ -56,7 +56,7 @@ const titleConfigBase: FieldConfig<string> = {
// --- SIMPLE
export const Simple = (args: Args) => {
const SimpleStoryComponent = (args: Args) => {
const { form } = useForm();
return (
@ -73,10 +73,12 @@ export const Simple = (args: Args) => {
);
};
Simple.parameters = {
docs: {
source: {
code: `
export const Simple: StoryObj<Args> = {
render: (args) => <SimpleStoryComponent {...args} />,
parameters: {
docs: {
source: {
code: `
const MyFormComponent = () => {
const { form } = useForm();
@ -102,7 +104,8 @@ const MyFormComponent = () => {
);
};
`,
language: 'tsx',
language: 'tsx',
},
},
},
};
@ -115,7 +118,7 @@ const formSchema = {
},
};
export const Schema = (args: Args) => {
const SchemaStoryComponent = (args: Args) => {
const { form } = useForm({
schema: formSchema,
});
@ -128,10 +131,12 @@ export const Schema = (args: Args) => {
);
};
Schema.parameters = {
docs: {
source: {
code: `
export const Schema: StoryObj<Args> = {
render: (args) => <SchemaStoryComponent {...args} />,
parameters: {
docs: {
source: {
code: `
const formSchema = {
title: {
label: 'Title',
@ -159,7 +164,8 @@ const MyFormComponent = () => {
);
};
`,
language: 'tsx',
language: 'tsx',
},
},
},
};

View file

@ -33,9 +33,6 @@ const Renderer = () => {
export default {
title: 'renderers/image',
};
export const Default = {
render: (_, props) => {
return <Renderer />;
},

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { I18nProvider } from '@kbn/i18n-react';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
@ -31,8 +31,10 @@ const defaultProps = {
alert,
};
export const StatusBar = Template.bind({});
StatusBar.args = defaultProps;
export const StatusBar: StoryObj<StatusBarProps> = {
render: Template,
args: defaultProps,
};
const services = {
http: {

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import type { Meta, StoryFn } from '@storybook/react';
import type { Meta, StoryFn, StoryObj } from '@storybook/react';
import { ThemeProvider, css } from '@emotion/react';
import { action } from '@storybook/addon-actions';
import { Actions as ActionsComponent, type ActionsProps } from './actions';
@ -38,11 +38,13 @@ const Template: StoryFn<ActionsProps> = (props) => {
);
};
export const Actions = Template.bind({});
export const Actions: StoryObj<ActionsProps> = {
render: Template,
Actions.args = {
showToggleSearch: true,
searchFilterCounter: 0,
showInvestigateInTimeline: true,
searchToggled: false,
args: {
showToggleSearch: true,
searchFilterCounter: 0,
showInvestigateInTimeline: true,
searchToggled: false,
},
};

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import type { StoryFn, Meta } from '@storybook/react';
import type { StoryFn, Meta, StoryObj } from '@storybook/react';
import { ThemeProvider, css } from '@emotion/react';
import { ReactFlowProvider } from '@xyflow/react';
import { action } from '@storybook/addon-actions';
@ -49,10 +49,12 @@ const Template: StoryFn<ControlsProps> = (props) => {
);
};
export const Controls = Template.bind({});
export const Controls: StoryObj<ControlsProps> = {
render: Template,
Controls.args = {
showZoom: true,
showFitView: true,
showCenter: true,
args: {
showZoom: true,
showFitView: true,
showCenter: true,
},
};

View file

@ -21,7 +21,7 @@ import {
type Edge as xyEdge,
} from '@xyflow/react';
import { isEmpty, isEqual, pick, size, xorWith } from 'lodash';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { DefaultEdge } from '.';
import { GlobalStylesStorybookDecorator } from '../../../.storybook/decorators';
import { LabelNode } from '../node';
@ -180,14 +180,16 @@ const Template: StoryFn<EdgeViewModel> = (args: EdgeViewModel) => {
);
};
export const Edge = Template.bind({});
export const Edge: StoryObj<EdgeViewModel> = {
render: Template,
Edge.args = {
id: 'siem-windows',
label: 'User login to OKTA',
color: 'primary',
interactive: true,
type: 'solid',
args: {
id: 'siem-windows',
label: 'User login to OKTA',
color: 'primary',
interactive: true,
type: 'solid',
},
};
const isArrayOfObjectsEqual = (x: object[], y: object[]) =>

View file

@ -7,7 +7,7 @@
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { css, ThemeProvider } from '@emotion/react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { EuiListGroup, EuiHorizontalRule } from '@elastic/eui';
import type { NodeProps, NodeViewModel } from '..';
import { Graph } from '..';
@ -213,4 +213,6 @@ const Template: StoryFn = () => {
);
};
export const LargeGraphWithPopovers = Template.bind({});
export const LargeGraphWithPopovers: StoryObj = {
render: Template,
};

View file

@ -7,7 +7,7 @@
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { ThemeProvider, css } from '@emotion/react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { EuiListGroup, EuiHorizontalRule } from '@elastic/eui';
import type { EntityNodeViewModel, LabelNodeViewModel, NodeProps } from '..';
import { Graph } from '..';
@ -221,4 +221,6 @@ const Template: StoryFn = () => {
);
};
export const GraphPopovers = Template.bind({});
export const GraphPopovers: StoryObj = {
render: Template,
};

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import type { StoryFn, Meta } from '@storybook/react';
import type { StoryFn, Meta, StoryObj } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { GraphInvestigation, type GraphInvestigationProps } from './graph_investigation';
import {
@ -96,4 +96,6 @@ const Template: StoryFn<Partial<GraphInvestigationProps>> = (props) => {
return <GraphInvestigation {...defaultProps} {...props} />;
};
export const Investigation = Template.bind({});
export const Investigation: StoryObj<Partial<GraphInvestigationProps>> = {
render: Template,
};

View file

@ -7,7 +7,7 @@
import React from 'react';
import { ThemeProvider, css } from '@emotion/react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { Writable } from '@kbn/utility-types';
import { GlobalStylesStorybookDecorator } from '../../.storybook/decorators';
import type {
@ -178,151 +178,156 @@ const Template: StoryFn<GraphData> = ({ nodes, edges, interactive }: GraphData)
);
};
export const SimpleAPIMock = Template.bind({});
SimpleAPIMock.args = {
nodes: [
{
id: 'admin@example.com',
label: 'admin@example.com',
color: 'primary',
shape: 'ellipse',
icon: 'user',
},
{
id: 'projects/your-project-id/roles/customRole',
label: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'hexagon',
icon: 'questionInCircle',
},
{
id: 'a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)',
label: 'google.iam.admin.v1.CreateRole',
source: 'admin@example.com',
target: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'label',
},
],
edges: [
{
id: 'a(admin@example.com)-b(a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole))',
source: 'admin@example.com',
sourceShape: 'ellipse',
target:
'a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)',
targetShape: 'label',
color: 'primary',
},
{
id: 'a(a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole))-b(projects/your-project-id/roles/customRole)',
source:
'a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)',
sourceShape: 'label',
target: 'projects/your-project-id/roles/customRole',
targetShape: 'hexagon',
color: 'primary',
},
],
export const SimpleAPIMock: StoryObj<GraphData> = {
render: Template,
args: {
nodes: [
{
id: 'admin@example.com',
label: 'admin@example.com',
color: 'primary',
shape: 'ellipse',
icon: 'user',
},
{
id: 'projects/your-project-id/roles/customRole',
label: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'hexagon',
icon: 'questionInCircle',
},
{
id: 'a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)',
label: 'google.iam.admin.v1.CreateRole',
source: 'admin@example.com',
target: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'label',
},
],
edges: [
{
id: 'a(admin@example.com)-b(a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole))',
source: 'admin@example.com',
sourceShape: 'ellipse',
target:
'a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)',
targetShape: 'label',
color: 'primary',
},
{
id: 'a(a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole))-b(projects/your-project-id/roles/customRole)',
source:
'a(admin@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)',
sourceShape: 'label',
target: 'projects/your-project-id/roles/customRole',
targetShape: 'hexagon',
color: 'primary',
},
],
},
};
export const GroupWithWarningAPIMock = Template.bind({});
GroupWithWarningAPIMock.args = {
nodes: [
{
id: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
shape: 'group',
},
{
id: 'admin3@example.com',
label: 'admin3@example.com',
color: 'primary',
shape: 'ellipse',
icon: 'user',
},
{
id: 'projects/your-project-id/roles/customRole',
label: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'hexagon',
icon: 'questionInCircle',
},
{
id: 'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed)',
label: 'google.iam.admin.v1.CreateRole',
source: 'admin3@example.com',
target: 'projects/your-project-id/roles/customRole',
color: 'warning',
shape: 'label',
parentId: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
},
{
id: 'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success)',
label: 'google.iam.admin.v1.CreateRole',
source: 'admin3@example.com',
target: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'label',
parentId: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
},
],
edges: [
{
id: 'a(admin3@example.com)-b(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))',
source: 'admin3@example.com',
sourceShape: 'ellipse',
target: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
targetShape: 'group',
color: 'primary',
},
{
id: 'a(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))-b(projects/your-project-id/roles/customRole)',
source: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
sourceShape: 'group',
target: 'projects/your-project-id/roles/customRole',
targetShape: 'hexagon',
color: 'primary',
},
{
id: 'a(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))-b(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed))',
source: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
sourceShape: 'group',
target:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed)',
targetShape: 'label',
color: 'warning',
},
{
id: 'a(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed))-b(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))',
source:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed)',
sourceShape: 'label',
target: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
targetShape: 'group',
color: 'warning',
},
{
id: 'a(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))-b(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success))',
source: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
sourceShape: 'group',
target:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success)',
targetShape: 'label',
color: 'primary',
},
{
id: 'a(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success))-b(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))',
source:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success)',
sourceShape: 'label',
target: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
targetShape: 'group',
color: 'primary',
},
],
export const GroupWithWarningAPIMock: StoryObj<GraphData> = {
render: Template,
args: {
nodes: [
{
id: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
shape: 'group',
},
{
id: 'admin3@example.com',
label: 'admin3@example.com',
color: 'primary',
shape: 'ellipse',
icon: 'user',
},
{
id: 'projects/your-project-id/roles/customRole',
label: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'hexagon',
icon: 'questionInCircle',
},
{
id: 'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed)',
label: 'google.iam.admin.v1.CreateRole',
source: 'admin3@example.com',
target: 'projects/your-project-id/roles/customRole',
color: 'warning',
shape: 'label',
parentId: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
},
{
id: 'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success)',
label: 'google.iam.admin.v1.CreateRole',
source: 'admin3@example.com',
target: 'projects/your-project-id/roles/customRole',
color: 'primary',
shape: 'label',
parentId: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
},
],
edges: [
{
id: 'a(admin3@example.com)-b(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))',
source: 'admin3@example.com',
sourceShape: 'ellipse',
target: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
targetShape: 'group',
color: 'primary',
},
{
id: 'a(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))-b(projects/your-project-id/roles/customRole)',
source: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
sourceShape: 'group',
target: 'projects/your-project-id/roles/customRole',
targetShape: 'hexagon',
color: 'primary',
},
{
id: 'a(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))-b(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed))',
source: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
sourceShape: 'group',
target:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed)',
targetShape: 'label',
color: 'warning',
},
{
id: 'a(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed))-b(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))',
source:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(failed)',
sourceShape: 'label',
target: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
targetShape: 'group',
color: 'warning',
},
{
id: 'a(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))-b(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success))',
source: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
sourceShape: 'group',
target:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success)',
targetShape: 'label',
color: 'primary',
},
{
id: 'a(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success))-b(grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole)))',
source:
'a(admin3@example.com)-b(projects/your-project-id/roles/customRole)label(google.iam.admin.v1.CreateRole)outcome(success)',
sourceShape: 'label',
target: 'grp(a(admin3@example.com)-b(projects/your-project-id/roles/customRole))',
targetShape: 'group',
color: 'primary',
},
],
},
};
export const LargeGraph = Template.bind({});
const baseGraph: EnhancedNodeViewModel[] = [
{
id: 'siem-windows',
@ -446,89 +451,99 @@ const baseGraph: EnhancedNodeViewModel[] = [
},
];
LargeGraph.args = {
...extractEdges(baseGraph),
export const LargeGraph: StoryObj<GraphData> = {
render: Template,
args: {
...extractEdges(baseGraph),
},
};
export const GraphLabelOverlayCases = Template.bind({});
export const GraphLabelOverlayCases: StoryObj<GraphData> = {
render: Template,
GraphLabelOverlayCases.args = {
...extractEdges([
...baseGraph,
{
id: 'newnode',
label: 'New Node',
color: 'primary',
shape: 'ellipse',
icon: 'user',
},
{
id: 'a(newnode)-b(hackeruser)',
source: 'newnode',
target: 'hackeruser',
label: 'Overlay Label',
color: 'danger',
shape: 'label',
},
{
id: 'a(newnode)-b(s3)',
source: 'newnode',
target: 's3',
label: 'Overlay Label',
color: 'danger',
shape: 'label',
},
]),
args: {
...extractEdges([
...baseGraph,
{
id: 'newnode',
label: 'New Node',
color: 'primary',
shape: 'ellipse',
icon: 'user',
},
{
id: 'a(newnode)-b(hackeruser)',
source: 'newnode',
target: 'hackeruser',
label: 'Overlay Label',
color: 'danger',
shape: 'label',
},
{
id: 'a(newnode)-b(s3)',
source: 'newnode',
target: 's3',
label: 'Overlay Label',
color: 'danger',
shape: 'label',
},
]),
},
};
export const GraphStackedEdgeCases = Template.bind({});
export const GraphStackedEdgeCases: StoryObj<GraphData> = {
render: Template,
GraphStackedEdgeCases.args = {
...extractEdges([
...baseGraph,
{
id: 'a(oktauser)-b(hackeruser)',
source: 'oktauser',
target: 'hackeruser',
label: 'CreateUser2',
color: 'primary',
shape: 'label',
},
{
id: 'a(siem-windows)-b(user)',
source: 'siem-windows',
target: 'user',
label: 'User login to OKTA2',
color: 'danger',
shape: 'label',
},
]),
};
export const GraphLargeStackedEdgeCases = Template.bind({});
GraphLargeStackedEdgeCases.args = {
...extractEdges([
...baseGraph,
...Array(10)
.fill(0)
.map<EnhancedNodeViewModel>((_v, idx) => ({
args: {
...extractEdges([
...baseGraph,
{
id: 'a(oktauser)-b(hackeruser)',
source: 'oktauser',
target: 'hackeruser',
label: `CreateUser${idx}`,
label: 'CreateUser2',
color: 'primary',
shape: 'label',
})),
...Array(10)
.fill(0)
.map<EnhancedNodeViewModel>((_v, idx) => ({
},
{
id: 'a(siem-windows)-b(user)',
source: 'siem-windows',
target: 'user',
label: `User login to OKTA${idx}`,
label: 'User login to OKTA2',
color: 'danger',
shape: 'label',
})),
]),
},
]),
},
};
export const GraphLargeStackedEdgeCases: StoryObj<GraphData> = {
render: Template,
args: {
...extractEdges([
...baseGraph,
...Array(10)
.fill(0)
.map<EnhancedNodeViewModel>((_v, idx) => ({
id: 'a(oktauser)-b(hackeruser)',
source: 'oktauser',
target: 'hackeruser',
label: `CreateUser${idx}`,
color: 'primary',
shape: 'label',
})),
...Array(10)
.fill(0)
.map<EnhancedNodeViewModel>((_v, idx) => ({
id: 'a(siem-windows)-b(user)',
source: 'siem-windows',
target: 'user',
label: `User login to OKTA${idx}`,
color: 'danger',
shape: 'label',
})),
]),
},
};

View file

@ -9,7 +9,7 @@ import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { pick } from 'lodash';
import { ReactFlow, Controls, Background } from '@xyflow/react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { NodeViewModel } from '../types';
import { GlobalStylesStorybookDecorator } from '../../../.storybook/decorators';
import { HexagonNode, PentagonNode, EllipseNode, RectangleNode, DiamondNode, LabelNode } from '.';
@ -63,57 +63,67 @@ const Template: StoryFn<NodeViewModel> = (args: NodeViewModel) => (
</ThemeProvider>
);
export const ShortLabel = Template.bind({});
export const ShortLabel: StoryObj<NodeViewModel> = {
render: Template,
ShortLabel.args = {
id: 'siem-windows',
label: '',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
args: {
id: 'siem-windows',
label: '',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
},
};
export const ArnLabel = Template.bind({});
export const ArnLabel: StoryObj<NodeViewModel> = {
render: Template,
ArnLabel.args = {
id: 'siem-windows',
label: 'arn:aws:iam::1234567890:user/lorem-ipsumdol-sitamet-user-1234',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
args: {
id: 'siem-windows',
label: 'arn:aws:iam::1234567890:user/lorem-ipsumdol-sitamet-user-1234',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
},
};
export const DashedLabel = Template.bind({});
export const DashedLabel: StoryObj<NodeViewModel> = {
render: Template,
DashedLabel.args = {
id: 'siem-windows',
label: 'lore-ipsumdol-sitameta-consectetu-adipis342',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
args: {
id: 'siem-windows',
label: 'lore-ipsumdol-sitameta-consectetu-adipis342',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
},
};
export const NoSpacesLabel = Template.bind({});
export const NoSpacesLabel: StoryObj<NodeViewModel> = {
render: Template,
NoSpacesLabel.args = {
id: 'siem-windows',
label: 'LoremIpsumDolorSitAmetConsectetur123',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
args: {
id: 'siem-windows',
label: 'LoremIpsumDolorSitAmetConsectetur123',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
},
};
export const NoSpacesAllLoweredLabel = Template.bind({});
export const NoSpacesAllLoweredLabel: StoryObj<NodeViewModel> = {
render: Template,
NoSpacesAllLoweredLabel.args = {
id: 'siem-windows',
label: 'loremipsumdolorsitametconsectetur123',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
args: {
id: 'siem-windows',
label: 'loremipsumdolorsitametconsectetur123',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
},
};

View file

@ -9,7 +9,7 @@ import React from 'react';
import { ThemeProvider } from '@emotion/react';
import { pick } from 'lodash';
import { ReactFlow, Controls, Background } from '@xyflow/react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { NodeViewModel } from '../types';
import { GlobalStylesStorybookDecorator } from '../../../.storybook/decorators';
import { HexagonNode, PentagonNode, EllipseNode, RectangleNode, DiamondNode, LabelNode } from '.';
@ -63,13 +63,15 @@ const Template: StoryFn<NodeViewModel> = (args: NodeViewModel) => (
</ThemeProvider>
);
export const Node = Template.bind({});
export const Node: StoryObj<NodeViewModel> = {
render: Template,
Node.args = {
id: 'siem-windows',
label: '',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
args: {
id: 'siem-windows',
label: '',
color: 'primary',
shape: 'hexagon',
icon: 'okta',
interactive: true,
},
};

View file

@ -9,7 +9,7 @@
import React from 'react';
import { ThemeProvider } from '@emotion/react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import { GlobalStylesStorybookDecorator } from '../../../.storybook/decorators';
import { NodeShapeContainer } from './styles';
import { NodeExpandButton, type NodeExpandButtonProps } from './node_expand_button';
@ -37,4 +37,6 @@ const Template: StoryFn<NodeExpandButtonProps> = (args) => (
</ThemeProvider>
);
export const ExpandButton = Template.bind({});
export const ExpandButton: StoryObj<NodeExpandButtonProps> = {
render: Template,
};

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import type { StoryFn } from '@storybook/react';
import type { StoryFn, StoryObj } from '@storybook/react';
import type { DiffViewProps } from './diff_view';
import { DiffView } from './diff_view';
import { DiffMethod } from './mark_edits';
@ -51,10 +51,13 @@ const Template: StoryFn<DiffViewProps> = ({ oldSource, newSource, diffMethod, zi
);
};
export const Default = Template.bind({});
Default.args = {
oldSource:
'from logs-endpoint.alerts-*\n| where event.code in ("malicious_file", "memory_signature", "shellcode_thread") and rule.name is not null\n| keep host.id, rule.name, event.code\n| stats hosts = count_distinct(host.id) by rule.name, event.code\n| where hosts >= 3',
newSource:
'from logs-endpoint.alerts-*\n| where event.code in ("malicious_file", "memory_signature", "shellcode_thread")\n| stats hosts = count_distinct(host.id)\n| where hosts >= 3',
export const Default: StoryObj<DiffViewProps> = {
render: Template,
args: {
oldSource:
'from logs-endpoint.alerts-*\n| where event.code in ("malicious_file", "memory_signature", "shellcode_thread") and rule.name is not null\n| keep host.id, rule.name, event.code\n| stats hosts = count_distinct(host.id) by rule.name, event.code\n| where hosts >= 3',
newSource:
'from logs-endpoint.alerts-*\n| where event.code in ("malicious_file", "memory_signature", "shellcode_thread")\n| stats hosts = count_distinct(host.id)\n| where hosts >= 3',
},
};

View file

@ -10160,6 +10160,16 @@
dependencies:
"@storybook/global" "^5.0.0"
"@storybook/addon-jest@8.6.3":
version "8.6.3"
resolved "https://registry.yarnpkg.com/@storybook/addon-jest/-/addon-jest-8.6.3.tgz#8f764bb82c959107c2ffad72e51eb50533c0fe12"
integrity sha512-HrX9z4EtEg6fwevcneT3BfIdQjCayNxxoeSr3mctRpoipm7Exo2fJ5RX/K8ePSObY2IDmK/OJZFeujplQ7MkjA==
dependencies:
"@storybook/global" "^5.0.0"
tiny-invariant "^1.3.1"
ts-dedent "^2.0.0"
upath "^2.0.1"
"@storybook/addon-measure@8.6.3":
version "8.6.3"
resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-8.6.3.tgz#f7fd39d0c78bada393e91c8d1d415f3978f6e2d8"
@ -30592,6 +30602,11 @@ unzip-stream@^0.3.4:
binary "^0.3.0"
mkdirp "^0.5.1"
upath@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b"
integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==
update-browserslist-db@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5"