1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-13 14:53:33 +00:00

PM-14051-storybook-implementation (#12840)

* PM-14051 -initial storybook set up
-Initial stories and folder structure

* clean up typing on existing stories

* add icons file

* assign packages to autofill

* row stories

* row storiescd

* -change file nnames to avoid rendering in main storybook instance - fix folder structure to set prep for doc creation

* remove babel loader

* -fix folder structure -add new package json -edit main to correct ts-config path

* edit package name
This commit is contained in:
Daniel Riera
2025-01-15 14:13:03 -05:00
committed by GitHub
parent b0957cf1f6
commit 99937e5831
19 changed files with 637 additions and 3 deletions

View File

@@ -0,0 +1,67 @@
import { dirname, join } from "path";
import path from "path";
import type { StorybookConfig } from "@storybook/web-components-webpack5";
import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
import remarkGfm from "remark-gfm";
const getAbsolutePath = (value: string): string =>
dirname(require.resolve(join(value, "package.json")));
const config: StorybookConfig = {
stories: ["../lit-stories/**/*.lit-stories.@(js|jsx|ts|tsx)"],
addons: [
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@storybook/addon-a11y"),
getAbsolutePath("@storybook/addon-designs"),
getAbsolutePath("@storybook/addon-interactions"),
{
name: "@storybook/addon-docs",
options: {
mdxPluginOptions: {
mdxCompileOptions: {
remarkPlugins: [remarkGfm],
},
},
},
},
],
framework: {
name: getAbsolutePath("@storybook/web-components-webpack5"),
options: {
legacyRootApi: true,
},
},
core: {
disableTelemetry: true,
},
env: (existingConfig) => ({
...existingConfig,
FLAGS: JSON.stringify({}),
}),
webpackFinal: async (config) => {
if (config.resolve) {
config.resolve.plugins = [
new TsconfigPathsPlugin({
configFile: path.resolve(__dirname, "../../../../../tsconfig.json"),
}),
] as any;
}
if (config.module && config.module.rules) {
config.module.rules.push({
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve("ts-loader"),
},
],
});
}
return config;
},
docs: {},
};
export default config;

View File

