Skip to content
Open
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
100 changes: 100 additions & 0 deletions src/components/MUI/DataDisplay/Avatar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Avatar } from "./Avatar";
import { AvatarGroup } from "./AvatarGroup";

import { Stack } from "../Layout/Stack";
import { AssignmentIcon } from "../Icons/AssignmentIcon";
import { PageviewIcon } from "../Icons/PageviewIcon";
import { FolderIcon } from "../Icons/FolderIcon";

const meta: Meta<typeof Avatar> = {
title: "MUI/Data Display/Avatar",
component: Avatar,
tags: ["autodocs"],
argTypes: {
variant: {
control: "select",
options: ["circular", "rounded", "square"],
},
children: { name: "initials", control: "text" },
alt: { control: "text" },
src: { control: "text" },
imgProps: { control: false },
sx: { control: "object" },
},
args: {
variant: "circular",
children: "AB",
alt: "User avatar",
src: "",
sx: { width: 56, height: 56, bgcolor: "primary.main" },
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Basic: Story = {
render: (args) => <Avatar {...args}>{args.children}</Avatar>,
};

export const Variants: Story = {
render: (_args) => (
<Stack direction="row" spacing={2}>
<Avatar variant="circular" sx={{ bgcolor: "error.main" }}>
AB
</Avatar>
<Avatar variant="rounded" sx={{ bgcolor: "warning.main" }}>
CD
</Avatar>
<Avatar variant="square" sx={{ bgcolor: "success.main" }}>
EF
</Avatar>
</Stack>
),
};

export const WithIcon: Story = {
render: (_args) => (
<Stack direction="row" spacing={2}>
<Avatar sx={{ bgcolor: "primary.main" }}>
<FolderIcon />
</Avatar>
<Avatar sx={{ bgcolor: "secondary.main" }}>
<PageviewIcon />
</Avatar>
<Avatar sx={{ bgcolor: "success.main" }}>
<AssignmentIcon />
</Avatar>
</Stack>
),
};

export const Grouped: Story = {
render: (_args) => (
<AvatarGroup max={4}>
<Avatar sx={{ bgcolor: "error.main" }}>AB</Avatar>
<Avatar sx={{ bgcolor: "warning.main" }}>CD</Avatar>
<Avatar sx={{ bgcolor: "success.main" }}>EF</Avatar>
<Avatar>IJ</Avatar>
<Avatar>KL</Avatar>
</AvatarGroup>
),
};

export const Sizes: Story = {
render: (_args) => {
return (
<Stack direction="row" spacing={2} alignItems="center">
{[40, 56, 80].map((size) => (
<Avatar
key={size}
sx={{ width: size, height: size, bgcolor: "primary.main" }}
>
{size}
</Avatar>
))}
</Stack>
);
},
};
14 changes: 14 additions & 0 deletions src/components/MUI/DataDisplay/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from "react";
import MuiAvatar, { AvatarProps as MuiAvatarProps } from "@mui/material/Avatar";

export type AvatarProps = MuiAvatarProps;

export const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
({ children, ...rest }, ref) => (
<MuiAvatar ref={ref} {...rest}>
{children}
</MuiAvatar>
),
);

Avatar.displayName = "Avatar";
16 changes: 16 additions & 0 deletions src/components/MUI/DataDisplay/AvatarGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from "react";
import MuiAvatarGroup, {
AvatarGroupProps as MuiAvatarGroupProps,
} from "@mui/material/AvatarGroup";

export type AvatarGroupProps = MuiAvatarGroupProps;

export const AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(
({ children, ...rest }, ref) => (
<MuiAvatarGroup ref={ref} {...rest}>
{children}
</MuiAvatarGroup>
),
);

AvatarGroup.displayName = "AvatarGroup";
95 changes: 95 additions & 0 deletions src/components/MUI/DataDisplay/Badge.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Badge } from "./Badge";
import { Stack } from "../Layout/Stack";
import { colourSet } from "../../../utils/diamond";
import { WorkIcon } from "../Icons/WorkIcon";
import { NotificationsIcon } from "../Icons/NotificationsIcon";
import { MailIcon } from "../Icons/MailIcon";

const childMap = {
mail: <MailIcon />,
notifications: <NotificationsIcon />,
work: <WorkIcon />,
} as const;

const meta: Meta<typeof Badge> = {
title: "MUI/Data Display/Badge",
component: Badge,
tags: ["autodocs"],
argTypes: {
color: {
control: "select",
options: colourSet,
},
variant: { control: "select", options: ["standard", "dot"] },
badgeContent: { control: "number" },
max: { control: "number" },
invisible: { control: "boolean" },
showZero: { control: "boolean" },
overlap: { control: "select", options: ["rectangular", "circular"] },
anchorOrigin: { control: false },
children: {
name: "child",
control: "select",
options: Object.keys(childMap),
mapping: childMap,
},
},
args: {
color: "primary",
variant: "standard",
badgeContent: 4,
max: 99,
invisible: false,
showZero: false,
overlap: "circular",
children: "mail",
},
};
export default meta;
type Story = StoryObj<typeof meta>;

export const Basic: Story = { render: (args) => <Badge {...args} /> };

