"use client";
import React from "react";
import { motion } from "framer-motion";
import { cn } from "@/lib/utils";
import { Loader2 } from "lucide-react";
interface EnhancedButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "outline" | "ghost";
size?: "sm" | "md" | "lg";
isLoading?: boolean;
loadingText?: string;
icon?: React.ReactNode;
iconPosition?: "left" | "right";
children: React.ReactNode;
}
const buttonVariants = {
primary: "bg-primary text-primary-foreground hover:bg-primary/90 focus:ring-primary/50",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90 focus:ring-secondary/50",
outline: "border border-border bg-background hover:bg-muted focus:ring-border",
ghost: "hover:bg-muted hover:text-foreground focus:ring-muted",
};
const sizeVariants = {
sm: "h-8 px-3 text-xs",
md: "h-10 px-4 text-sm",
lg: "h-12 px-6 text-base",
};
export default function EnhancedButton({
className,
variant = "primary",
size = "md",
isLoading = false,
loadingText,
icon,
iconPosition = "left",
children,
disabled,
...props
}: EnhancedButtonProps) {
const isDisabled = disabled || isLoading;
return (
<motion.button
whileHover={!isDisabled ? { scale: 1.02, y: -1 } : {}}
whileTap={!isDisabled ? { scale: 0.98 } : {}}
transition={{ duration: 0.2 }}
className={cn(
// Base styles
"relative inline-flex items-center justify-center rounded-lg font-medium transition-all duration-200",
"focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background",
"disabled:opacity-50 disabled:cursor-not-allowed",
// Enhanced shadow and depth
"shadow-sm hover:shadow-md active:shadow-sm",
// Variant styles
buttonVariants[variant],
// Size styles
sizeVariants[size],
className
)}
disabled={isDisabled}
{...props}
>
{/* Loading overlay */}
{isLoading && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="absolute inset-0 flex items-center justify-center bg-current/10 rounded-lg"
>
<Loader2 className="w-4 h-4 animate-spin" />
</motion.div>
)}
{/* Content */}
<motion.div
animate={{ opacity: isLoading ? 0 : 1 }}
transition={{ duration: 0.2 }}
className="flex items-center gap-2"
>
{icon && iconPosition === "left" && (
<motion.span
whileHover={{ x: variant === "outline" ? 2 : 0 }}
transition={{ duration: 0.2 }}
>
{icon}
</motion.span>
)}
<span>{isLoading && loadingText ? loadingText : children}</span>
{icon && iconPosition === "right" && (
<motion.span
whileHover={{ x: 2 }}
transition={{ duration: 0.2 }}
>
{icon}
</motion.span>
)}
</motion.div>
</motion.button>
);
}Enhanced Button Basic
By Prism UI
Try the interaction, copy the React source files, or download the complete example.
About Enhanced Button Basic
Enhanced Button Basic is an animated React and Tailwind CSS button by Prism UI. Try the interaction, copy the React source, or download the example with creator credit.
- Effects and categories
- Hover effects, Animated
- Using this example
- Copy a TSX file or download the original source and standalone demo. Test keyboard focus, motion and contrast in your own project.
Usage, Tailwind and licensing questions
Read the source files
registry/example/enhanced-button-basic.tsx
"use client";
import { useState } from "react";
import EnhancedButton from "@/components/prismui/enhanced-button";
export default function EnhancedButtonBasic() {
const [isLoading, setIsLoading] = useState(false);
function handleClick() {
setIsLoading(true);
setTimeout(() => setIsLoading(false), 2000);
}
return (
<div className="flex min-h-[200px] w-full items-center justify-center">
<EnhancedButton
onClick={handleClick}
isLoading={isLoading}
loadingText="Processing..."
>
Click Me
</EnhancedButton>
</div>
);
}
export const demoSource = `"use client";
import { useState } from "react";
import EnhancedButton from "@/components/prismui/enhanced-button";
export default function EnhancedButtonBasic() {
const [isLoading, setIsLoading] = useState(false);
function handleClick() {
setIsLoading(true);
setTimeout(() => setIsLoading(false), 2000);
}
return (
<div className="flex min-h-[200px] w-full items-center justify-center">
<EnhancedButton
onClick={handleClick}
isLoading={isLoading}
loadingText="Processing..."
>
Click Me
</EnhancedButton>
</div>
);
}`;components/prismui/enhanced-button.tsx
"use client";
import React from "react";
import { motion } from "framer-motion";
import { cn } from "@/lib/utils";
import { Loader2 } from "lucide-react";
interface EnhancedButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "outline" | "ghost";
size?: "sm" | "md" | "lg";
isLoading?: boolean;
loadingText?: string;
icon?: React.ReactNode;
iconPosition?: "left" | "right";
children: React.ReactNode;
}
const buttonVariants = {
primary: "bg-primary text-primary-foreground hover:bg-primary/90 focus:ring-primary/50",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90 focus:ring-secondary/50",
outline: "border border-border bg-background hover:bg-muted focus:ring-border",
ghost: "hover:bg-muted hover:text-foreground focus:ring-muted",
};
const sizeVariants = {
sm: "h-8 px-3 text-xs",
md: "h-10 px-4 text-sm",
lg: "h-12 px-6 text-base",
};
export default function EnhancedButton({
className,
variant = "primary",
size = "md",
isLoading = false,
loadingText,
icon,
iconPosition = "left",
children,
disabled,
...props
}: EnhancedButtonProps) {
const isDisabled = disabled || isLoading;
return (
<motion.button
whileHover={!isDisabled ? { scale: 1.02, y: -1 } : {}}
whileTap={!isDisabled ? { scale: 0.98 } : {}}
transition={{ duration: 0.2 }}
className={cn(
// Base styles
"relative inline-flex items-center justify-center rounded-lg font-medium transition-all duration-200",
"focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background",
"disabled:opacity-50 disabled:cursor-not-allowed",
// Enhanced shadow and depth
"shadow-sm hover:shadow-md active:shadow-sm",
// Variant styles
buttonVariants[variant],
// Size styles
sizeVariants[size],
className
)}
disabled={isDisabled}
{...props}
>
{/* Loading overlay */}
{isLoading && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="absolute inset-0 flex items-center justify-center bg-current/10 rounded-lg"
>
<Loader2 className="w-4 h-4 animate-spin" />
</motion.div>
)}
{/* Content */}
<motion.div
animate={{ opacity: isLoading ? 0 : 1 }}
transition={{ duration: 0.2 }}
className="flex items-center gap-2"
>
{icon && iconPosition === "left" && (
<motion.span
whileHover={{ x: variant === "outline" ? 2 : 0 }}
transition={{ duration: 0.2 }}
>
{icon}
</motion.span>
)}
<span>{isLoading && loadingText ? loadingText : children}</span>
{icon && iconPosition === "right" && (
<motion.span
whileHover={{ x: 2 }}
transition={{ duration: 0.2 }}
>
{icon}
</motion.span>
)}
</motion.div>
</motion.button>
);
}lib/utils.ts
import { siteConfig } from "@/lib/config";
import { type ClassValue, clsx } from "clsx";
import { Metadata } from "next";
import { twMerge } from "tailwind-merge";
import { customAlphabet } from "nanoid";
import ms from "ms";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function absoluteUrl(path: string) {
return `${process.env.NEXT_PUBLIC_APP_URL || siteConfig.url}${path}`;
}
export function constructMetadata({
title = siteConfig.name,
description = siteConfig.description,
image = absoluteUrl("/og"),
canonical,
noIndex = false,
...props
}: {
title?: string;
description?: string;
image?: string;
canonical?: string;
noIndex?: boolean;
[key: string]: Metadata[keyof Metadata];
}): Metadata {
return {
title: {
template: "%s | " + siteConfig.name,
default: siteConfig.name,
},
description: description || siteConfig.description,
keywords: siteConfig.keywords,
openGraph: {
title,
description,
url: canonical,
siteName: siteConfig.name,
images: [
{
url: image,
width: 1200,
height: 630,
alt: title,
},
],
type: "website",
locale: "en_US",
},
twitter: {
card: "summary_large_image",
title,
description,
images: [image],
creator: "@codehagen",
site: "@prismui",
},
robots: {
index: !noIndex,
follow: !noIndex,
googleBot: {
index: !noIndex,
follow: !noIndex,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
icons: "/favicon.ico",
metadataBase: new URL(siteConfig.url),
alternates: {
canonical: canonical,
},
authors: [
{
name: siteConfig.name,
url: siteConfig.url,
},
],
...props,
};
}
export function formatDate(date: string) {
let currentDate = new Date().getTime();
if (!date.includes("T")) {
date = `${date}T00:00:00`;
}
let targetDate = new Date(date).getTime();
let timeDifference = Math.abs(currentDate - targetDate);
let daysAgo = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
let fullDate = new Date(date).toLocaleString("en-us", {
month: "long",
day: "numeric",
year: "numeric",
});
if (daysAgo < 1) {
return "Today";
} else if (daysAgo < 7) {
return `${fullDate} (${daysAgo}d ago)`;
} else if (daysAgo < 30) {
const weeksAgo = Math.floor(daysAgo / 7);
return `${fullDate} (${weeksAgo}w ago)`;
} else if (daysAgo < 365) {
const monthsAgo = Math.floor(daysAgo / 30);
return `${fullDate} (${monthsAgo}mo ago)`;
} else {
const yearsAgo = Math.floor(daysAgo / 365);
return `${fullDate} (${yearsAgo}y ago)`;
}
}
export const timeAgo = (
timestamp: Date | null,
{
withAgo,
}: {
withAgo?: boolean;
} = {}
): string => {
if (!timestamp) return "Never";
const diff = Date.now() - new Date(timestamp).getTime();
if (diff < 1000) {
// less than 1 second
return "Just now";
} else if (diff > 82800000) {
// more than 23 hours – similar to how Twitter displays timestamps
return new Date(timestamp).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year:
new Date(timestamp).getFullYear() !== new Date().getFullYear()
? "numeric"
: undefined,
});
}
return `${ms(diff)}${withAgo ? " ago" : ""}`;
};
export function nFormatter(num: number, digits?: number) {
if (!num) return "0";
const lookup = [
{ value: 1, symbol: "" },
{ value: 1e3, symbol: "K" },
{ value: 1e6, symbol: "M" },
{ value: 1e9, symbol: "G" },
{ value: 1e12, symbol: "T" },
{ value: 1e15, symbol: "P" },
{ value: 1e18, symbol: "E" },
];
const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
const item = lookup
.slice()
.reverse()
.find(function (item) {
return num >= item.value;
});
return item
? (num / item.value).toFixed(digits || 1).replace(rx, "$1") + item.symbol
: "0";
}
export const nanoid = customAlphabet(
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
7
); // 7-character random string
interface SWRError extends Error {
status: number;
}
lib/config.tsx
export const BLUR_FADE_DELAY = 0.15;
export const siteConfig = {
name: "Prism UI",
description: "Build better apps faster with Prism UI - Modern React component library with pre-built sections and advanced UI patterns",
url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
keywords: [
"React Components",
"UI Library",
"Tailwind CSS",
"Next.js",
"shadcn/ui",
"Component Library",
"UI Kit",
"Design System",
"Web Development",
"Frontend Framework"
],
links: {
email: "support@prism.ui",
twitter: "https://twitter.com/prismui",
discord: "https://discord.gg/",
github: "https://github.com/Codehagen/Prismui",
instagram: "https://instagram.com/prismui/",
},
navItems: [
{
href: "/docs",
title: "Docs",
},
{
href: "/components",
title: "Components",
},
{
href: "/pro",
title: "Templates",
},
{
href: "/blog",
title: "Blog",
},
],
header: [
{
href: "/docs",
label: "Docs",
},
{
href: "/components",
label: "Components",
},
{
href: "/pro",
label: "Templates",
},
{
href: "/blog",
label: "Blog",
},
],
};
export type SiteConfig = typeof siteConfig;
demo.tsx
export { default as default } from "@/registry/example/enhanced-button-basic";CSS
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties;
@layer theme, base, components, utilities;
@layer theme {
:root, :host {
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
"Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
--spacing: 0.25rem;
--text-xs: 0.75rem;
--text-xs--line-height: calc(1 / 0.75);
--text-sm: 0.875rem;
--text-sm--line-height: calc(1.25 / 0.875);
--text-base: 1rem;
--text-base--line-height: calc(1.5 / 1);
--font-weight-medium: 500;
--animate-spin: spin 1s linear infinite;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
--default-font-family: var(--font-sans);
--default-mono-font-family: var(--font-mono);
}
}
@layer base {
*, ::after, ::before, ::backdrop, ::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
html, :host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family: var(--default-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
font-feature-settings: var(--default-font-feature-settings, normal);
font-variation-settings: var(--default-font-variation-settings, normal);
-webkit-tap-highlight-color: transparent;
}
hr {
height: 0;
color: inherit;
border-top-width: 1px;
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
h1, h2, h3, h4, h5, h6 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
-webkit-text-decoration: inherit;
text-decoration: inherit;
}
b, strong {
font-weight: bolder;
}
code, kbd, samp, pre {
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
font-feature-settings: var(--default-mono-font-feature-settings, normal);
font-variation-settings: var(--default-mono-font-variation-settings, normal);
font-size: 1em;
}
small {
font-size: 80%;
}
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
:-moz-focusring:where(:not(iframe)) {
outline: auto;
}
progress {
vertical-align: baseline;
}
summary {
display: list-item;
}
ol, ul, menu {
list-style: none;
}
img, svg, video, canvas, audio, iframe, embed, object {
display: block;
vertical-align: middle;
}
img, video {
max-width: 100%;
height: auto;
}
button, input, select, optgroup, textarea, ::file-selector-button {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
border-radius: 0;
background-color: transparent;
opacity: 1;
}
:where(select:is([multiple], [size])) optgroup {
font-weight: bolder;
}
:where(select:is([multiple], [size])) optgroup option {
padding-inline-start: 20px;
}
::file-selector-button {
margin-inline-end: 4px;
}
::placeholder {
opacity: 1;
}
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
::placeholder {
color: currentcolor;
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, currentcolor 50%, transparent);
}
}
}
textarea {
resize: vertical;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-date-and-time-value {
min-height: 1lh;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
padding-block: 0;
}
::-webkit-calendar-picker-indicator {
line-height: 1;
}
:-moz-ui-invalid {
box-shadow: none;
}
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
appearance: button;
}
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
height: auto;
}
[hidden]:where(:not([hidden="until-found"])) {
display: none !important;
}
}
@layer utilities {
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.inset-0 {
inset: 0px;
}
.flex {
display: flex;
}
.inline-flex {
display: inline-flex;
}
.h-4 {
height: calc(var(--spacing) * 4);
}
.h-8 {
height: calc(var(--spacing) * 8);
}
.h-10 {
height: calc(var(--spacing) * 10);
}
.h-12 {
height: calc(var(--spacing) * 12);
}
.min-h-\[200px\] {
min-height: 200px;
}
.w-4 {
width: calc(var(--spacing) * 4);
}
.w-full {
width: 100%;
}
.animate-spin {
animation: var(--animate-spin);
}
.items-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.gap-2 {
gap: calc(var(--spacing) * 2);
}
.rounded-lg {
border-radius: var(--radius);
}
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-border {
border-color: var(--border);
}
.bg-background {
background-color: var(--background);
}
.bg-current\/10 {
background-color: currentcolor;
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, currentcolor 10%, transparent);
}
}
.bg-primary {
background-color: var(--primary);
}
.bg-secondary {
background-color: var(--secondary);
}
.px-3 {
padding-inline: calc(var(--spacing) * 3);
}
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
.px-6 {
padding-inline: calc(var(--spacing) * 6);
}
.text-base {
font-size: var(--text-base);
line-height: var(--tw-leading, var(--text-base--line-height));
}
.text-sm {
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
}
.text-xs {
font-size: var(--text-xs);
line-height: var(--tw-leading, var(--text-xs--line-height));
}
.font-medium {
--tw-font-weight: var(--font-weight-medium);
font-weight: var(--font-weight-medium);
}
.text-primary-foreground {
color: var(--primary-foreground);
}
.text-secondary-foreground {
color: var(--secondary-foreground);
}
.shadow {
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.shadow-sm {
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.transition-all {
transition-property: all;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.duration-200 {
--tw-duration: 200ms;
transition-duration: 200ms;
}
@media (hover: hover) {
.hover\:bg-muted:hover {
background-color: var(--muted);
}
.hover\:bg-primary\/90:hover {
background-color: var(--primary);
}
@supports (color: color-mix(in lab, red, red)) {
.hover\:bg-primary\/90:hover {
background-color: color-mix(in oklab, var(--primary) 90%, transparent);
}
}
.hover\:bg-secondary\/90:hover {
background-color: var(--secondary);
}
@supports (color: color-mix(in lab, red, red)) {
.hover\:bg-secondary\/90:hover {
background-color: color-mix(in oklab, var(--secondary) 90%, transparent);
}
}
.hover\:text-foreground:hover {
color: var(--foreground);
}
.hover\:shadow-md:hover {
--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
}
.focus\:ring-2:focus {
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.focus\:ring-border:focus {
--tw-ring-color: var(--border);
}
.focus\:ring-muted:focus {
--tw-ring-color: var(--muted);
}
.focus\:ring-primary\/50:focus {
--tw-ring-color: var(--primary);
@supports (color: color-mix(in lab, red, red)) {
--tw-ring-color: color-mix(in oklab, var(--primary) 50%, transparent);
}
}
.focus\:ring-secondary\/50:focus {
--tw-ring-color: var(--secondary);
@supports (color: color-mix(in lab, red, red)) {
--tw-ring-color: color-mix(in oklab, var(--secondary) 50%, transparent);
}
}
.focus\:ring-offset-2:focus {
--tw-ring-offset-width: 2px;
--tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.focus\:ring-offset-background:focus {
--tw-ring-offset-color: var(--background);
}
.focus\:outline-none:focus {
--tw-outline-style: none;
outline-style: none;
}
.active\:shadow-sm:active {
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.disabled\:cursor-not-allowed:disabled {
cursor: not-allowed;
}
.disabled\:opacity-50:disabled {
opacity: 50%;
}
}
:root {
--background: #fff;
--foreground: #111;
--primary: #171717;
--primary-foreground: #fff;
--secondary: #eee;
--secondary-foreground: #171717;
--muted: #eee;
--muted-foreground: #666;
--accent: #eee;
--accent-foreground: #171717;
--border: #ddd;
--input: #ddd;
--ring: #777;
--destructive: #dc2626;
--destructive-foreground: #fff;
--popover: #fff;
--popover-foreground: #111;
--success: #15803d;
--success-foreground: #fff;
--radius: .625rem;
--hairline: 1px;
}
.dark {
--background: #090909;
--foreground: #fafafa;
--primary: #fafafa;
--primary-foreground: #171717;
--secondary: #262626;
--secondary-foreground: #fafafa;
--muted: #262626;
--muted-foreground: #a3a3a3;
--accent: #262626;
--accent-foreground: #fafafa;
--border: #333;
--input: #333;
--popover: #171717;
--popover-foreground: #fafafa;
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@property --tw-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-shadow-color {
syntax: "*";
inherits: false;
}
@property --tw-shadow-alpha {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-inset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-shadow-color {
syntax: "*";
inherits: false;
}
@property --tw-inset-shadow-alpha {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-ring-color {
syntax: "*";
inherits: false;
}
@property --tw-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-ring-color {
syntax: "*";
inherits: false;
}
@property --tw-inset-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-ring-inset {
syntax: "*";
inherits: false;
}
@property --tw-ring-offset-width {
syntax: "<length>";
inherits: false;
initial-value: 0px;
}
@property --tw-ring-offset-color {
syntax: "*";
inherits: false;
initial-value: #fff;
}
@property --tw-ring-offset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-duration {
syntax: "*";
inherits: false;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {
--tw-border-style: solid;
--tw-font-weight: initial;
--tw-shadow: 0 0 #0000;
--tw-shadow-color: initial;
--tw-shadow-alpha: 100%;
--tw-inset-shadow: 0 0 #0000;
--tw-inset-shadow-color: initial;
--tw-inset-shadow-alpha: 100%;
--tw-ring-color: initial;
--tw-ring-shadow: 0 0 #0000;
--tw-inset-ring-color: initial;
--tw-inset-ring-shadow: 0 0 #0000;
--tw-ring-inset: initial;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-offset-shadow: 0 0 #0000;
--tw-outline-style: solid;
--tw-duration: initial;
}
}
}