Skip to content

Commit

Permalink
docs: enhance component documentation and storybook integration (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
pheobeayo authored Feb 1, 2025
1 parent 641c8e7 commit 7670446
Show file tree
Hide file tree
Showing 18 changed files with 290 additions and 47 deletions.
13 changes: 0 additions & 13 deletions apps/web/.env.example

This file was deleted.

8 changes: 7 additions & 1 deletion apps/web/src/stories/Alert.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import type { Meta, StoryObj } from "@storybook/react";
import type React from "react";
import { useState } from "react";

//This meta object defines metadata for the Alert component story,
// including its title, tags, and component settings.

const meta: Meta<typeof Alert> = {
title: "Components/Alert",
title: "Components/Alert", //Specifies the name and hierarchical path for the story given an example "Alert"
tags: ["autodocs"],
component: Alert,
parameters: {
controls: { expanded: true },
},
argTypes: {
//Defines controls for component props, enabling dynamic interaction in the Storybook UI.
type: {
control: { type: "select" },
options: ["success", "error", "info"],
Expand All @@ -22,6 +26,7 @@ export default meta;

type Story = StoryObj<typeof Alert>;

//This Template story demonstrates how the Alert component behaves with specific arguments (args). It includes a state (isVisible) to manage the visibility of the Alert
export const Template: Story = (
args: React.JSX.IntrinsicAttributes & {
message: string;
Expand All @@ -30,6 +35,7 @@ export const Template: Story = (
onDismiss: () => void;
},
) => {
//Example code
const [isVisible, setIsVisible] = useState(true);

if (!isVisible) return null;
Expand Down
19 changes: 17 additions & 2 deletions apps/web/src/stories/Badge.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//The Badge component is a versatile UI element designed to display small amounts of contextual information

import type { Meta, StoryFn } from "@storybook/react";
import React from "react";
import Badge from "../../../../packages/ui/src/badge";

export default {
title: "Components/Badge",
// This meta object configures the Storybook settings for the Badge component
title: "Components/Badge", //organises the components under the "Components" section here.
component: Badge,
tags: ["autodocs"],
tags: ["autodocs"], //automates documentation generation
argTypes: {
variant: {
control: "radio",
Expand All @@ -20,13 +23,15 @@ export default {

const Template: StoryFn<typeof Badge> = (args) => <Badge {...args} />;

//This is the default story that showcases the basic badge components
export const Default = Template.bind({});
Default.args = {
text: "Default Badge",
variant: "default",
size: "md",
};

//This showcases variant options of the Badge component.
export const Variants: StoryFn = () => (
<div style={{ display: "flex", gap: "1rem" }}>
<Badge variant="primary" text="Primary" />
Expand All @@ -36,10 +41,20 @@ export const Variants: StoryFn = () => (
</div>
);

//This demonstrates all the size options of the Badge component.
export const Sizes: StoryFn = () => (
<div style={{ display: "flex", gap: "1rem" }}>
<Badge variant="primary" text="Primary" size="sm" />
<Badge variant="accent" text="Primary" size="md" />
<Badge variant="secondary" text="Primary" size="lg" />
</div>
);

// Aria best practices with the Badge include using aria-live for a content to dynamically update as in below:
<Badge aria-live="polite" variant="primary" text="Success" />;

// for an interactive badge ; example
<Badge variant="accent" text="Clickable Badge" />;

//If the badge contains icons or dynamic data, ensure there is an accessible label using aria-label or visually hidden text.e.g
<Badge variant="success" text=" " aria-label="Success Badge" />;
23 changes: 21 additions & 2 deletions apps/web/src/stories/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//This is a reusable UI component for intereactive actions

import { ArrowRightIcon } from "@heroicons/react/24/solid";
import Button from "@repo/ui/button";
import type { Meta, StoryFn } from "@storybook/react";

export default {
title: "Components/Button",
tags: ["autodocs"],
//Meta configures the settings for the Button component
title: "Components/Button", //organizes components under the "Button component"
tags: ["autodocs"], //automates documentation generation
component: Button,
argTypes: {
variant: {
Expand Down Expand Up @@ -34,26 +37,30 @@ export default {

const Template: StoryFn<typeof Button> = (args) => <Button {...args} />;

//showcases a button in the disabled state
export const Disabled = Template.bind({});
Disabled.args = {
children: "Disabled",
disabled: true,
};

//showcases using a icon with a button text
export const WithIcon = Template.bind({});
WithIcon.args = {
children: "Icon",
variant: "primary",
icon: <ArrowRightIcon />,
};

//illustrates the variant options "primary" and "secondary"
export const Variants: StoryFn = () => (
<div style={{ display: "flex", gap: "1rem" }}>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
</div>
);

//showcases all size options for the button component
export const Sizes: StoryFn = () => (
<div style={{ display: "flex", gap: "1rem" }}>
<Button variant="primary" size="sm">
Expand All @@ -70,3 +77,15 @@ export const Sizes: StoryFn = () => (
</Button>
</div>
);

// Aria best practices with the Button include using aria-label or aria-labelledby attribute
// to provide accessible name without visible text such as
<Button aria-label="Submit Form" variant="primary" />;

// using in disabled button example:
<Button disabled aria-disabled="true" variant="secondary">
Disabled Button
</Button>;

//using accessible label with icon button example:
<Button icon={<ArrowRightIcon />} aria-label="Next Page" />;
17 changes: 15 additions & 2 deletions apps/web/src/stories/CarouselCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//This is a reusable card component designed for use in carousels or grids.
import type { Meta, StoryObj } from "@storybook/react";
import CarouselCard, {
type CardProps,
} from "../../../../packages/ui/src/carouselCard";

//This meta object configures the CarouselCard for Storybook.
const meta: Meta<typeof CarouselCard> = {
title: "Components/CarouselCard",
tags: ["autodocs"],
title: "Components/CarouselCard", //organizes components under the "CarouselCard component"
tags: ["autodocs"], //automates documentation generation
component: CarouselCard,
parameters: {
controls: { expanded: true },
Expand All @@ -30,6 +32,7 @@ export default meta;

type Story = StoryObj<typeof CarouselCard>;

// showcases a typical/default CarouselCard with all its properties
const defaultArgs: CardProps = {
tag: "Tech",
title: "Latest Innovations in Technology",
Expand All @@ -40,3 +43,13 @@ const defaultArgs: CardProps = {
export const Default: Story = {
args: { ...defaultArgs },
};

// Aria best accessibility practices with the CarouselCard include using aria-label or aria-labelledby attribute
// to link the card's title to its content for users; example :
<CarouselCard
tag="Cofiblock Store"
title="Latest Cofiblock Stores "
id="1"
image="https://via.placeholder.com/380x180?text=Card+Image"
aria-label="Latest Cofiblock Stores"
/>;
17 changes: 15 additions & 2 deletions apps/web/src/stories/ChatWithSeller.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//The ChatWithSeller component is a reusable UI element for initiating a chat with a seller
import { ChatWithSeller } from "@repo/ui/chatWithSeller";
import type { Meta, StoryFn } from "@storybook/react";
import React from "react";

//This meta object configures the ChatWithSeller for Storybook.
export default {
title: "Components/ChatWithSeller",
tags: ["autodocs"],
title: "Components/ChatWithSeller", //organizes components under the "ChatWithSeller component"
tags: ["autodocs"], //automates documentation generation
component: ChatWithSeller,
argTypes: {
name: {
Expand Down Expand Up @@ -35,10 +37,21 @@ const Template: StoryFn<typeof ChatWithSeller> = (args) => (
</div>
);

//This template showcases a default/typical ChatWithSeller setup.
export const Default = Template.bind({});
Default.args = {
name: "Jane Doe",
description: "Click to chat with the seller",
avatarSrc: "/images/user-profile/avatar.svg",
onClick: () => alert("Navigating to chat..."),
};

//This component is made accessible by ensuring that the seller's name and description are announced by screen readers
// using aria-labelledby and aria-describedby.Example as shown below
<ChatWithSeller
name="Jane Doe"
description="Click to chat with the seller"
avatarSrc="/images/user-profile/avatar.svg"
aria-labelledby="chat-with-seller-name"
aria-describedby="chat-with-seller-description"
/>;
23 changes: 21 additions & 2 deletions apps/web/src/stories/IconButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//This IconButton component is a button designed to display an icon with various sizes, styles, and states.
import { ArrowRightIcon, HomeIcon } from "@heroicons/react/24/solid";
import IconButton from "@repo/ui/iconButton";
import type { Meta, StoryFn } from "@storybook/react";

//This meta object configures the IconButton for Storybook
export default {
title: "Components/IconButton",
tags: ["autodocs"],
title: "Components/IconButton", //organizes components under the "IconButton component"
tags: ["autodocs"], //automates documentation generation
component: IconButton,
argTypes: {
variant: {
Expand Down Expand Up @@ -34,13 +36,15 @@ export default {

const Template: StoryFn<typeof IconButton> = (args) => <IconButton {...args} />;

//Shows the IconButton with a HomeIcon.
export const WithHomeIcon = Template.bind({});
WithHomeIcon.args = {
icon: <HomeIcon />,
variant: "secondary",
size: "lg",
};

//Shows the IconButton in a disabled state
export const Disabled = Template.bind({});
Disabled.args = {
icon: <ArrowRightIcon />,
Expand All @@ -49,6 +53,7 @@ Disabled.args = {
disabled: true,
};

//shows both primary and secondary variants of the IconButton
export const Variants: StoryFn = () => (
<div style={{ display: "flex", gap: "1rem" }}>
<IconButton variant="primary" size="md" icon={<ArrowRightIcon />}>
Expand All @@ -60,6 +65,7 @@ export const Variants: StoryFn = () => (
</div>
);

//Demonstrates all size options for the IconButton.
export const Sizes: StoryFn = () => (
<div style={{ display: "flex", gap: "1rem" }}>
<IconButton variant="primary" size="sm" icon={<ArrowRightIcon />}>
Expand All @@ -76,3 +82,16 @@ export const Sizes: StoryFn = () => (
</IconButton>
</div>
);

//To make the IconButton accessible, you can use [role="group"] explicitly for non-button elements styled as buttons.
// and [aria-disabled="true"] when the button is disabled to communicate its state to assistive technologies..
//example as seen below:

<IconButton
icon={<HomeIcon />}
variant="primary"
size="md"
aria-label="Navigate to home"
disabled={true}
aria-disabled="true"
/>;
26 changes: 23 additions & 3 deletions apps/web/src/stories/InfoCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
//The InfoCard component is a versatile UI element designed to display
// a title and a list of interactive options or child components.
import { InfoCard } from "@repo/ui/infoCard";
import type { Meta, StoryFn } from "@storybook/react";
import React from "react";

//This meta object configures the InfoCard for Storybook
export default {
title: "Components/InfoCard",
title: "Components/InfoCard", //organizes components under the "InfoCard component"
component: InfoCard,
tags: ["autodocs"],
tags: ["autodocs"], //automates documentation generation
argTypes: {
title: { control: "text", description: "The title of the InfoCard" },
options: {
control: false,
description: "Options displayed in the InfoCard",
},
children: { control: false, description: "Optional child components" },
children: { control: false, description: "Optional child components" }, //Optional child components, useful when no options are provided
},
} as Meta;

Expand Down Expand Up @@ -41,15 +44,32 @@ const Template: StoryFn = (args) => (
<InfoCard title={""} options={options} {...args} />
);

//shows an InfoCard with a title and multiple options.
export const Default = Template.bind({});
Default.args = {
title: "Default InfoCard",
options,
};

// shows the InfoCard without options, showing a fallback message using children.
export const NoOptions = Template.bind({});
NoOptions.args = {
title: "InfoCard with No Options",
options: [],
children: <p>No options available</p>,
};

//To make the InfoCard accessible, you can use [role="group"] for the InfoCard to indicate it groups related options
// and 'aria-labelledby' on the options container to associate it with the title.
// Use 'aria-pressed' for selectable options to indicate their current state.
<InfoCard
title="Accessible InfoCard"
options={[
{
label: "Option 1",
iconSrc: "/images/Avatar.png",
selected: false,
onClick: () => alert("Option 1 clicked"),
},
]}
/>;
Loading

0 comments on commit 7670446

Please sign in to comment.