feat: add multiple magic ui button components including AnimatedSubscribeButton, InteractiveHoverButton, PulsatingButton, RippleButton, ShimmerButton, and ShinyButton to Magicui
This commit is contained in:
parent
3fff508728
commit
35005ea725
98
src/components/magicui/animated-subscribe-button.tsx
Normal file
98
src/components/magicui/animated-subscribe-button.tsx
Normal file
@ -0,0 +1,98 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { HTMLMotionProps } from "motion/react";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
interface AnimatedSubscribeButtonProps
|
||||
extends Omit<HTMLMotionProps<"button">, "ref"> {
|
||||
subscribeStatus?: boolean;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const AnimatedSubscribeButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
AnimatedSubscribeButtonProps
|
||||
>(
|
||||
(
|
||||
{ subscribeStatus = false, onClick, className, children, ...props },
|
||||
ref,
|
||||
) => {
|
||||
const [isSubscribed, setIsSubscribed] = useState<boolean>(subscribeStatus);
|
||||
|
||||
if (
|
||||
React.Children.count(children) !== 2 ||
|
||||
!React.Children.toArray(children).every(
|
||||
(child) => React.isValidElement(child) && child.type === "span",
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
"AnimatedSubscribeButton expects two children, both of which must be <span> elements.",
|
||||
);
|
||||
}
|
||||
|
||||
const childrenArray = React.Children.toArray(children);
|
||||
const initialChild = childrenArray[0];
|
||||
const changeChild = childrenArray[1];
|
||||
|
||||
return (
|
||||
<AnimatePresence mode="wait">
|
||||
{isSubscribed ? (
|
||||
<motion.button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex h-10 w-fit items-center justify-center overflow-hidden rounded-lg bg-primary px-6 text-primary-foreground",
|
||||
className,
|
||||
)}
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
setIsSubscribed(false);
|
||||
onClick?.(e);
|
||||
}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
{...props}
|
||||
>
|
||||
<motion.span
|
||||
key="action"
|
||||
className="relative flex h-full w-full items-center justify-center font-semibold"
|
||||
initial={{ y: -50 }}
|
||||
animate={{ y: 0 }}
|
||||
>
|
||||
{changeChild} {/* Use children for subscribed state */}
|
||||
</motion.span>
|
||||
</motion.button>
|
||||
) : (
|
||||
<motion.button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex h-10 w-fit cursor-pointer items-center justify-center rounded-lg border-none bg-primary px-6 text-primary-foreground",
|
||||
className,
|
||||
)}
|
||||
onClick={(e) => {
|
||||
setIsSubscribed(true);
|
||||
onClick?.(e);
|
||||
}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
{...props}
|
||||
>
|
||||
<motion.span
|
||||
key="reaction"
|
||||
className="relative flex items-center justify-center font-semibold"
|
||||
initial={{ x: 0 }}
|
||||
exit={{ x: 50, transition: { duration: 0.1 } }}
|
||||
>
|
||||
{initialChild} {/* Use children for unsubscribed state */}
|
||||
</motion.span>
|
||||
</motion.button>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
AnimatedSubscribeButton.displayName = "AnimatedSubscribeButton";
|
35
src/components/magicui/interactive-hover-button.tsx
Normal file
35
src/components/magicui/interactive-hover-button.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React from "react";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface InteractiveHoverButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
||||
|
||||
export const InteractiveHoverButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
InteractiveHoverButtonProps
|
||||
>(({ children, className, ...props }, ref) => {
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"group relative w-auto cursor-pointer overflow-hidden rounded-full border bg-background p-2 px-6 text-center font-semibold",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-primary transition-all duration-300 group-hover:scale-[100.8]"></div>
|
||||
<span className="inline-block transition-all duration-300 group-hover:translate-x-12 group-hover:opacity-0">
|
||||
{children}
|
||||
</span>
|
||||
</div>
|
||||
<div className="absolute top-0 z-10 flex h-full w-full translate-x-12 items-center justify-center gap-2 text-primary-foreground opacity-0 transition-all duration-300 group-hover:-translate-x-5 group-hover:opacity-100">
|
||||
<span>{children}</span>
|
||||
<ArrowRight />
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
InteractiveHoverButton.displayName = "InteractiveHoverButton";
|
46
src/components/magicui/pulsating-button.tsx
Normal file
46
src/components/magicui/pulsating-button.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface PulsatingButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
pulseColor?: string;
|
||||
duration?: string;
|
||||
}
|
||||
|
||||
export const PulsatingButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
PulsatingButtonProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
pulseColor = "#808080",
|
||||
duration = "1.5s",
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer items-center justify-center rounded-lg bg-primary px-4 py-2 text-center text-primary-foreground",
|
||||
className,
|
||||
)}
|
||||
style={
|
||||
{
|
||||
"--pulse-color": pulseColor,
|
||||
"--duration": duration,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
>
|
||||
<div className="relative z-10">{children}</div>
|
||||
<div className="absolute left-1/2 top-1/2 size-full -translate-x-1/2 -translate-y-1/2 animate-pulse rounded-lg bg-inherit" />
|
||||
</button>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
PulsatingButton.displayName = "PulsatingButton";
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import React from "react";
|
||||
|
||||
interface RainbowButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
||||
@ -12,13 +12,13 @@ export const RainbowButton = React.forwardRef<
|
||||
<button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"group relative inline-flex h-11 animate-rainbow cursor-pointer items-center justify-center rounded-xl border-0 bg-[length:200%] px-8 py-2 font-medium text-primary-foreground transition-colors [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.08*1rem)_solid_transparent] focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
||||
"group relative inline-flex h-11 animate-rainbow cursor-pointer items-center justify-center rounded-xl border-0 bg-[length:200%] px-8 py-2 font-medium text-primary-foreground transition-colors [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.08*1rem)_solid_transparent] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
||||
// before styles
|
||||
"before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))] before:[filter:blur(calc(0.8*1rem))]",
|
||||
"before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] before:[filter:blur(calc(0.8*1rem))]",
|
||||
// light mode colors
|
||||
"bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]",
|
||||
"bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))]",
|
||||
// dark mode colors
|
||||
"dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]",
|
||||
"dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))]",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
91
src/components/magicui/ripple-button.tsx
Normal file
91
src/components/magicui/ripple-button.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import React, { MouseEvent, useEffect, useState } from "react";
|
||||
|
||||
interface RippleButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
rippleColor?: string;
|
||||
duration?: string;
|
||||
}
|
||||
|
||||
export const RippleButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
RippleButtonProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
rippleColor = "#ffffff",
|
||||
duration = "600ms",
|
||||
onClick,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [buttonRipples, setButtonRipples] = useState<
|
||||
Array<{ x: number; y: number; size: number; key: number }>
|
||||
>([]);
|
||||
|
||||
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
createRipple(event);
|
||||
onClick?.(event);
|
||||
};
|
||||
|
||||
const createRipple = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
const button = event.currentTarget;
|
||||
const rect = button.getBoundingClientRect();
|
||||
const size = Math.max(rect.width, rect.height);
|
||||
const x = event.clientX - rect.left - size / 2;
|
||||
const y = event.clientY - rect.top - size / 2;
|
||||
|
||||
const newRipple = { x, y, size, key: Date.now() };
|
||||
setButtonRipples((prevRipples) => [...prevRipples, newRipple]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (buttonRipples.length > 0) {
|
||||
const lastRipple = buttonRipples[buttonRipples.length - 1];
|
||||
const timeout = setTimeout(() => {
|
||||
setButtonRipples((prevRipples) =>
|
||||
prevRipples.filter((ripple) => ripple.key !== lastRipple.key),
|
||||
);
|
||||
}, parseInt(duration));
|
||||
return () => clearTimeout(timeout);
|
||||
}
|
||||
}, [buttonRipples, duration]);
|
||||
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
"relative flex cursor-pointer items-center justify-center overflow-hidden rounded-lg border-2 bg-background px-4 py-2 text-center text-primary",
|
||||
className,
|
||||
)}
|
||||
onClick={handleClick}
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<div className="relative z-10">{children}</div>
|
||||
<span className="pointer-events-none absolute inset-0">
|
||||
{buttonRipples.map((ripple) => (
|
||||
<span
|
||||
className="absolute animate-rippling rounded-full bg-background opacity-30"
|
||||
key={ripple.key}
|
||||
style={{
|
||||
width: `${ripple.size}px`,
|
||||
height: `${ripple.size}px`,
|
||||
top: `${ripple.y}px`,
|
||||
left: `${ripple.x}px`,
|
||||
backgroundColor: rippleColor,
|
||||
transform: `scale(0)`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
RippleButton.displayName = "RippleButton";
|
96
src/components/magicui/shimmer-button.tsx
Normal file
96
src/components/magicui/shimmer-button.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import React, { CSSProperties, ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface ShimmerButtonProps extends ComponentPropsWithoutRef<"button"> {
|
||||
shimmerColor?: string;
|
||||
shimmerSize?: string;
|
||||
borderRadius?: string;
|
||||
shimmerDuration?: string;
|
||||
background?: string;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ShimmerButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ShimmerButtonProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
shimmerColor = "#ffffff",
|
||||
shimmerSize = "0.05em",
|
||||
shimmerDuration = "3s",
|
||||
borderRadius = "100px",
|
||||
background = "rgba(0, 0, 0, 1)",
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
return (
|
||||
<button
|
||||
style={
|
||||
{
|
||||
"--spread": "90deg",
|
||||
"--shimmer-color": shimmerColor,
|
||||
"--radius": borderRadius,
|
||||
"--speed": shimmerDuration,
|
||||
"--cut": shimmerSize,
|
||||
"--bg": background,
|
||||
} as CSSProperties
|
||||
}
|
||||
className={cn(
|
||||
"group relative z-0 flex cursor-pointer items-center justify-center overflow-hidden whitespace-nowrap border border-white/10 px-6 py-3 text-white [background:var(--bg)] [border-radius:var(--radius)] dark:text-black",
|
||||
"transform-gpu transition-transform duration-300 ease-in-out active:translate-y-px",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
{/* spark container */}
|
||||
<div
|
||||
className={cn(
|
||||
"-z-30 blur-[2px]",
|
||||
"absolute inset-0 overflow-visible [container-type:size]",
|
||||
)}
|
||||
>
|
||||
{/* spark */}
|
||||
<div className="absolute inset-0 h-[100cqh] animate-shimmer-slide [aspect-ratio:1] [border-radius:0] [mask:none]">
|
||||
{/* spark before */}
|
||||
<div className="absolute -inset-full w-auto rotate-0 animate-spin-around [background:conic-gradient(from_calc(270deg-(var(--spread)*0.5)),transparent_0,var(--shimmer-color)_var(--spread),transparent_var(--spread))] [translate:0_0]" />
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
|
||||
{/* Highlight */}
|
||||
<div
|
||||
className={cn(
|
||||
"insert-0 absolute size-full",
|
||||
|
||||
"rounded-2xl px-4 py-1.5 text-sm font-medium shadow-[inset_0_-8px_10px_#ffffff1f]",
|
||||
|
||||
// transition
|
||||
"transform-gpu transition-all duration-300 ease-in-out",
|
||||
|
||||
// on hover
|
||||
"group-hover:shadow-[inset_0_-6px_10px_#ffffff3f]",
|
||||
|
||||
// on click
|
||||
"group-active:shadow-[inset_0_-10px_10px_#ffffff3f]",
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* backdrop */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute -z-20 [background:var(--bg)] [border-radius:var(--radius)] [inset:var(--cut)]",
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ShimmerButton.displayName = "ShimmerButton";
|
72
src/components/magicui/shiny-button.tsx
Normal file
72
src/components/magicui/shiny-button.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { motion, MotionProps, type AnimationProps } from "motion/react";
|
||||
import React from "react";
|
||||
|
||||
const animationProps = {
|
||||
initial: { "--x": "100%", scale: 0.8 },
|
||||
animate: { "--x": "-100%", scale: 1 },
|
||||
whileTap: { scale: 0.95 },
|
||||
transition: {
|
||||
repeat: Infinity,
|
||||
repeatType: "loop",
|
||||
repeatDelay: 1,
|
||||
type: "spring",
|
||||
stiffness: 20,
|
||||
damping: 15,
|
||||
mass: 2,
|
||||
scale: {
|
||||
type: "spring",
|
||||
stiffness: 200,
|
||||
damping: 5,
|
||||
mass: 0.5,
|
||||
},
|
||||
},
|
||||
} as AnimationProps;
|
||||
|
||||
interface ShinyButtonProps
|
||||
extends Omit<React.HTMLAttributes<HTMLElement>, keyof MotionProps>,
|
||||
MotionProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const ShinyButton = React.forwardRef<
|
||||
HTMLButtonElement,
|
||||
ShinyButtonProps
|
||||
>(({ children, className, ...props }, ref) => {
|
||||
return (
|
||||
<motion.button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative rounded-lg px-6 py-2 font-medium backdrop-blur-xl transition-shadow duration-300 ease-in-out hover:shadow dark:bg-[radial-gradient(circle_at_50%_0%,var(--primary)/10%_0%,transparent_60%)] dark:hover:shadow-[0_0_20px_var(--primary)/10%]",
|
||||
className,
|
||||
)}
|
||||
{...animationProps}
|
||||
{...props}
|
||||
>
|
||||
<span
|
||||
className="relative block size-full text-sm uppercase tracking-wide text-[rgb(0,0,0,65%)] dark:font-light dark:text-[rgb(255,255,255,90%)]"
|
||||
style={{
|
||||
maskImage:
|
||||
"linear-gradient(-75deg,var(--primary) calc(var(--x) + 20%),transparent calc(var(--x) + 30%),var(--primary) calc(var(--x) + 100%))",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
mask: "linear-gradient(rgb(0,0,0), rgb(0,0,0)) content-box exclude,linear-gradient(rgb(0,0,0), rgb(0,0,0))",
|
||||
WebkitMask:
|
||||
"linear-gradient(rgb(0,0,0), rgb(0,0,0)) content-box exclude,linear-gradient(rgb(0,0,0), rgb(0,0,0))",
|
||||
backgroundImage:
|
||||
"linear-gradient(-75deg,var(--primary)/10% calc(var(--x)+20%),var(--primary)/50% calc(var(--x)+25%),var(--primary)/10% calc(var(--x)+100%))",
|
||||
}}
|
||||
className="absolute inset-0 z-10 block rounded-[inherit] p-px"
|
||||
></span>
|
||||
</motion.button>
|
||||
);
|
||||
});
|
||||
|
||||
ShinyButton.displayName = "ShinyButton";
|
@ -69,6 +69,9 @@
|
||||
--animate-accordion-up: accordion-up 0.2s ease-out;
|
||||
--animate-marquee: marquee var(--duration) infinite linear;
|
||||
--animate-marquee-vertical: marquee-vertical var(--duration) linear infinite;
|
||||
--animate-ripple: ripple var(--duration, 2s) ease calc(var(--i, 0) * .2s)
|
||||
infinite;
|
||||
--animate-pulse: pulse var(--duration) ease-out infinite;
|
||||
|
||||
@keyframes shiny-text {
|
||||
0%,
|
||||
@ -76,7 +79,6 @@
|
||||
100% {
|
||||
background-position: calc(-100% - var(--shiny-width)) 0;
|
||||
}
|
||||
|
||||
30%,
|
||||
60% {
|
||||
background-position: calc(100% + var(--shiny-width)) 0;
|
||||
@ -87,7 +89,6 @@
|
||||
0% {
|
||||
background-position: 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 200%;
|
||||
}
|
||||
@ -97,7 +98,6 @@
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
@ -107,7 +107,6 @@
|
||||
from {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
|
||||
to {
|
||||
height: 0;
|
||||
}
|
||||
@ -131,13 +130,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
--animate-ripple: ripple var(--duration,2s) ease calc(var(--i, 0)*.2s) infinite
|
||||
;
|
||||
@keyframes ripple {
|
||||
0%, 100% {
|
||||
transform: translate(-50%, -50%) scale(1);}
|
||||
50% {
|
||||
transform: translate(-50%, -50%) scale(0.9);}}}
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: translate(-50%, -50%) scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 var(--pulse-color);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 8px var(--pulse-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
@ -290,4 +302,4 @@ body {
|
||||
--primary: var(--color-amber-500);
|
||||
--primary-foreground: var(--color-amber-50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user