diff --git a/site/src/components/Loader/Loader.tsx b/site/src/components/Loader/Loader.tsx index 589cbd72b2331..0121b352eaeb1 100644 --- a/site/src/components/Loader/Loader.tsx +++ b/site/src/components/Loader/Loader.tsx @@ -1,5 +1,5 @@ import type { Interpolation, Theme } from "@emotion/react"; -import { Spinner } from "components/Spinner/Spinner"; +import { Spinner } from "components/deprecated/Spinner/Spinner"; import type { FC, HTMLAttributes } from "react"; interface LoaderProps extends HTMLAttributes { diff --git a/site/src/components/Spinner/Spinner.stories.tsx b/site/src/components/Spinner/Spinner.stories.tsx new file mode 100644 index 0000000000000..f1cd9e1b24ff2 --- /dev/null +++ b/site/src/components/Spinner/Spinner.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { PlusIcon } from "lucide-react"; +import { Spinner } from "./Spinner"; + +const meta: Meta = { + title: "components/Spinner", + component: Spinner, + args: { + children: , + }, +}; + +export default meta; +type Story = StoryObj; + +export const Idle: Story = {}; + +export const Loading: Story = { + args: { loading: true }, +}; diff --git a/site/src/components/Spinner/Spinner.tsx b/site/src/components/Spinner/Spinner.tsx index 5b20e2e54c5ef..8e331a1a6dd20 100644 --- a/site/src/components/Spinner/Spinner.tsx +++ b/site/src/components/Spinner/Spinner.tsx @@ -1,22 +1,77 @@ -import CircularProgress, { - type CircularProgressProps, -} from "@mui/material/CircularProgress"; -import isChromatic from "chromatic/isChromatic"; -import type { FC } from "react"; - /** - * Spinner component used to indicate loading states. This component abstracts - * the MUI CircularProgress to provide better control over its rendering, - * especially in snapshot tests with Chromatic. + * This component was inspired by + * https://www.radix-ui.com/themes/docs/components/spinner and developed using + * https://v0.dev/ help. */ -export const Spinner: FC = (props) => { - /** - * During Chromatic snapshots, we render the spinner as determinate to make it - * static without animations, using a deterministic value (75%). - */ - if (isChromatic()) { - props.variant = "determinate"; - props.value = 75; + +import isChromatic from "chromatic/isChromatic"; +import { type VariantProps, cva } from "class-variance-authority"; +import type { ReactNode } from "react"; +import { cn } from "utils/cn"; + +const leaves = 8; + +const spinnerVariants = cva("", { + variants: { + size: { + lg: "size-icon-lg", + sm: "size-icon-sm", + }, + }, + defaultVariants: { + size: "lg", + }, +}); + +type SpinnerProps = React.SVGProps & + VariantProps & { + children?: ReactNode; + loading?: boolean; + }; + +export function Spinner({ + className, + size, + loading, + children, + ...props +}: SpinnerProps) { + if (!loading) { + return children; } - return ; -}; + + return ( + + Loading spinner + {[...Array(leaves)].map((_, i) => { + const rotation = i * (360 / leaves); + + return ( + + ); + })} + + ); +} diff --git a/site/src/components/deprecated/Spinner/Spinner.tsx b/site/src/components/deprecated/Spinner/Spinner.tsx new file mode 100644 index 0000000000000..35fc7e9e177b0 --- /dev/null +++ b/site/src/components/deprecated/Spinner/Spinner.tsx @@ -0,0 +1,24 @@ +import CircularProgress, { + type CircularProgressProps, +} from "@mui/material/CircularProgress"; +import isChromatic from "chromatic/isChromatic"; +import type { FC } from "react"; + +/** + * Spinner component used to indicate loading states. This component abstracts + * the MUI CircularProgress to provide better control over its rendering, + * especially in snapshot tests with Chromatic. + * + * @deprecated prefer `components.Spinner` + */ +export const Spinner: FC = (props) => { + /** + * During Chromatic snapshots, we render the spinner as determinate to make it + * static without animations, using a deterministic value (75%). + */ + if (isChromatic()) { + props.variant = "determinate"; + props.value = 75; + } + return ; +}; diff --git a/site/tailwind.config.js b/site/tailwind.config.js index 389ffb22fe96a..884cbe88b2c9f 100644 --- a/site/tailwind.config.js +++ b/site/tailwind.config.js @@ -58,6 +58,15 @@ module.exports = { 5: "hsl(var(--chart-5))", }, }, + keyframes: { + loading: { + "0%": { opacity: 0.85 }, + "25%": { opacity: 0.7 }, + "50%": { opacity: 0.4 }, + "75%": { opacity: 0.3 }, + "100%": { opacity: 0.2 }, + }, + }, }, }, plugins: [require("tailwindcss-animate")],