Skip to content

Commit

Permalink
feat: ✨ multi-theme and design tokens (#73)
Browse files Browse the repository at this point in the history
* refactor(tokens): ♻️ abstract theme into tokens
* feat(tokens): 💄 add warning, info and success variants to badge and toast
* feat(theme): 💄 add theme selector and three themes
* style(theme): 💄 setup multiple themes; light and dark
* refactor(tokens): ♻️ abstract out stroke and shadow into tokens
  • Loading branch information
lloydrichards authored Feb 12, 2024
1 parent 6d0079a commit f3b11ee
Show file tree
Hide file tree
Showing 18 changed files with 898 additions and 123 deletions.
12 changes: 10 additions & 2 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,18 @@ export default function RootLayout({
>
<body suppressHydrationWarning={true}>
<ThemeProvider
attribute="class"
defaultTheme="light"
enableSystem
disableTransitionOnChange
enableColorScheme
themes={[
"light-classic",
"dark-classic",
"light-professional",
"dark-professional",
"light-soft",
"light-acid",
"dark-midnight",
]}
>
<Layout>{children}</Layout>
<Analytics />
Expand Down
28 changes: 28 additions & 0 deletions src/components/atom/badge/badge.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ export const Destructive: Story = {
},
};

/**
* Use the `warning` badge to indicate caution or a warning that requires
* attention.
*/
export const Warning: Story = {
args: {
variant: "warning",
},
};

/**
* Use the `success` badge to indicate success or a positive change.
*/
export const Success: Story = {
args: {
variant: "success",
},
};

/**
* Use the `info` badge to indicate information or a neutral change.
*/
export const Info: Story = {
args: {
variant: "info",
},
};

/**
* Use the `outline` badge for overlaying without obscuring interface details,
* emphasizing clarity and subtlety..
Expand Down
5 changes: 5 additions & 0 deletions src/components/atom/badge/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ const badgeVariants = cva(
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
warning:
"border-transparent bg-warning text-warning-foreground hover:bg-warning/80",
success:
"border-transparent bg-success text-success-foreground hover:bg-success/80",
info: "border-transparent bg-info text-info-foreground hover:bg-info/80",
outline: "text-foreground",
},
},
Expand Down
8 changes: 4 additions & 4 deletions src/components/atom/placeholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { typefaceValue2 } from "../typeface";

const PlaceholderIcon = {
image: (
<TentTree className="h-full max-h-24 w-full max-w-24 p-1 text-destructive" />
<TentTree className="size-full max-h-24 max-w-24 p-1 text-destructive" />
),
icon: (
<Apple className="h-full max-h-24 w-full max-w-24 p-1 text-destructive" />
<Apple className="size-full max-h-24 max-w-24 p-1 text-destructive" />
),
text: (
<Text className="h-full max-h-24 w-full max-w-24 p-1 text-destructive" />
<Text className="size-full max-h-24 max-w-24 p-1 text-destructive" />
),
chart: (
<LineChart className="h-full max-h-24 w-full max-w-24 p-1 text-destructive" />
<LineChart className="size-full max-h-24 max-w-24 p-1 text-destructive" />
),
};
export const Placeholder = React.forwardRef<
Expand Down
51 changes: 40 additions & 11 deletions src/components/atom/toast/toast.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react";
import { Toast, ToastAction, ToastActionElement, ToastProps } from "./toast";
import { Toaster } from "./toaster";
import { useToast } from "../../../hooks/use-toast";
import { Button } from "../button/button";

/**
* A succinct message that is displayed temporarily.
Expand All @@ -13,9 +14,17 @@ const meta = {
tags: ["autodocs"],
argTypes: {},
parameters: {
layout: "centered",
layout: "fullscreen",
},
render: (args) => <ToastExample {...args} />,
decorators: [
(Story) => (
<div className="grid h-44 items-center justify-center">
<Story />
<Toaster />
</div>
),
],
} satisfies Meta<typeof Toast>;

export default meta;
Expand All @@ -34,16 +43,14 @@ type ToasterToast = ToastProps & {
const ToastExample = (args: Story["args"]) => {
const { toast } = useToast();
return (
<div>
<button
onClick={() => {
toast(args);
}}
>
Show Toast
</button>
<Toaster />
</div>
<Button
variant="outline"
onClick={() => {
toast(args);
}}
>
Show Toast
</Button>
);
};

Expand Down Expand Up @@ -88,3 +95,25 @@ export const Destructive: Story = {
action: <ToastAction altText="Try again">Try again</ToastAction>,
},
};

/**
* Use the `warning` variant to indicate a warning.
*/
export const Warning: Story = {
args: {
variant: "warning",
title: "Looks like you missed something!",
description: "Please fill out all required fields.",
},
};

/**
* Use the `success` variant to indicate a successful action.
*/
export const Success: Story = {
args: {
variant: "success",
title: "Success!",
description: "Your message has been sent.",
},
};
4 changes: 4 additions & 0 deletions src/components/atom/toast/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const toastVariants = cva(
default: "border bg-background text-foreground",
destructive:
"destructive group border-destructive bg-destructive text-destructive-foreground",
warning:
"warning group border-warning bg-warning text-warning-foreground",
success:
"success group border-success bg-success text-success-foreground",
},
},
defaultVariants: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/atom/dropdown-menu/dropdown-menu";

export function ModeToggle() {
export function ThemeToggle() {
const { setTheme } = useTheme();

return (
Expand All @@ -26,13 +27,26 @@ export function ModeToggle() {
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>
Light
Classic (Light)
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>
Dark
<DropdownMenuItem onClick={() => setTheme("dark-classic")}>
Classic (Dark)
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
System
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => setTheme("light-professional")}>
Professional
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark-professional")}>
Professional (Dark)
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("light-soft")}>
Soft
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("light-acid")}>
Acid
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark-midnight")}>
Midnight (Dark)
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
4 changes: 2 additions & 2 deletions src/components/template/layout/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { buttonVariants } from "@/components/atom/button/button";
import { ModeToggle } from "@/components/molecule/mode-toggle";
import { ThemeToggle } from "@/components/molecule/theme-toggle";
import {
NavigationMenu,
NavigationMenuContent,
Expand Down Expand Up @@ -95,7 +95,7 @@ const NavRoutes: FC<NavRouteProps> = ({ vertical }) => {
</div>
</NavigationMenuContent>
</NavigationMenuItem>
<ModeToggle />
<ThemeToggle />
</NavigationMenuList>
);
};
Expand Down
Loading

0 comments on commit f3b11ee

Please sign in to comment.