export const Dot: Story = {
args: { variant: "dot", color: "secondary" },
render: (args) => <Badge {...args} />,
};

export const InvisibleNumber: Story = {
args: { variant: "dot", color: "secondary" },
render: (args) => <Badge {...args} invisible={true} />,
};

export const Colors: Story = {
args: { badgeContent: 7 },
render: (args) => (
<>
<Badge {...args} color="primary" />
<Badge {...args} color="secondary" />
<Badge {...args} color="error" />
<Badge {...args} color="success" />
<Badge {...args} color="info" />
<Badge {...args} color="warning" />
</>
),
};

export const DifferentChildren: Story = {
parameters: {
docs: {
description: {
story: "Badge with different child icons.",
},
},
},
render: (args) => (
<Stack direction="row" spacing={4}>
{Object.entries(childMap).map(([key, child]) => (
<Badge key={key} {...args} badgeContent={args.badgeContent}>
{child}
</Badge>
))}
</Stack>
),
};
10 changes: 10 additions & 0 deletions src/components/MUI/DataDisplay/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as React from "react";
import MuiBadge, { BadgeProps as MuiBadgeProps } from "@mui/material/Badge";

export type BadgeProps = MuiBadgeProps;

export const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
(props, ref) => <MuiBadge ref={ref} {...props} />,
);

Badge.displayName = "Badge";
146 changes: 146 additions & 0 deletions src/components/MUI/DataDisplay/Chip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";
import { Chip } from "./Chip";
import { Button } from "../Inputs/Button";
import { Stack } from "../Layout/Stack";
import { colourSet } from "../../../utils/diamond";
import { SaveIcon } from "../Icons/SaveIcon";
import { SendIcon } from "../Icons/SendIcon";
import { DeleteIcon } from "../Icons/DeleteIcon";
import { AddIcon } from "../Icons/AddIcon";

const iconMap = {
none: undefined,
save: <SaveIcon />,
send: <SendIcon />,
delete: <DeleteIcon />,
add: <AddIcon />,
} as const;

const meta: Meta<typeof Chip> = {
title: "MUI/Data Display/Chip",
component: Chip,
tags: ["autodocs"],
argTypes: {
label: { control: "text" },
variant: { control: "select", options: ["filled", "outlined"] },
color: {
control: "select",
options: colourSet,
},
size: { control: "select", options: ["small", "medium"] },
clickable: { control: "boolean" },
disabled: { control: "boolean" },
icon: {
control: "select",
options: Object.keys(iconMap),
mapping: iconMap,
},
deleteIcon: {
control: "select",
options: Object.keys(iconMap),
mapping: iconMap,
},
onDelete: { control: false },
sx: { control: false },
},
args: {
label: "Chip",
variant: "filled",
color: "primary",
size: "medium",
clickable: false,
disabled: false,
icon: undefined,
deleteIcon: undefined,
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Basic: Story = {
render: (args) => <Chip {...args} />,
};

export const Variants: Story = {
render: (args) => (
<Stack direction="row" spacing={1}>
<Chip {...args} variant="filled" label="Filled" />
<Chip {...args} variant="outlined" label="Outlined" />
</Stack>
),
};

export const Colours: Story = {
args: { variant: "filled" },
render: (args) => (
<Stack direction="row" spacing={1} flexWrap="wrap">
{colourSet.map((colour) => (
<Chip key={colour} {...args} color={colour} label={colour} />
))}
</Stack>
),
};

export const WithIcons: Story = {
render: (args) => (
<Stack direction="row" spacing={1}>
<Chip {...args} icon={iconMap.save} label="Save" />
<Chip {...args} icon={iconMap.add} label="Add" color="success" />
<Chip {...args} icon={iconMap.send} label="Send" color="info" />
<Chip {...args} icon={iconMap.delete} label="Remove" color="error" />
</Stack>
),
};

export const Deletable: Story = {
parameters: {
docs: {
description: {
story:
"Chips can be removed by the user. The Reset button restores the initial set.",
},
},
},
render: (args) => {
const initialChips = [
{ key: 1, label: "Item A" },
{ key: 2, label: "Item B" },
{ key: 3, label: "Item C" },
];

const [chips, setChips] = React.useState(initialChips);

const handleDelete = (key: number) => {
setChips((prev) => prev.filter((chip) => chip.key !== key));
};

const handleReset = () => {
setChips(initialChips);
};

return (
<Stack direction="row" spacing={2} alignItems="center">
{chips.map((chip) => (
<Chip
key={chip.key}
{...args}
label={chip.label}
deleteIcon={iconMap.delete}
onDelete={() => handleDelete(chip.key)}
/>
))}

<Button
size="small"
variant="contained"
onClick={handleReset}
disabled={chips.length === initialChips.length}
>
Reset
</Button>
</Stack>
);
},
};
10 changes: 10 additions & 0 deletions src/components/MUI/DataDisplay/Chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as React from "react";
import MuiChip, { ChipProps as MuiChipProps } from "@mui/material/Chip";

export type ChipProps = MuiChipProps;

export const Chip = React.forwardRef<HTMLDivElement, ChipProps>(
(props, ref) => <MuiChip ref={ref} {...props} />,
);

Chip.displayName = "Chip";
Loading
Loading