Files
3x-ui/frontend/src/components/ui/notifications/EmailNotifications.stories.tsx
T
MHSanaei 7078abc14a feat(frontend): make Storybook a validated, fully covered component workbench
Storybook existed only as an undocumented local tool: 9 of 24 reusable components had stories, autodocs pages were bare prop tables, nothing built or tested the stories, and no contributor doc mentioned the workbench existed.

Every reusable component under src/components/ now has a co-located story with enriched autodocs (component descriptions plus per-prop argTypes, kept as string metadata since the repo bans line comments). Stories double as headless Chromium tests through the Storybook vitest addon, with axe accessibility checks enforced as errors and play-function interaction tests covering the modals, the RHF field bridge, the config block, and the select-all buttons. The preview now mirrors the panel's real theme DOM (body class, shared AntD theme config, seeded theme storage) so what stories render matches production.

CI and make verify gain a static Storybook build as a compile gate, and the frontend test job installs Chromium so story tests run on every PR. Contributor docs (frontend README, CONTRIBUTING, agent guides) document the workbench, the story conventions, and the Controls setup. Node engines move to 24 LTS and gen:api drops the type-stripping flags that Node 24 makes default.
2026-07-14 03:37:21 +02:00

86 lines
2.4 KiB
TypeScript

import { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { AllSetting } from '@/models/setting';
import { EmailNotifications } from './EmailNotifications';
const meta = {
title: 'UI/Notifications/EmailNotifications',
component: EmailNotifications,
tags: ['autodocs'],
parameters: {
layout: 'padded',
docs: {
description: {
component:
'Grid of grouped event checkboxes on the settings page that picks which panel events (outbound/node health, Xray crashes, CPU/RAM thresholds, login attempts) trigger an SMTP email, stored as a comma-separated list in smtpEnabledEvents.',
},
},
},
argTypes: {
allSetting: {
description:
'Panel settings snapshot; smtpEnabledEvents holds the selected event keys and smtpCpu/smtpMemory the alert threshold percentages.',
},
updateSetting: {
description: 'Receives a partial settings patch when an event is toggled or a threshold input changes.',
},
},
} satisfies Meta<typeof EmailNotifications>;
export default meta;
type Story = StoryObj<typeof meta>;
function StatefulDemo({ initial }: { initial: AllSetting }) {
const [settings, setSettings] = useState(initial);
return (
<EmailNotifications
allSetting={settings}
updateSetting={(patch) => setSettings((prev) => new AllSetting({ ...prev, ...patch }))}
/>
);
}
const placeholderArgs = {
allSetting: new AllSetting(),
updateSetting: () => undefined,
};
export const NothingSelected: Story = {
args: placeholderArgs,
render: () => <StatefulDemo initial={new AllSetting()} />,
};
export const SystemThresholdAlerts: Story = {
args: placeholderArgs,
render: () => (
<StatefulDemo
initial={new AllSetting({ smtpEnabledEvents: 'cpu.high,memory.high', smtpCpu: 85, smtpMemory: 90 })}
/>
),
};
export const InfrastructureOnly: Story = {
args: placeholderArgs,
render: () => (
<StatefulDemo initial={new AllSetting({ smtpEnabledEvents: 'outbound.down,node.down,node.up,xray.crash' })} />
),
};
export const AllEventsEnabled: Story = {
args: placeholderArgs,
render: () => (
<StatefulDemo
initial={
new AllSetting({
smtpEnabledEvents:
'outbound.down,outbound.up,xray.crash,node.down,node.up,cpu.high,memory.high,login.attempt',
smtpCpu: 80,
smtpMemory: 80,
})
}
/>
),
};