mirror of
https://github.com/homarr-labs/dashboard-icons.git
synced 2026-01-12 16:25:38 +08:00
feat: enhance styling and animations for search
- Added rainbow animation to global styles. - Introduced new color variables for consistent theming. - Updated AddToSearchBarButton to use the new RainbowButton component. - Adjusted dialog content size for better layout. - Removed deprecated RainbowButton component from magicui registry.
This commit is contained in:
@@ -152,6 +152,26 @@
|
||||
--shadow-opacity: var(--shadow-opacity);
|
||||
|
||||
--color-shadow-color: var(--shadow-color);
|
||||
|
||||
--animate-rainbow: rainbow var(--speed, 2s) infinite linear;
|
||||
|
||||
--color-color-5: var(--color-5);
|
||||
|
||||
--color-color-4: var(--color-4);
|
||||
|
||||
--color-color-3: var(--color-3);
|
||||
|
||||
--color-color-2: var(--color-2);
|
||||
|
||||
--color-color-1: var(--color-1);
|
||||
@keyframes rainbow {
|
||||
0% {
|
||||
background-position: 0%;
|
||||
}
|
||||
100% {
|
||||
background-position: 200%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
@@ -223,6 +243,16 @@
|
||||
--spacing: 0.25rem;
|
||||
|
||||
--tracking-normal: 0em;
|
||||
|
||||
--color-1: oklch(66.2% 0.225 25.9);
|
||||
|
||||
--color-2: oklch(60.4% 0.26 302);
|
||||
|
||||
--color-3: oklch(69.6% 0.165 251);
|
||||
|
||||
--color-4: oklch(80.2% 0.134 225);
|
||||
|
||||
--color-5: oklch(90.7% 0.231 133);
|
||||
}
|
||||
|
||||
.dark {
|
||||
@@ -284,6 +314,16 @@
|
||||
--shadow-offset-x: 0px;
|
||||
|
||||
--shadow-offset-y: 2px;
|
||||
|
||||
--color-1: oklch(66.2% 0.225 25.9);
|
||||
|
||||
--color-2: oklch(60.4% 0.26 302);
|
||||
|
||||
--color-3: oklch(69.6% 0.165 251);
|
||||
|
||||
--color-4: oklch(80.2% 0.134 225);
|
||||
|
||||
--color-5: oklch(90.7% 0.231 133);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@@ -340,4 +380,4 @@
|
||||
input.error:focus {
|
||||
@apply ring-2 ring-destructive ring-offset-2 ring-offset-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState } from "react"
|
||||
import { Check, Copy, Globe2, Search, Sparkles } from "lucide-react"
|
||||
import { RainbowButton } from "@/registry/magicui/rainbow-button"
|
||||
import { RainbowButton } from "@/components/ui/rainbow-button"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
@@ -80,18 +80,17 @@ export function AddToSearchBarButton({
|
||||
variant="outline"
|
||||
size={size}
|
||||
className={cn(
|
||||
"shadow-md px-5 hover:shadow-primary/30 active:scale-[0.99]",
|
||||
"shadow-sm",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Search className="h-4 w-4" />
|
||||
<span className="hidden sm:inline">Add to browser search</span>
|
||||
<span className="hidden sm:inline text-foreground group-hover:scale-105 transition-all duration-300">Add to browser search</span>
|
||||
<span className="sm:hidden">Add to search</span>
|
||||
<Sparkles className="h-4 w-4 text-primary" />
|
||||
</RainbowButton>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent className="sm:max-w-xl">
|
||||
<DialogContent className="sm:max-w-5xl">
|
||||
<DialogHeader className="space-y-1">
|
||||
<DialogTitle className="flex items-center gap-2 text-lg sm:text-xl">
|
||||
<Globe2 className="h-5 w-5 text-primary" />
|
||||
|
||||
@@ -325,7 +325,7 @@ export function IconSearch({ icons }: IconSearchProps) {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<AddToSearchBarButton size="sm" className="flex-1 sm:flex-none" />
|
||||
<AddToSearchBarButton className="flex-1 sm:flex-none rounded-sm" />
|
||||
|
||||
{/* Clear all button */}
|
||||
{(searchQuery || selectedCategories.length > 0 || sortOption !== "relevance") && (
|
||||
|
||||
@@ -164,3 +164,5 @@ export {
|
||||
ModalTrigger,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
61
web/src/components/ui/rainbow-button.tsx
Normal file
61
web/src/components/ui/rainbow-button.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const rainbowButtonVariants = cva(
|
||||
cn(
|
||||
"relative cursor-pointer group transition-all animate-rainbow",
|
||||
"inline-flex items-center justify-center gap-2 shrink-0",
|
||||
"rounded-sm outline-none focus-visible:ring-[3px] aria-invalid:border-destructive",
|
||||
"text-sm font-medium whitespace-nowrap",
|
||||
"disabled:pointer-events-none disabled:opacity-50",
|
||||
"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0"
|
||||
),
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border-0 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))] bg-[length:200%] text-primary-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.125rem)_solid_transparent] 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(0.75rem)] 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))]",
|
||||
outline:
|
||||
"border border-input border-b-transparent bg-[linear-gradient(#ffffff,#ffffff),linear-gradient(#ffffff_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))] bg-[length:200%] text-accent-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] 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(0.75rem)] dark:bg-[linear-gradient(#0a0a0a,#0a0a0a),linear-gradient(#0a0a0a_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))]",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-xl px-3 text-xs",
|
||||
lg: "h-11 rounded-xl px-8",
|
||||
icon: "size-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
interface RainbowButtonProps
|
||||
extends
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof rainbowButtonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const RainbowButton = React.forwardRef<HTMLButtonElement, RainbowButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
data-slot="button"
|
||||
className={cn(rainbowButtonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
RainbowButton.displayName = "RainbowButton"
|
||||
|
||||
export { RainbowButton, rainbowButtonVariants, type RainbowButtonProps }
|
||||
@@ -1,58 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const rainbowButtonVariants = cva(
|
||||
"relative inline-flex items-center justify-center overflow-hidden rounded-full font-semibold transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "text-white shadow-lg",
|
||||
outline: "text-foreground border border-border bg-background/80 backdrop-blur-sm",
|
||||
},
|
||||
size: {
|
||||
sm: "h-9 px-4 text-sm",
|
||||
default: "h-10 px-6 text-sm",
|
||||
lg: "h-12 px-8 text-base",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
export interface RainbowButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof rainbowButtonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const RainbowButton = React.forwardRef<HTMLButtonElement, RainbowButtonProps>(
|
||||
({ className, variant, size, asChild = false, children, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
|
||||
return (
|
||||
<Comp
|
||||
ref={ref}
|
||||
className={cn("group isolate", rainbowButtonVariants({ variant, size }), className)}
|
||||
{...props}
|
||||
>
|
||||
<span
|
||||
aria-hidden
|
||||
className="absolute inset-0 -z-10 animate-[spin_6s_linear_infinite] bg-[conic-gradient(#f97316,#f43f5e,#a855f7,#06b6d4,#22c55e,#f59e0b,#f97316)] opacity-80"
|
||||
/>
|
||||
<span aria-hidden className="absolute inset-[1px] -z-0 rounded-full bg-background/80" />
|
||||
<span className="relative z-10 flex items-center gap-2">{children}</span>
|
||||
</Comp>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
RainbowButton.displayName = "RainbowButton"
|
||||
|
||||
export { RainbowButton, rainbowButtonVariants }
|
||||
Reference in New Issue
Block a user