button
Theme toggle button with animated moon and sun icons
Theme toggle button with animated moon and sun icons
Загрузка превью…
src/button/c-button-61.vue
<script setup lang="ts">
import { ref, computed } from "vue"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
const theme = ref<"light" | "dark">("light")
const label = computed(() => `Switch to ${theme.value === "dark" ? "light" : "dark"} mode`)
function toggle() {
theme.value = theme.value === "light" ? "dark" : "light"
}
</script>
<template>
<Button
variant="outline"
size="icon"
@click="toggle"
:aria-label="label"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
:class="cn('size-4 transition-all duration-300', theme === 'dark' ? 'scale-0 -rotate-90 opacity-0' : 'scale-100 rotate-0 opacity-100')"
class="lucide lucide-sun"
>
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2" />
<path d="M12 20v2" />
<path d="m4.93 4.93 1.41 1.41" />
<path d="m17.66 17.66 1.41 1.41" />
<path d="M2 12h2" />
<path d="M20 12h2" />
<path d="m6.34 17.66-1.41 1.41" />
<path d="m19.07 4.93-1.41 1.41" />
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
:class="cn('absolute size-4 transition-all duration-300', theme === 'dark' ? 'scale-100 rotate-0 opacity-100' : 'scale-0 rotate-90 opacity-0')"
class="lucide lucide-moon"
>
<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401" />
</svg>
<span class="sr-only">Toggle theme</span>
</Button>
</template>