From 54f602c93870a7a6e8d714a3bde6095633cc3ac8 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Sat, 16 Aug 2025 22:49:21 +0530 Subject: [PATCH] Added new Theme Switcher and Color Switcher --- src/components/ColorSwitcher.astro | 227 ++++++++++++++++++++ src/components/ThemeSwitcher.astro | 322 +++++++++++++++++++++++++++++ src/layouts/Base.astro | 2 +- src/pages/buttons.astro | 12 +- src/pages/index.astro | 3 + src/pages/theme.astro | 24 +++ 6 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 src/components/ColorSwitcher.astro create mode 100644 src/components/ThemeSwitcher.astro create mode 100644 src/pages/theme.astro diff --git a/src/components/ColorSwitcher.astro b/src/components/ColorSwitcher.astro new file mode 100644 index 0000000..3c8c8fd --- /dev/null +++ b/src/components/ColorSwitcher.astro @@ -0,0 +1,227 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +interface Palette { key: string; label: string; } + +interface Props extends HTMLAttributes<"div"> { + storageKey?: string; + rootSelector?: string; // where to set data-color (e.g., "html" or ".wrnx") + ui?: "swatches" | "menu"; // grid or dropdown + showLabels?: boolean; // for swatch grid + compact?: boolean; // smaller dots + trigger?: "default" | "dot"; // dot = only a colored circle in trigger + palettes?: Palette[]; // keys/labels to display +} + +const { + storageKey = "wr-color", + rootSelector = "html", + ui = "menu", + showLabels = false, + compact = false, + trigger = "default", + class: className, + palettes = [ + { key: "ocean", label: "Ocean" }, + { key: "forest", label: "Forest" }, + { key: "sunset", label: "Sunset" }, + { key: "grape", label: "Grape" }, + { key: "slate", label: "Slate" }, + { key: "mint", label: "Mint" }, + { key: "amber", label: "Amber" }, + { key: "crimson", label: "Crimson" }, + { key: "indigo", label: "Indigo" }, + ], + ...rest +}: Props = Astro.props; + +const dot = compact ? "wr:h-3.5 wr:w-3.5" : "wr:h-4 wr:w-4"; +const btn = + "wr:inline-flex wr:items-center wr:gap-2 wr:rounded-xl wr:border wr:border-border wr:bg-background/80 wr:backdrop-blur-sm " + + "wr:text-foreground wr:h-10 wr:px-3 wr:text-sm wr:shadow-sm wr:transition wr:duration-200 wr:ease-out " + + "wr:hover:bg-muted/70 wr:focus-visible:outline-none wr:focus-visible:ring-2 wr:focus-visible:ring-primary/40 wr:focus-visible:ring-offset-2"; +const iconBtn = + "wr:inline-flex wr:items-center wr:justify-center wr:h-9 wr:w-9 wr:rounded-xl wr:border wr:border-border wr:bg-background/80 wr:backdrop-blur-sm " + + "wr:text-foreground wr:shadow-sm wr:transition wr:duration-200 wr:ease-out wr:hover:bg-muted/70 " + + "wr:focus-visible:outline-none wr:focus-visible:ring-2 wr:focus-visible:ring-primary/40 wr:focus-visible:ring-offset-2"; +const item = + "wr:flex wr:items-center wr:gap-3 wr:w-full wr:px-3 wr:py-2.5 wr:rounded-lg wr:text-sm wr:hover:bg-muted/70 wr:transition wr:duration-150"; +--- + +{ui === "swatches" ? ( +
+ {palettes.map(p => ( + + ))} +
+) : ( +
+ {trigger === "default" ? ( + + ) : ( + + )} + + +
+)} + + + diff --git a/src/components/ThemeSwitcher.astro b/src/components/ThemeSwitcher.astro new file mode 100644 index 0000000..e3152bd --- /dev/null +++ b/src/components/ThemeSwitcher.astro @@ -0,0 +1,322 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import { Icon } from "astro-icon/components"; + +interface Props extends HTMLAttributes<"div"> { + ui?: "icons" | "menu"; + storageKey?: string; + rootSelector?: string; + label?: string; + compact?: boolean; + darkBgClass?: string[]; + lightBgClass?: string[]; + rootExtraClass?: string; +} + +const { + ui = "menu", + storageKey = "wr-theme", + rootSelector = "html", + label = "", + compact = false, + darkBgClass = ["wr-theme-dark-soft"], + lightBgClass = ["wr-theme-light"], + rootExtraClass = "", + class: className, + ...rest +}: Props = Astro.props; + +const btn = + "wr:inline-flex wr:items-center wr:gap-2 wr:rounded-xl wr:border wr:border-border wr:bg-background/80 wr:backdrop-blur-sm " + + "wr:text-foreground wr:h-10 wr:px-3 wr:text-sm wr:shadow-sm wr:transition wr:duration-200 wr:ease-out " + + "wr:hover:bg-muted/70 wr:focus-visible:outline-none wr:focus-visible:ring-2 wr:focus-visible:ring-primary/40 wr:focus-visible:ring-offset-2"; + +const iconBtn = + "wr:inline-flex wr:items-center wr:justify-center wr:h-9 wr:w-9 wr:rounded-xl wr:border wr:border-border wr:bg-background/80 wr:backdrop-blur-sm " + + "wr:text-foreground wr:shadow-sm wr:transition wr:duration-200 wr:ease-out wr:hover:bg-muted/70 " + + "wr:focus-visible:outline-none wr:focus-visible:ring-2 wr:focus-visible:ring-primary/40 wr:focus-visible:ring-offset-2"; + +const item = + "wr:flex wr:items-center wr:gap-3 wr:w-full wr:px-3 wr:py-2.5 wr:rounded-lg wr:text-sm wr:hover:bg-muted/70 wr:transition wr:duration-150"; + +const icon = "wr:size-4"; +const checkBase = "wr:size-4 wr:opacity-0 wr:scale-90 wr:transition"; +--- + +
+ {label && {label}} + + { + ui === "icons" && ( +
+ + + +
+ ) + } + + { + ui === "menu" && ( +
+ + + +
+ ) + } +
+ + + + diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index fbf252f..211069c 100644 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -5,7 +5,7 @@ import { cn } from "../utils/cn"; const attributes = Astro.props; --- - + diff --git a/src/pages/buttons.astro b/src/pages/buttons.astro index 0f03911..4071aa4 100644 --- a/src/pages/buttons.astro +++ b/src/pages/buttons.astro @@ -1,14 +1,24 @@ --- import Base from "../layouts/Base.astro"; import Button from "../components/Button.astro"; +import ThemeSwitcher from "../components/ThemeSwitcher.astro"; +import ColorSwitcher from "../components/ColorSwitcher.astro"; --- + + +