diff --git a/src/components/MUI/DataDisplay/IconButton.tsx b/src/components/MUI/DataDisplay/IconButton.tsx new file mode 100644 index 0000000..52db5ef --- /dev/null +++ b/src/components/MUI/DataDisplay/IconButton.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiIconButton, { + IconButtonProps as MuiIconButtonProps, +} from "@mui/material/IconButton"; + +export type IconButtonProps = MuiIconButtonProps; + +export const IconButton = React.forwardRef( + (props, ref) => , +); + +IconButton.displayName = "IconButton"; diff --git a/src/components/MUI/DataDisplay/Typography.tsx b/src/components/MUI/DataDisplay/Typography.tsx new file mode 100644 index 0000000..581ab8e --- /dev/null +++ b/src/components/MUI/DataDisplay/Typography.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiTypography, { + TypographyProps as MuiTypographyProps, +} from "@mui/material/Typography"; + +export type TypographyProps = MuiTypographyProps; + +export const Typography = React.forwardRef( + (props, ref) => , +); + +Typography.displayName = "Typography"; diff --git a/src/components/MUI/Feedback/Alert.stories.tsx b/src/components/MUI/Feedback/Alert.stories.tsx new file mode 100644 index 0000000..122c931 --- /dev/null +++ b/src/components/MUI/Feedback/Alert.stories.tsx @@ -0,0 +1,84 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Alert } from "./Alert"; +import { Button } from "../Inputs/Button"; +import { Stack } from "../Layout/Stack"; + +const meta: Meta = { + title: "MUI/Feedback/Alert", + component: Alert, + tags: ["autodocs"], + argTypes: { + severity: { + control: "select", + options: ["success", "info", "warning", "error"], + }, + variant: { control: "select", options: ["standard", "outlined", "filled"] }, + children: { name: "message", control: "text" }, + icon: { control: false }, + action: { control: false }, + onClose: { control: false }, + }, + args: { + severity: "info", + variant: "standard", + children: "Alert message", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Variants: Story = { + render: (args) => ( + + + Standard + + + Outlined + + + Filled + + + ), +}; + +export const SeverityLevels: Story = { + render: (args) => ( + + + This is a success alert + + + This is an info alert + + + This is a warning alert + + + This is an error alert + + + ), +}; + +export const WithActionAndClose: Story = { + render: (args) => ( + <> + + UNDO + + } + onClose={() => console.log("alert close")} + > + Warning with action + + + ), +}; diff --git a/src/components/MUI/Feedback/Alert.tsx b/src/components/MUI/Feedback/Alert.tsx new file mode 100644 index 0000000..3760b7d --- /dev/null +++ b/src/components/MUI/Feedback/Alert.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiAlert, { AlertProps as MuiAlertProps } from "@mui/material/Alert"; + +export type AlertProps = MuiAlertProps; + +export const Alert = React.forwardRef( + (props, ref) => , +); + +Alert.displayName = "Alert"; diff --git a/src/components/MUI/Feedback/Backdrop.stories.tsx b/src/components/MUI/Feedback/Backdrop.stories.tsx new file mode 100644 index 0000000..9cee4d1 --- /dev/null +++ b/src/components/MUI/Feedback/Backdrop.stories.tsx @@ -0,0 +1,47 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Backdrop } from "./Backdrop"; +import { CircularProgress } from "./CircularProgress"; +import { Button } from "../Inputs/Button"; +import { Stack } from "../Layout/Stack"; + +const meta: Meta = { + title: "MUI/Feedback/Backdrop", + component: Backdrop, + tags: ["autodocs"], + argTypes: { + invisible: { control: "boolean" }, + }, + args: { invisible: false }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + return ( + + + + + + ); + }, +}; + +/** + * Click show to open backdrop and click again to close. + */ +export const ControlledBackdrop: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( + + + setOpen(false)}> + + + + ); + }, +}; diff --git a/src/components/MUI/Feedback/Backdrop.tsx b/src/components/MUI/Feedback/Backdrop.tsx new file mode 100644 index 0000000..3686d04 --- /dev/null +++ b/src/components/MUI/Feedback/Backdrop.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiBackdrop, { + BackdropProps as MuiBackdropProps, +} from "@mui/material/Backdrop"; + +export type BackdropProps = MuiBackdropProps; + +export const Backdrop = React.forwardRef( + (props, ref) => , +); + +Backdrop.displayName = "Backdrop"; diff --git a/src/components/MUI/Feedback/CircularProgress.stories.tsx b/src/components/MUI/Feedback/CircularProgress.stories.tsx new file mode 100644 index 0000000..dfe8665 --- /dev/null +++ b/src/components/MUI/Feedback/CircularProgress.stories.tsx @@ -0,0 +1,97 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { CircularProgress } from "./CircularProgress"; +import { Stack } from "../Layout/Stack"; +import { Typography } from "../DataDisplay/Typography"; + +const meta: Meta = { + title: "MUI/Feedback/CircularProgress", + component: CircularProgress, + tags: ["autodocs"], + argTypes: { + color: { + control: "select", + options: [ + "primary", + "secondary", + "success", + "error", + "info", + "warning", + "inherit", + ], + }, + variant: { control: "select", options: ["indeterminate", "determinate"] }, + value: { control: { type: "number", min: 0, max: 100, step: 1 } }, + size: { control: { type: "number", min: 8, max: 200, step: 2 } }, + thickness: { control: { type: "number", min: 1, max: 10, step: 0.5 } }, + }, + args: { + color: "primary", + variant: "indeterminate", + value: 75, + size: 40, + thickness: 3.6, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Determinate: Story = { + args: { variant: "determinate", value: 70 }, + render: (args) => , +}; + +export const DeterminateValues: Story = { + render: (args) => ( + + {[0, 25, 50, 75, 100].map((value) => ( + + + {value}% + + ))} + + ), +}; + +export const Sizes: Story = { + parameters: { + docs: { + description: { + story: "Circular Progress in different sizes.", + }, + }, + }, + render: (args) => ( + + {[16, 24, 40, 64, 80].map((size) => ( + + ))} + + ), +}; + +export const Thickness: Story = { + parameters: {}, + render: (args) => ( + + {[2, 3.6, 5, 7].map((thickness) => ( + + ))} + + ), +}; diff --git a/src/components/MUI/Feedback/CircularProgress.tsx b/src/components/MUI/Feedback/CircularProgress.tsx new file mode 100644 index 0000000..5a2aa25 --- /dev/null +++ b/src/components/MUI/Feedback/CircularProgress.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiCircularProgress, { + CircularProgressProps as MuiCircularProgressProps, +} from "@mui/material/CircularProgress"; + +export type CircularProgressProps = MuiCircularProgressProps; + +export const CircularProgress = React.forwardRef< + HTMLSpanElement, + CircularProgressProps +>((props, ref) => ); + +CircularProgress.displayName = "CircularProgress"; diff --git a/src/components/MUI/Feedback/Dialog.stories.tsx b/src/components/MUI/Feedback/Dialog.stories.tsx new file mode 100644 index 0000000..1dadb38 --- /dev/null +++ b/src/components/MUI/Feedback/Dialog.stories.tsx @@ -0,0 +1,79 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Dialog } from "./Dialog"; +import { Typography } from "../DataDisplay/Typography"; +import { Button } from "../Inputs/Button"; +import { DialogActions } from "./DialogActions"; +import { DialogContent } from "./DialogContent"; +import { DialogTitle } from "./DialogTitle"; + +const meta: Meta = { + title: "MUI/Feedback/Dialog", + component: Dialog, + tags: ["autodocs"], + argTypes: { + fullWidth: { control: "boolean" }, + maxWidth: { + control: "select", + options: ["xs", "sm", "md", "lg", "xl", false], + }, + fullScreen: { control: "boolean" }, + scroll: { control: "select", options: ["paper", "body"] }, + }, + args: { fullWidth: true, maxWidth: "sm", fullScreen: false, scroll: "paper" }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)}> + Title + + Content goes here. + + + + + + +
+ ); + }, +}; + +export const FullScreen: Story = { + args: { fullScreen: true }, + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)} + > + Full Screen + + Full-screen content. + + + + + +
+ ); + }, +}; diff --git a/src/components/MUI/Feedback/Dialog.tsx b/src/components/MUI/Feedback/Dialog.tsx new file mode 100644 index 0000000..88c2811 --- /dev/null +++ b/src/components/MUI/Feedback/Dialog.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiDialog, { DialogProps as MuiDialogProps } from "@mui/material/Dialog"; + +export type DialogProps = MuiDialogProps; + +export const Dialog = React.forwardRef( + (props, ref) => , +); + +Dialog.displayName = "Dialog"; diff --git a/src/components/MUI/Feedback/DialogActions.tsx b/src/components/MUI/Feedback/DialogActions.tsx new file mode 100644 index 0000000..c9acd5a --- /dev/null +++ b/src/components/MUI/Feedback/DialogActions.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiDialogActions, { + DialogActionsProps as MuiDialogActionsProps, +} from "@mui/material/DialogActions"; + +export type DialogActionsProps = MuiDialogActionsProps; + +export const DialogActions = React.forwardRef< + HTMLDivElement, + DialogActionsProps +>((props, ref) => ); + +DialogActions.displayName = "DialogActions"; diff --git a/src/components/MUI/Feedback/DialogContent.tsx b/src/components/MUI/Feedback/DialogContent.tsx new file mode 100644 index 0000000..c5b525a --- /dev/null +++ b/src/components/MUI/Feedback/DialogContent.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiDialogContent, { + DialogContentProps as MuiDialogContentProps, +} from "@mui/material/DialogContent"; + +export type DialogContentProps = MuiDialogContentProps; + +export const DialogContent = React.forwardRef< + HTMLDivElement, + DialogContentProps +>((props, ref) => ); + +DialogContent.displayName = "DialogContent"; diff --git a/src/components/MUI/Feedback/DialogTitle.tsx b/src/components/MUI/Feedback/DialogTitle.tsx new file mode 100644 index 0000000..debc000 --- /dev/null +++ b/src/components/MUI/Feedback/DialogTitle.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiDialogTitle, { + DialogTitleProps as MuiDialogTitleProps, +} from "@mui/material/DialogTitle"; + +export type DialogTitleProps = MuiDialogTitleProps; + +export const DialogTitle = React.forwardRef( + (props, ref) => , +); + +DialogTitle.displayName = "DialogTitle"; diff --git a/src/components/MUI/Feedback/LinearProgress.stories.tsx b/src/components/MUI/Feedback/LinearProgress.stories.tsx new file mode 100644 index 0000000..5b01f54 --- /dev/null +++ b/src/components/MUI/Feedback/LinearProgress.stories.tsx @@ -0,0 +1,100 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { LinearProgress } from "./LinearProgress"; +import { Stack } from "../Layout/Stack"; +import { Typography } from "../DataDisplay/Typography"; + +const meta: Meta = { + title: "MUI/Feedback/LinearProgress", + component: LinearProgress, + tags: ["autodocs"], + argTypes: { + color: { + control: "select", + options: [ + "primary", + "secondary", + "success", + "error", + "info", + "warning", + "inherit", + ], + }, + variant: { + control: "select", + options: ["indeterminate", "determinate", "buffer", "query"], + }, + value: { control: { type: "number", min: 0, max: 100, step: 1 } }, + valueBuffer: { control: { type: "number", min: 0, max: 100, step: 1 } }, + }, + args: { + color: "primary", + variant: "indeterminate", + value: 40, + valueBuffer: 60, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Determinate: Story = { + args: { variant: "determinate", value: 50 }, + render: (args) => , +}; + +export const Buffer: Story = { + args: { variant: "buffer", value: 30, valueBuffer: 60 }, + render: (args) => , +}; + +export const Query: Story = { + args: { variant: "query" }, + render: (args) => , +}; + +export const DeterminateValues: Story = { + parameters: { + docs: { + description: { + story: "Determinate linear progress with different values.", + }, + }, + }, + render: (args) => ( + + {[0, 25, 50, 75, 100].map((value) => ( + + ))} + + ), +}; + +export const WithLabelValues: Story = { + parameters: { + docs: { + description: { + story: "Linear progress with value labels.", + }, + }, + }, + render: (args) => ( + + {[0, 25, 50, 75, 100].map((value) => ( + + + {value}% + + ))} + + ), +}; diff --git a/src/components/MUI/Feedback/LinearProgress.tsx b/src/components/MUI/Feedback/LinearProgress.tsx new file mode 100644 index 0000000..d21d8df --- /dev/null +++ b/src/components/MUI/Feedback/LinearProgress.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiLinearProgress, { + LinearProgressProps as MuiLinearProgressProps, +} from "@mui/material/LinearProgress"; + +export type LinearProgressProps = MuiLinearProgressProps; + +export const LinearProgress = React.forwardRef< + HTMLDivElement, + LinearProgressProps +>((props, ref) => ); + +LinearProgress.displayName = "LinearProgress"; diff --git a/src/components/MUI/Feedback/Skeleton.stories.tsx b/src/components/MUI/Feedback/Skeleton.stories.tsx new file mode 100644 index 0000000..d58fd2c --- /dev/null +++ b/src/components/MUI/Feedback/Skeleton.stories.tsx @@ -0,0 +1,80 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Skeleton } from "./Skeleton"; +import { Stack } from "../Layout/Stack"; +import { Typography } from "../DataDisplay/Typography"; + +const meta: Meta = { + title: "MUI/Feedback/Skeleton", + component: Skeleton, + tags: ["autodocs"], + parameters: { + layout: "padded", + }, + argTypes: { + variant: { + control: "select", + options: ["text", "rectangular", "circular", "rounded"], + }, + animation: { + control: "select", + options: ["pulse", "wave", false], + }, + width: { + control: { type: "number", min: 16, max: 600, step: 4 }, + }, + height: { + control: { type: "number", min: 16, max: 400, step: 4 }, + }, + }, + args: { + variant: "rectangular", + animation: "pulse", + width: 240, + height: 180, + }, +}; + +export default meta; +type Story = StoryObj; + +/** + * Skeleton represents elements while content is loading. + * Multiple Skeletons can be composed to represent complex layouts. + */ +export const Basic: Story = { + render: (args) => , +}; + +export const Variants: Story = { + render: (_args) => ( + + Text + + Circular + + Rectangular + + Rounded + + + ), +}; + +export const Animations: Story = { + render: (args) => ( + + + Pulse + + + + Wave + + + + None + + + + ), +}; diff --git a/src/components/MUI/Feedback/Skeleton.tsx b/src/components/MUI/Feedback/Skeleton.tsx new file mode 100644 index 0000000..dd7b5ea --- /dev/null +++ b/src/components/MUI/Feedback/Skeleton.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiSkeleton, { + SkeletonProps as MuiSkeletonProps, +} from "@mui/material/Skeleton"; + +export type SkeletonProps = MuiSkeletonProps; + +export const Skeleton = React.forwardRef( + (props, ref) => , +); + +Skeleton.displayName = "Skeleton"; diff --git a/src/components/MUI/Feedback/Snackbar.stories.tsx b/src/components/MUI/Feedback/Snackbar.stories.tsx new file mode 100644 index 0000000..73e77ce --- /dev/null +++ b/src/components/MUI/Feedback/Snackbar.stories.tsx @@ -0,0 +1,47 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import React from "react"; +import { Snackbar } from "./Snackbar"; +import { Button } from "../Inputs/Button"; +import { Stack } from "../Layout/Stack"; + +const meta: Meta = { + title: "MUI/Feedback/Snackbar", + component: Snackbar, + tags: ["autodocs"], + argTypes: { + message: { + control: "text", + }, + autoHideDuration: { + control: { type: "number", min: 1000, max: 10000, step: 500 }, + }, + }, + args: { + message: "Saved", + autoHideDuration: 3000, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + + return ( + + + + setOpen(false)} + /> + + ); + }, +}; diff --git a/src/components/MUI/Feedback/Snackbar.tsx b/src/components/MUI/Feedback/Snackbar.tsx new file mode 100644 index 0000000..c72a864 --- /dev/null +++ b/src/components/MUI/Feedback/Snackbar.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiSnackbar, { + SnackbarProps as MuiSnackbarProps, +} from "@mui/material/Snackbar"; + +export type SnackbarProps = MuiSnackbarProps; + +export const Snackbar = React.forwardRef( + (props, ref) => , +); + +Snackbar.displayName = "Snackbar"; diff --git a/src/components/MUI/Inputs/Button.tsx b/src/components/MUI/Inputs/Button.tsx new file mode 100644 index 0000000..bd8d79c --- /dev/null +++ b/src/components/MUI/Inputs/Button.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; +import MuiButton, { ButtonProps as MuiButtonProps } from "@mui/material/Button"; + +export type ButtonProps = MuiButtonProps; + +export const Button = React.forwardRef( + ({ children, ...rest }, ref) => ( + + {children} + + ), +); + +Button.displayName = "Button"; diff --git a/src/components/MUI/Inputs/IconButton.tsx b/src/components/MUI/Inputs/IconButton.tsx new file mode 100644 index 0000000..52db5ef --- /dev/null +++ b/src/components/MUI/Inputs/IconButton.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiIconButton, { + IconButtonProps as MuiIconButtonProps, +} from "@mui/material/IconButton"; + +export type IconButtonProps = MuiIconButtonProps; + +export const IconButton = React.forwardRef( + (props, ref) => , +); + +IconButton.displayName = "IconButton"; diff --git a/src/components/MUI/Layout/Stack.tsx b/src/components/MUI/Layout/Stack.tsx new file mode 100644 index 0000000..2006df5 --- /dev/null +++ b/src/components/MUI/Layout/Stack.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiStack, { StackProps as MuiStackProps } from "@mui/material/Stack"; + +export type StackProps = MuiStackProps; + +export const Stack = React.forwardRef( + (props, ref) => , +); + +Stack.displayName = "Stack"; diff --git a/src/components/MUI/Layout/Toolbar.tsx b/src/components/MUI/Layout/Toolbar.tsx new file mode 100644 index 0000000..80b99a0 --- /dev/null +++ b/src/components/MUI/Layout/Toolbar.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiToolbar, { + ToolbarProps as MuiToolbarProps, +} from "@mui/material/Toolbar"; + +export type ToolbarProps = MuiToolbarProps; + +export const Toolbar = React.forwardRef( + (props, ref) => , +); + +Toolbar.displayName = "Toolbar"; diff --git a/src/components/MUI/Surfaces/Accordion.stories.tsx b/src/components/MUI/Surfaces/Accordion.stories.tsx new file mode 100644 index 0000000..ac342d7 --- /dev/null +++ b/src/components/MUI/Surfaces/Accordion.stories.tsx @@ -0,0 +1,95 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Accordion } from "./Accordion"; +import { AccordionDetails } from "./AccordionDetails"; +import { AccordionSummary } from "./AccordionSummary"; +import { ExpandMoreIcon } from "./Icons/ExpandMoreIcon"; +import { Stack } from "../Layout/Stack"; +import { Typography } from "../DataDisplay/Typography"; + +const meta: Meta = { + title: "MUI/Surfaces/Accordion", + component: Accordion, + tags: ["autodocs"], + argTypes: { + disabled: { control: "boolean" }, + disableGutters: { control: "boolean" }, + square: { control: "boolean" }, + defaultExpanded: { control: "boolean" }, + expanded: { control: false }, + onChange: { control: false }, + sx: { control: false }, + }, + args: { + disabled: false, + disableGutters: false, + square: false, + defaultExpanded: false, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + }> + Summary + + + Details + + + ), +}; + +export const Multiple: Story = { + render: (args) => ( + + + }> + Item 1 + + + Content 1 + + + + }> + Item 2 + + + Content 2 + + + + ), +}; + +export const Disabled: Story = { + args: { disabled: true }, + render: (args) => ( + + }> + Disabled + + + Cannot expand + + + ), +}; + +export const DefaultExpanded: Story = { + args: { defaultExpanded: true }, + render: (args) => ( + + }> + Expanded by default + + + Initial content is visible + + + ), +}; diff --git a/src/components/MUI/Surfaces/Accordion.tsx b/src/components/MUI/Surfaces/Accordion.tsx new file mode 100644 index 0000000..56649a6 --- /dev/null +++ b/src/components/MUI/Surfaces/Accordion.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiAccordion, { + AccordionProps as MuiAccordionProps, +} from "@mui/material/Accordion"; + +export type AccordionProps = MuiAccordionProps; + +export const Accordion = React.forwardRef( + (props, ref) => , +); + +Accordion.displayName = "Accordion"; diff --git a/src/components/MUI/Surfaces/AccordionDetails.tsx b/src/components/MUI/Surfaces/AccordionDetails.tsx new file mode 100644 index 0000000..15a9d2f --- /dev/null +++ b/src/components/MUI/Surfaces/AccordionDetails.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiAccordionDetails, { + AccordionDetailsProps as MuiAccordionDetailsProps, +} from "@mui/material/AccordionDetails"; + +export type AccordionDetailsProps = MuiAccordionDetailsProps; + +export const AccordionDetails = React.forwardRef< + HTMLDivElement, + AccordionDetailsProps +>((props, ref) => ); + +AccordionDetails.displayName = "AccordionDetails"; diff --git a/src/components/MUI/Surfaces/AccordionSummary.tsx b/src/components/MUI/Surfaces/AccordionSummary.tsx new file mode 100644 index 0000000..ae0a03a --- /dev/null +++ b/src/components/MUI/Surfaces/AccordionSummary.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiAccordionSummary, { + AccordionSummaryProps as MuiAccordionSummaryProps, +} from "@mui/material/AccordionSummary"; + +export type AccordionSummaryProps = MuiAccordionSummaryProps; + +export const AccordionSummary = React.forwardRef< + HTMLDivElement, + AccordionSummaryProps +>((props, ref) => ); + +AccordionSummary.displayName = "AccordionSummary"; diff --git a/src/components/MUI/Surfaces/AppBar.stories.tsx b/src/components/MUI/Surfaces/AppBar.stories.tsx new file mode 100644 index 0000000..3713156 --- /dev/null +++ b/src/components/MUI/Surfaces/AppBar.stories.tsx @@ -0,0 +1,54 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { AppBar } from "./AppBar"; +import { Toolbar } from "../Layout/Toolbar"; +import { Typography } from "../DataDisplay/Typography"; +import { IconButton } from "../Inputs/IconButton"; +import { Button } from "../Inputs/Button"; +import { MenuIcon } from "./Icons/MenuIcon"; + +const meta: Meta = { + title: "MUI/Surfaces/AppBar", + component: AppBar, + tags: ["autodocs"], + parameters: { + layout: "fullscreen", + }, + argTypes: { + position: { + control: "select", + options: ["fixed", "absolute", "sticky", "static", "relative"], + }, + color: { + control: "select", + options: ["default", "primary", "secondary", "inherit", "transparent"], + }, + elevation: { + control: { type: "number", min: 0, max: 24, step: 1 }, + }, + sx: { control: false }, + }, + args: { + position: "static", + color: "primary", + elevation: 4, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + + + Application title + + + + + ), +}; diff --git a/src/components/MUI/Surfaces/AppBar.tsx b/src/components/MUI/Surfaces/AppBar.tsx new file mode 100644 index 0000000..99b3971 --- /dev/null +++ b/src/components/MUI/Surfaces/AppBar.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiAppBar, { AppBarProps as MuiAppBarProps } from "@mui/material/AppBar"; + +export type AppBarProps = MuiAppBarProps; + +export const AppBar = React.forwardRef( + (props, ref) => , +); + +AppBar.displayName = "AppBar"; diff --git a/src/components/MUI/Surfaces/Card.stories.tsx b/src/components/MUI/Surfaces/Card.stories.tsx new file mode 100644 index 0000000..d0443dd --- /dev/null +++ b/src/components/MUI/Surfaces/Card.stories.tsx @@ -0,0 +1,74 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Card } from "./Card"; +import { Typography } from "../DataDisplay/Typography"; +import { Button } from "../Inputs/Button"; +import { CardContent } from "./CardContent"; +import { CardActions } from "./CardActions"; +import { CardMedia } from "./CardMedia"; +import Diamond from "../../../public/images/diamond.jpg"; + +const meta: Meta = { + title: "MUI/Surfaces/Card", + component: Card, + tags: ["autodocs"], + argTypes: { + variant: { + control: "select", + options: ["elevation", "outlined"], + }, + raised: { control: "boolean" }, + elevation: { + control: { type: "number", min: 0, max: 24, step: 1 }, + }, + sx: { control: false }, + }, + args: { + variant: "elevation", + raised: false, + elevation: 1, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + Diamond Light Source + + + Diamond Light Source is the UK’s national synchrotron serving + scientists and researchers from around the world. + + + + + + + + ), +}; + +export const Outlined: Story = { + args: { + variant: "outlined", + elevation: 0, + }, + render: (args) => ( + + + Outlined card + + Uses the outlined variant with zero elevation. + + + + + + + ), +}; diff --git a/src/components/MUI/Surfaces/Card.tsx b/src/components/MUI/Surfaces/Card.tsx new file mode 100644 index 0000000..ab1ee4a --- /dev/null +++ b/src/components/MUI/Surfaces/Card.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiCard, { CardProps as MuiCardProps } from "@mui/material/Card"; + +export type CardProps = MuiCardProps; + +export const Card = React.forwardRef( + (props, ref) => , +); + +Card.displayName = "Card"; diff --git a/src/components/MUI/Surfaces/CardActions.tsx b/src/components/MUI/Surfaces/CardActions.tsx new file mode 100644 index 0000000..c912226 --- /dev/null +++ b/src/components/MUI/Surfaces/CardActions.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiCardActions, { + CardActionsProps as MuiCardActionsProps, +} from "@mui/material/CardActions"; + +export type CardActionsProps = MuiCardActionsProps; + +export const CardActions = React.forwardRef( + (props, ref) => , +); + +CardActions.displayName = "CardActions"; diff --git a/src/components/MUI/Surfaces/CardContent.tsx b/src/components/MUI/Surfaces/CardContent.tsx new file mode 100644 index 0000000..88a61e9 --- /dev/null +++ b/src/components/MUI/Surfaces/CardContent.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiCardContent, { + CardContentProps as MuiCardContentProps, +} from "@mui/material/CardContent"; + +export type CardContentProps = MuiCardContentProps; + +export const CardContent = React.forwardRef( + (props, ref) => , +); + +CardContent.displayName = "CardContent"; diff --git a/src/components/MUI/Surfaces/CardMedia.tsx b/src/components/MUI/Surfaces/CardMedia.tsx new file mode 100644 index 0000000..89271cf --- /dev/null +++ b/src/components/MUI/Surfaces/CardMedia.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiCardMedia, { + CardMediaProps as MuiCardMediaProps, +} from "@mui/material/CardMedia"; + +export type CardMediaProps = MuiCardMediaProps; + +export const CardMedia = React.forwardRef( + (props, ref) => , +); + +CardMedia.displayName = "CardMedia"; diff --git a/src/components/MUI/Surfaces/Icons/ExpandMoreIcon.tsx b/src/components/MUI/Surfaces/Icons/ExpandMoreIcon.tsx new file mode 100644 index 0000000..9abb449 --- /dev/null +++ b/src/components/MUI/Surfaces/Icons/ExpandMoreIcon.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import type { SvgIconProps } from "@mui/material/SvgIcon"; + +export type ExpandMoreIconProps = SvgIconProps; + +export const ExpandMoreIcon = React.forwardRef< + SVGSVGElement, + ExpandMoreIconProps +>((props, ref) => ); + +ExpandMoreIcon.displayName = "ExpandMoreIcon"; diff --git a/src/components/MUI/Surfaces/Icons/MenuIcon.tsx b/src/components/MUI/Surfaces/Icons/MenuIcon.tsx new file mode 100644 index 0000000..f076f76 --- /dev/null +++ b/src/components/MUI/Surfaces/Icons/MenuIcon.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; +import MuiMenuIcon from "@mui/icons-material/Menu"; +import type { SvgIconProps } from "@mui/material/SvgIcon"; + +export type MenuIconProps = SvgIconProps; + +export const MenuIcon = React.forwardRef( + (props, ref) => , +); + +MenuIcon.displayName = "MenuIcon"; diff --git a/src/components/MUI/Surfaces/Paper.stories.tsx b/src/components/MUI/Surfaces/Paper.stories.tsx new file mode 100644 index 0000000..04a4dba --- /dev/null +++ b/src/components/MUI/Surfaces/Paper.stories.tsx @@ -0,0 +1,80 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Paper } from "./Paper"; +import { Typography } from "../DataDisplay/Typography"; +import { Stack } from "../Layout/Stack"; + +const meta: Meta = { + title: "MUI/Surfaces/Paper", + component: Paper, + tags: ["autodocs"], + argTypes: { + variant: { + control: "select", + options: ["elevation", "outlined"], + }, + elevation: { + control: { + type: "number", + min: 0, + max: 24, + step: 1, + }, + }, + square: { control: "boolean" }, + sx: { control: false }, + }, + args: { + variant: "elevation", + elevation: 1, + square: false, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + Paper content + + ), +}; + +export const Variants: Story = { + render: (_args) => ( + + + Elevation + + + Outlined + + + ), +}; + +export const Elevations: Story = { + render: (_args) => ( + + {[0, 3, 8, 16].map((level) => ( + + Elevation {level} + + ))} + + ), +}; + +export const Corners: Story = { + render: (_args) => ( + + + Rounded (default) + + + Square + + + ), +}; diff --git a/src/components/MUI/Surfaces/Paper.tsx b/src/components/MUI/Surfaces/Paper.tsx new file mode 100644 index 0000000..ce0e7a6 --- /dev/null +++ b/src/components/MUI/Surfaces/Paper.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiPaper, { PaperProps as MuiPaperProps } from "@mui/material/Paper"; + +export type PaperProps = MuiPaperProps; + +export const Paper = React.forwardRef( + (props, ref) => , +); + +Paper.displayName = "Paper";