Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions .storybook/storybookUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Story } from "@storybook/react";
import theme from "../src/theme/defaultTheme";

export const storyTemplate = <ComponentProps,>(
Component: React.FC,
Component: React.FC<ComponentProps>,
defaultArgs?: Partial<ComponentProps>,
) => (props: ComponentProps) => {
const base: Story<ComponentProps> = args => <Component {...args} />;
Expand All @@ -18,23 +18,31 @@ export const createUnionControl = (keys: any) => {
};
};

type CreateControlsOptions = { unions?: string[]; ignore?: string[] };
export const createControls = (
component: string,
options?: { unions: string[]; ignore: string[] },
options?: CreateControlsOptions,
) => {
const controls = options?.unions.reduce((cur, key) => {
return {
...cur,
[key]: createUnionControl((theme as Record<string, any>)[component][key]),
};
}, {});
try {
const controls = (options?.unions || []).reduce((cur, key) => {
const value = (theme as Record<string, any>)[component][key];

const ignoredControls = options?.ignore.reduce((cur, key) => {
return {
...cur,
[key]: { table: { disable: true } },
};
}, {});
if (!value) return cur;
return {
...cur,
[key]: createUnionControl(value),
};
}, {});

return { ...controls, ...ignoredControls };
const ignoredControls = (options?.ignore || []).reduce((cur, key) => {
return {
...cur,
[key]: { table: { disable: true } },
};
}, {});

return { ...controls, ...ignoredControls };
} catch (e) {
console.log(e);
}
};
85 changes: 45 additions & 40 deletions src/Tag/stories/Tag.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,67 @@
import React from "react";
import { Story, Meta } from "@storybook/react/types-6-0";
import { FaCopy } from "react-icons/fa";
import { Meta } from "@storybook/react/types-6-0";

import { Tag, TagGroup, TagProps } from "../index";
import { ClockIcon, PhotographIcon } from "../../icons";
import { ClockIcon } from "../../icons";
import { Avatar } from "../../avatar";
import {
createControls,
storyTemplate,
} from "../../../.storybook/storybookUtils";
import { TagGroupProps } from "../TagGroup";

export default {
title: "Tag",
component: Tag,
} as Meta;
argTypes: createControls("tag", { unions: ["size"], ignore: ["onClose"] }),
} as Meta<TagProps>;

const Component: Story<TagProps> = args => <Tag {...args}>Chennai</Tag>;
const base = storyTemplate<TagProps>(args => <Tag {...args}>Chennai</Tag>, {
closable: false,
size: "sm",
});

export const Default = Component.bind({});
Default.args = { size: "lg", onClose: () => alert(1) };
export const Default = base({ size: "lg", onClose: () => alert(1) });

export const GroupArrowNavigation = () => {
export const PrefixIcon = base({ prefix: <ClockIcon /> });

export const SuffixIcon = base({ closable: true, suffix: <FaCopy /> });

export const PrefixSuffixIcon = base({
closable: true,
prefix: <ClockIcon />,
suffix: <FaCopy />,
});

export const Closable = base({
closable: true,
onClose: () => alert("Removed"),
});

const group = storyTemplate<TagGroupProps>(args => {
return (
<TagGroup allowArrowNavigation className="flex items-center gap-1">
<TagGroup
{...args}
allowArrowNavigation
className="flex items-center gap-1"
>
<Tag closable>Tag 1</Tag>
<Tag closable>Tag 2</Tag>
<Tag closable>Tag 3</Tag>
</TagGroup>
);
};
});

export const GroupNoArrowNavigation = () => {
export const GroupArrowNavigation = group({});
export const GroupNoArrowNavigation = group({ allowArrowNavigation: false });

export const WithAvatar = () => {
return (
<TagGroup className="flex items-center gap-1">
<Tag closable>Tag 1</Tag>
<Tag closable>Tag 2</Tag>
<Tag closable>Tag 3</Tag>
</TagGroup>
<Tag closable>
<Avatar className="ring-0" src="https://bit.ly/dan-abramov" />
<span className="ml-2">Steve</span>
</Tag>
);
};

Expand All @@ -53,28 +83,3 @@ export const TagsExample = () => {
</TagGroup>
);
};

export const PrefixIcon = Default.bind({});
PrefixIcon.args = { prefix: <ClockIcon /> };

export const SuffixIcon = Default.bind({});
SuffixIcon.args = { closable: true, suffix: <PhotographIcon /> };

export const PrefixSuffixIcon = Default.bind({});
PrefixSuffixIcon.args = {
closable: true,
prefix: <ClockIcon />,
suffix: <PhotographIcon />,
};

export const Closable = Default.bind({});
Closable.args = { closable: true, onClose: () => alert("Removed") };

export const WithAvatar = () => {
return (
<Tag closable>
<Avatar className="ring-0" src="https://bit.ly/dan-abramov" />
<span className="ml-2">Steve</span>
</Tag>
);
};
12 changes: 8 additions & 4 deletions src/alert/stories/Alert.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ import { Box } from "../../box";
import { CloseIcon } from "../../icons";
import { AlertActionButton } from "../Alert";
import { Button, ButtonIcon } from "../../button";
import {
createControls,
storyTemplate,
} from "../../../.storybook/storybookUtils";

export default {
title: "Alert",
component: Alert,
argTypes: createControls("alert", { unions: ["status"] }),
} as Meta;