@@ -0,0 +1,34 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { ActionButton } from "../../buttons/action-button";
type Args = {
buttonText: string;
disabled: boolean;
theme: Theme;
buttonAction: (e: Event) => void;
};
export default {
title: "Components/Buttons/Action Button",
argTypes: {
buttonText: { control: "text" },
disabled: { control: "boolean" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
buttonAction: { control: false },
},
args: {
buttonText: "Click Me",
disabled: false,
theme: ThemeTypes.Light,
buttonAction: () => alert("Clicked"),
},
} as Meta<Args>;
const Template = (args: Args) => ActionButton({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,34 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { BadgeButton } from "../../buttons/badge-button";
type Args = {
buttonAction: (e: Event) => void;
buttonText: string;
disabled?: boolean;
theme: Theme;
};
export default {
title: "Components/Buttons/Badge Button",
argTypes: {
buttonText: { control: "text" },
disabled: { control: "boolean" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
buttonAction: { control: false },
},
args: {
buttonText: "Click Me",
disabled: false,
theme: ThemeTypes.Light,
buttonAction: () => alert("Clicked"),
},
} as Meta<Args>;
const Template = (args: Args) => BadgeButton({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,29 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { CloseButton } from "../../buttons/close-button";
type Args = {
handleCloseNotification: (e: Event) => void;
theme: Theme;
};
export default {
title: "Components/Buttons/Close Button",
argTypes: {
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
handleCloseNotification: { control: false },
},
args: {
theme: ThemeTypes.Light,
handleCloseNotification: () => {
alert("Close button clicked!");
},
},
} as Meta<Args>;
const Template = (args: Args) => CloseButton({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,33 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { EditButton } from "../../buttons/edit-button";
type Args = {
buttonAction: (e: Event) => void;
buttonText: string;
disabled?: boolean;
theme: Theme;
};
export default {
title: "Components/Buttons/Edit Button",
argTypes: {
buttonText: { control: "text" },
disabled: { control: "boolean" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
buttonAction: { control: false },
},
args: {
buttonText: "Click Me",
disabled: false,
theme: ThemeTypes.Light,
buttonAction: () => alert("Clicked"),
},
} as Meta<Args>;
const Template = (args: Args) => EditButton({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,36 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { NotificationTypes } from "../../../../notification/abstractions/notification-bar";
import { CipherAction } from "../../cipher/cipher-action";
type Args = {
handleAction?: (e: Event) => void;
notificationType: typeof NotificationTypes.Change | typeof NotificationTypes.Add;
theme: Theme;
};
export default {
title: "Components/Ciphers/Cipher Action",
argTypes: {
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
notificationType: {
control: "select",
options: [NotificationTypes.Change, NotificationTypes.Add],
},
handleAction: { control: false },
},
args: {
theme: ThemeTypes.Light,
notificationType: NotificationTypes.Change,
handleAction: () => {
alert("Action triggered!");
},
},
} as Meta<Args>;
const Template = (args: Args) => CipherAction({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,40 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { html } from "lit";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { CipherIcon } from "../../cipher/cipher-icon";
type Args = {
color: string;
size: string;
theme: Theme;
uri?: string;
};
export default {
title: "Components/Ciphers/Cipher Icon",
argTypes: {
color: { control: "color" },
size: { control: "text" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
uri: { control: "text" },
},
args: {
size: "50px",
theme: ThemeTypes.Light,
uri: "",
},
} as Meta<Args>;
const Template = (args: Args) => {
return html`
<div style="width: ${args.size}; height: ${args.size}; overflow: hidden;">
${CipherIcon({ ...args })}
</div>
`;
};
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,33 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { html } from "lit";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { CipherInfoIndicatorIcons } from "../../cipher/cipher-indicator-icons";
type Args = {
isBusinessOrg?: boolean;
isFamilyOrg?: boolean;
theme: Theme;
};
export default {
title: "Components/Ciphers/Cipher Indicator Icon",
argTypes: {
isBusinessOrg: { control: "boolean" },
isFamilyOrg: { control: "boolean" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
},
args: {
theme: ThemeTypes.Light,
isBusinessOrg: true,
isFamilyOrg: false,
},
} as Meta<Args>;
const Template: StoryObj<Args>["render"] = (args) =>
html`<div>${CipherInfoIndicatorIcons({ ...args })}</div>`;
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,66 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { html } from "lit";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import * as Icons from "../../icons";
type Args = {
color?: string;
disabled?: boolean;
theme: Theme;
size: number;
iconLink: URL;
};
export default {
title: "Components/Icons/Icons",
argTypes: {
iconLink: { control: "text" },
color: { control: "color" },
disabled: { control: "boolean" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
size: { control: "number", min: 10, max: 100, step: 1 },
},
args: {
iconLink: new URL("https://bitwarden.com"),
disabled: false,
theme: ThemeTypes.Light,
size: 50,
},
} as Meta<Args>;
const Template = (args: Args, IconComponent: (props: Args) => ReturnType<typeof html>) => html`
<div
style="width: ${args.size}px; height: ${args.size}px; display: flex; align-items: center; justify-content: center;"
>
${IconComponent({ ...args })}
</div>
`;
const createIconStory = (iconName: keyof typeof Icons): StoryObj<Args> => {
const story = {
render: (args) => Template(args, Icons[iconName]),
} as StoryObj<Args>;
if (iconName !== "BrandIconContainer") {
story.argTypes = {
iconLink: { table: { disable: true } },
};
}
return story;
};
export const AngleDownIcon = createIconStory("AngleDown");
export const BusinessIcon = createIconStory("Business");
export const BrandIcon = createIconStory("BrandIconContainer");
export const CloseIcon = createIconStory("Close");
export const ExclamationTriangleIcon = createIconStory("ExclamationTriangle");
export const FamilyIcon = createIconStory("Family");
export const FolderIcon = createIconStory("Folder");
export const GlobeIcon = createIconStory("Globe");
export const PartyHornIcon = createIconStory("PartyHorn");
export const PencilSquareIcon = createIconStory("PencilSquare");
export const ShieldIcon = createIconStory("Shield");
export const UserIcon = createIconStory("User");

View File

@@ -0,0 +1,53 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
import { NotificationType } from "../../../../notification/abstractions/notification-bar";
import { CipherData } from "../../cipher/types";
import { NotificationBody } from "../../notification/body";
type Args = {
ciphers: CipherData[];
notificationType: NotificationType;
theme: Theme;
};
export default {
title: "Components/Notifications/Notification Body",
argTypes: {
ciphers: { control: "object" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
notificationType: {
control: "select",
options: ["add", "change", "unlock", "fileless-import"],
},
},
args: {
ciphers: [
{
id: "1",
name: "Example Cipher",
type: CipherType.Login,
favorite: false,
reprompt: CipherRepromptType.None,
icon: {
imageEnabled: true,
image: "",
fallbackImage: "https://example.com/fallback.png",
icon: "icon-class",
},
login: { username: "user@example.com", passkey: null },
},
],
theme: ThemeTypes.Light,
notificationType: "change",
},
} as Meta<Args>;
const Template = (args: Args) => NotificationBody({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,32 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { NotificationType } from "../../../../notification/abstractions/notification-bar";
import { NotificationFooter } from "../../notification/footer";
type Args = {
notificationType: NotificationType;
theme: Theme;
};
export default {
title: "Components/Notifications/Notification Footer",
argTypes: {
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
notificationType: {
control: "select",
options: ["add", "change", "unlock", "fileless-import"],
},
},
args: {
theme: ThemeTypes.Light,
notificationType: "add",
},
} as Meta<Args>;
const Template = (args: Args) => NotificationFooter({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,33 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { NotificationHeader } from "../../notification/header";
type Args = {
message: string;
standalone: boolean;
theme: Theme;
handleCloseNotification: (e: Event) => void;
};
export default {
title: "Components/Notifications/Notification Header",
argTypes: {
message: { control: "text" },
standalone: { control: "boolean" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
},
args: {
message: "This is a notification message",
standalone: true,
theme: ThemeTypes.Light,
handleCloseNotification: () => alert("Close Clicked"),
},
} as Meta<Args>;
const Template = (args: Args) => NotificationHeader({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,31 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { ActionRow } from "../../rows/action-row";
type Args = {
itemText: string;
handleAction: (e: Event) => void;
theme: Theme;
};
export default {
title: "Components/Rows/Action Row",
argTypes: {
itemText: { control: "text" },
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
handleAction: { control: false },
},
args: {
itemText: "Action Item",
theme: ThemeTypes.Light,
handleAction: () => alert("Action triggered"),
},
} as Meta<Args>;
const Template = (args: Args) => ActionRow({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,25 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { ButtonRow } from "../../rows/button-row";
type Args = {
theme: Theme;
};
export default {
title: "Components/Rows/Button Row",
argTypes: {
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
},
args: {
theme: ThemeTypes.Light,
},
} as Meta<Args>;
const Template = (args: Args) => ButtonRow({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,28 @@
import { Meta, StoryObj } from "@storybook/web-components";
import { TemplateResult } from "lit";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums/theme-type.enum";
import { ItemRow } from "../../rows/item-row";
type Args = {
theme: Theme;
children: TemplateResult | TemplateResult[];
};
export default {
title: "Components/Rows/Item Row",
argTypes: {
theme: { control: "select", options: [...Object.values(ThemeTypes)] },
children: { control: "object" },
},
args: {
theme: ThemeTypes.Light,
},
} as Meta<Args>;
const Template = (args: Args) => ItemRow({ ...args });
export const Default: StoryObj<Args> = {
render: Template,
};

View File

@@ -0,0 +1,7 @@
{
"name": "@bitwarden/lit-components",
"version": "2025.1.1",
"scripts": {
"storybook:lit": "storybook dev -p 6006 -c ./.lit-storybook"
}
}