const Base: Story<AlertProps> = args => {
const base = storyTemplate<AlertProps>(args => {
const status = args?.status || "info";
const buttonBg = {
info: "bg-blue-200",
Expand Down Expand Up @@ -51,7 +56,6 @@ const Base: Story<AlertProps> = args => {
</Box>
</Alert>
);
};
});

export const Default = Base.bind({});
Default.args = { status: "info" };
export const Default = base({ status: "info" });
83 changes: 42 additions & 41 deletions src/avatar/stories/Avatar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import { AvatarBadge } from "../Avatar";
import { Avatar, AvatarProps } from "..";
import { AvatarGroup } from "../AvatarGroup";
import Status, { OfflineDot, OnlineDot } from "../../common/Status";
import {
createControls,
storyTemplate,
} from "../../../.storybook/storybookUtils";

export default {
title: "Avatar",
component: Avatar,
argTypes: createControls("avatar", { unions: ["size"] }),
} as Meta;

const TypingAnimation = () => (
Expand All @@ -22,41 +27,47 @@ const TypingAnimation = () => (
</div>
);

const Base: Story<AvatarProps> = args => (
<Avatar
src="https://bit.ly/dan-abramov"
name="Dan Abrahmov"
{...args}
></Avatar>
const base = storyTemplate<AvatarProps & { children?: React.ReactNode }>(
args => <Avatar {...args}>{args.children}</Avatar>,
{
size: "md",
},
);

export const Default = Base.bind({});
Default.args = { size: "xl" };

export const OnError: Story<AvatarProps> = () => (
<Avatar
src="https://bit.ly/dan-dabramov"
onError={e => {
alert("Error loading image");
console.log(e);
}}
/>
);
export const Default = base({});

export const WithIcon: Story<AvatarProps> = () => (
<Avatar className="text-white bg-red-400">
<ClockIcon />
</Avatar>
);
export const OnError = base({
src: "https://bit.ly/dan-dabramov",
onError: e => {
alert("Error loading image");
console.log(e);
},
});

export const WithIconAndBadge: Story<AvatarProps> = () => (
<Avatar size="xl">
<ClockIcon />
<AvatarBadge position="bottom-right">
<OfflineDot />
</AvatarBadge>
</Avatar>
);
export const WithIcon = base({
className: "text-white bg-red-400",
children: <ClockIcon />,
});

export const WithIconAndBadge = base({
size: "xl",
children: (
<>
<ClockIcon />
<AvatarBadge position="bottom-right">
<OfflineDot />
</AvatarBadge>
</>
),
});

export const NoNameAndSrc = base({});
export const NameButNoSrc = base({ name: "Anurag Hazra" });
export const NoNameAndSrcButFallback = base({ fallback: <ClockIcon /> });
export const NameAndFallback = base({
name: "Anurag Hazra",
fallback: <ClockIcon />,
});

export const WithBadge: Story<AvatarProps> = () => {
const [isTyping, setTyping] = React.useState(false);
Expand All @@ -83,16 +94,6 @@ export const WithBadge: Story<AvatarProps> = () => {
);
};

export const NoNameAndSrc: Story<AvatarProps> = () => <Avatar />;
export const NameButNoSrc: Story<AvatarProps> = () => (
<Avatar name="Anurag Hazra" />
);
export const NoNameAndSrcButFallback: Story<AvatarProps> = () => (
<Avatar fallback={<ClockIcon />} />
);
export const NameAndFallback: Story<AvatarProps> = () => (
<Avatar name="Anurag Hazra" fallback={<ClockIcon />} />
);
export const Statuses: Story<AvatarProps> = () => (
<AvatarGroup size="xl">
<Avatar size="xl" src="https://bit.ly/dan-abramov" name="Anurag Hazra">
Expand Down
4 changes: 2 additions & 2 deletions src/badge/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type BadgeProps = BoxProps & {
*
* @default "primary"
*/
variant?: keyof Renderlesskit.GetThemeValue<"badge", "variants">;
variant?: keyof Renderlesskit.GetThemeValue<"badge", "variant">;
/**
* How large should the button be?
*
Expand All @@ -34,7 +34,7 @@ export const Badge = forwardRefWithAs<BadgeProps, HTMLButtonElement, "span">(
const badgeStyles = cx(
theme.badge.base,
theme.badge.size[size],
theme.badge.variants[variant],
theme.badge.variant[variant],
className,
);

Expand Down
43 changes: 24 additions & 19 deletions src/badge/stories/Badge.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
import React from "react";
import { Story, Meta } from "@storybook/react/types-6-0";
import { Meta } from "@storybook/react/types-6-0";

import { Badge, BadgeProps } from "../Badge";
import {
createControls,
storyTemplate,
} from "../../../.storybook/storybookUtils";

export default {
title: "Badge",
component: Badge,
argTypes: {},
argTypes: createControls("badge", {
unions: ["size", "variant"],
}),
} as Meta;

const Template: Story<BadgeProps> = args => <Badge {...args}>badge</Badge>;
const base = storyTemplate<BadgeProps>(
args => {
return <Badge {...args}>badge</Badge>;
},
{ variant: "primary" },
);

export const Primary = Template.bind({});
Primary.args = {
export const Primary = base({
size: "sm",
variant: "primary",
};
});

export const XSmall = Template.bind({});
XSmall.args = {
export const XSmall = base({
size: "xs",
};
});

export const Small = Template.bind({});
Small.args = {
export const Small = base({
size: "sm",
};
});

export const Medium = Template.bind({});
Medium.args = {
export const Medium = base({
size: "md",
};
});

export const Large = Template.bind({});
Large.args = {
export const Large = base({
size: "lg",
};
});
Loading