new styles

This commit is contained in:
User
2025-01-06 20:19:07 +03:00
parent 8b589470ac
commit 847102e843
51 changed files with 8457 additions and 627 deletions

View File

@@ -0,0 +1,29 @@
import Image from "next/image"
import { Button } from "./ui/button"
export function Banner() {
return (
<div className="relative w-full h-[300px] rounded-lg overflow-hidden">
<Image
src="/placeholder.svg"
alt="Promotional Banner"
fill
className="object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/90 to-blue-600/50 flex items-center">
<div className="container mx-auto px-4">
<div className="max-w-lg text-white">
<h1 className="text-4xl font-bold mb-4">САМОЕ ЗАВЕТНОЕ!</h1>
<p className="text-xl mb-6">
Исполняйте мечты с Eternos
</p>
<Button variant="secondary" size="lg">
Подробнее
</Button>
</div>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,97 @@
"use client"
import { useState } from "react"
import { Checkbox } from "./ui/checkbox"
import { Button } from "./ui/button"
import { Minus, Plus, Heart, Trash } from 'lucide-react'
import Image from "next/image"
const SAMPLE_ITEMS = [
{
id: 1,
name: "Бумага офисная SvetoCopy, 500 листов, А4",
price: 352,
oldPrice: 399,
image: "/placeholder.svg",
},
{
id: 2,
name: "Глюкометр Диаконт Концепт + тест-полоски",
price: 1450,
oldPrice: 1599,
image: "/placeholder.svg",
}
]
export function CartItems() {
const [selectedItems, setSelectedItems] = useState<number[]>([])
const toggleItem = (id: number) => {
setSelectedItems(prev =>
prev.includes(id)
? prev.filter(item => item !== id)
: [...prev, id]
)
}
return (
<div className="space-y-4">
<div className="flex items-center gap-2 mb-4">
<Checkbox
checked={selectedItems.length === SAMPLE_ITEMS.length}
onCheckedChange={(checked) => {
setSelectedItems(checked ? SAMPLE_ITEMS.map(item => item.id) : [])
}}
/>
<span>Выбрать все</span>
{selectedItems.length > 0 && (
<button className="text-red-500 ml-4 hover:underline">
Удалить выбранные
</button>
)}
</div>
{SAMPLE_ITEMS.map((item) => (
<div key={item.id} className="flex gap-4 p-4 bg-white rounded-lg">
<Checkbox
checked={selectedItems.includes(item.id)}
onCheckedChange={() => toggleItem(item.id)}
/>
<Image
src={item.image}
alt={item.name}
width={100}
height={100}
className="object-cover"
/>
<div className="flex-1">
<h3 className="font-medium">{item.name}</h3>
<div className="flex gap-4 mt-4">
<div className="flex items-center gap-2">
<Button variant="outline" size="icon">
<Minus className="h-4 w-4" />
</Button>
<span className="w-8 text-center">1</span>
<Button variant="outline" size="icon">
<Plus className="h-4 w-4" />
</Button>
</div>
<Button variant="ghost" size="icon">
<Heart className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon">
<Trash className="h-4 w-4" />
</Button>
</div>
</div>
<div className="text-right">
<div className="text-lg font-bold">{item.price} </div>
<div className="text-sm text-muted-foreground line-through">
{item.oldPrice}
</div>
</div>
</div>
))}
</div>
)
}

View File

@@ -0,0 +1,27 @@
import { Button } from "./ui/button"
export function CartSummary() {
return (
<div className="bg-white p-4 rounded-lg">
<h2 className="text-lg font-semibold mb-4">Ваша корзина</h2>
<div className="space-y-2 mb-4">
<div className="flex justify-between">
<span>Товары (2)</span>
<span>10 236 </span>
</div>
<div className="flex justify-between text-green-600">
<span>Скидка</span>
<span>- 4 387 </span>
</div>
</div>
<div className="flex justify-between text-lg font-bold mb-4">
<span>С Ozon Картой</span>
<span>5 467 </span>
</div>
<Button className="w-full" size="lg">
Перейти к оформлению
</Button>
</div>
)
}

View File

@@ -0,0 +1,96 @@
"use client"
import * as React from "react"
import Link from "next/link"
import { Laptop, Smartphone, ShirtIcon, Home, Car, Baby, Dumbbell, BookOpen, Gift, MoreHorizontal } from 'lucide-react'
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
const categories = [
{
title: "Электроника",
icon: <Laptop className="w-5 h-5" />,
subcategories: ["Ноутбуки", "Планшеты", "Компьютеры", "Аксессуары"]
},
{
title: "Смартфоны и гаджеты",
icon: <Smartphone className="w-5 h-5" />,
subcategories: ["Телефоны", "Смарт-часы", "Наушники"]
},
{
title: "Одежда и обувь",
icon: <ShirtIcon className="w-5 h-5" />,
subcategories: ["Мужская одежда", "Женская одежда", "Обувь", "Аксессуары"]
},
{
title: "Дом и сад",
icon: <Home className="w-5 h-5" />,
subcategories: ["Мебель", "Текстиль", "Освещение", "Инструменты"]
},
{
title: "Авто",
icon: <Car className="w-5 h-5" />,
subcategories: ["Запчасти", "Шины", "Электроника", "Аксессуары"]
},
{
title: "Детские товары",
icon: <Baby className="w-5 h-5" />,
subcategories: ["Игрушки", "Питание", "Одежда", "Коляски"]
},
{
title: "Спорт и отдых",
icon: <Dumbbell className="w-5 h-5" />,
subcategories: ["Тренажеры", "Одежда", "Туризм"]
},
{
title: "Книги",
icon: <BookOpen className="w-5 h-5" />,
subcategories: ["Художественная", "Учебная", "Детская"]
},
{
title: "Подарки",
icon: <Gift className="w-5 h-5" />,
subcategories: ["Сувениры", "Цветы", "Подарочные наборы"]
},
]
export function CatalogMenu() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Каталог</NavigationMenuTrigger>
<NavigationMenuContent>
<div className="w-[500px] p-4">
<div className="grid gap-3">
{categories.map((category) => (
<Link
key={category.title}
href="#"
className="flex items-center gap-2 p-2 hover:bg-gray-100 rounded-md group"
>
<span className="group-hover:text-blue-600">{category.icon}</span>
<div className="flex-1">
<div className="font-medium group-hover:text-blue-600">{category.title}</div>
<div className="text-sm text-gray-500">
{category.subcategories.join(" • ")}
</div>
</div>
<MoreHorizontal className="w-5 h-5 text-gray-400" />
</Link>
))}
</div>
</div>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
)
}

View File

@@ -0,0 +1,57 @@
import Link from "next/link"
import { Facebook, Instagram, Twitter } from 'lucide-react'
export function Footer() {
return (
<footer className="bg-white border-t mt-16">
<div className="container mx-auto px-4 py-12">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<h3 className="font-semibold mb-4">О компании</h3>
<ul className="space-y-2">
<li><Link href="#" className="text-gray-600 hover:text-gray-900">О нас</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Вакансии</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Реквизиты</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Пресс-центр</Link></li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">Покупателям</h3>
<ul className="space-y-2">
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Как сделать заказ</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Способы оплаты</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Доставка</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Возврат товара</Link></li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">Партнерам</h3>
<ul className="space-y-2">
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Продавайте на Store</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Перевозчикам</Link></li>
<li><Link href="#" className="text-gray-600 hover:text-gray-900">Откройте пункт выдачи</Link></li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">Мы в соцсетях</h3>
<div className="flex space-x-4">
<Link href="#" className="text-gray-600 hover:text-gray-900">
<Facebook className="h-6 w-6" />
</Link>
<Link href="#" className="text-gray-600 hover:text-gray-900">
<Instagram className="h-6 w-6" />
</Link>
<Link href="#" className="text-gray-600 hover:text-gray-900">
<Twitter className="h-6 w-6" />
</Link>
</div>
</div>
</div>
<div className="border-t mt-8 pt-8 text-center text-gray-600">
<p>© 2024 Store. Все права защищены.</p>
</div>
</div>
</footer>
)
}

View File

@@ -0,0 +1,35 @@
import Link from "next/link"
import { Search } from "./search"
import { Button } from "./ui/button"
import { ShoppingCart, Heart, Package2 } from 'lucide-react'
import { CatalogMenu } from "./catalog-menu"
export function Header() {
return (
<header className="border-b sticky top-0 bg-white z-50">
<div className="container mx-auto px-4">
<div className="flex h-16 items-center justify-between">
<div className="flex items-center gap-8">
<Link href="/" className="text-2xl font-bold text-blue-600">
Eternos
</Link>
<CatalogMenu />
<Search />
</div>
<div className="flex items-center gap-4">
<Button variant="ghost" size="icon">
<Package2 className="h-5 w-5" />
</Button>
<Button variant="ghost" size="icon">
<Heart className="h-5 w-5" />
</Button>
<Button variant="ghost" size="icon">
<ShoppingCart className="h-5 w-5" />
</Button>
</div>
</div>
</div>
</header>
)
}

View File

@@ -0,0 +1,60 @@
import Image from "next/image"
import { Heart } from 'lucide-react'
import { Button } from "./ui/button"
import { Badge } from "./ui/badge"
interface ProductCardProps {
product: {
id: number
title: string
price: number
oldPrice: number
discount: number
image: string
isHotDeal?: boolean
isSale?: boolean
}
}
export function ProductCard({ product }: ProductCardProps) {
return (
<div className="group relative bg-white rounded-lg p-2 transition-shadow hover:shadow-lg">
<div className="relative aspect-square mb-2">
<Image
src={product.image}
alt={product.title}
fill
className="object-cover rounded-lg"
/>
<Button
variant="ghost"
size="icon"
className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity"
>
<Heart className="h-5 w-5" />
</Button>
{product.isHotDeal && (
<div className="absolute top-2 left-2 bg-pink-500 text-white px-2 py-1 text-xs font-medium rounded">
НАРАСХВАТ
</div>
)}
</div>
<div className="space-y-2">
<div className="flex items-baseline gap-2">
<span className="text-xl font-bold">{product.price} </span>
<span className="text-sm text-muted-foreground line-through">
{product.oldPrice}
</span>
<span className="text-sm text-red-500">-{product.discount}%</span>
</div>
<h3 className="text-sm line-clamp-2">{product.title}</h3>
{product.isSale && (
<Badge variant="destructive" className="mt-2">
Распродажа
</Badge>
)}
</div>
</div>
)
}

View File

@@ -0,0 +1,80 @@
"use client"
import { useState } from "react"
import { Slider } from "@/components/ui/slider"
import { Checkbox } from "@/components/ui/checkbox"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
export function ProductFilters() {
const [priceRange, setPriceRange] = useState([0, 10000])
return (
<div className="w-64 bg-white p-4 rounded-lg">
<h3 className="font-semibold mb-4">Фильтры</h3>
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="price">
<AccordionTrigger>Цена</AccordionTrigger>
<AccordionContent>
<div className="space-y-4">
<Slider
defaultValue={[0, 10000]}
max={10000}
step={100}
value={priceRange}
onValueChange={setPriceRange}
className="mt-6"
/>
<div className="flex justify-between text-sm">
<span>{priceRange[0]} </span>
<span>{priceRange[1]} </span>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="brand">
<AccordionTrigger>Бренд</AccordionTrigger>
<AccordionContent>
<div className="space-y-2">
<label className="flex items-center gap-2">
<Checkbox id="samsung" />
<span>Samsung</span>
</label>
<label className="flex items-center gap-2">
<Checkbox id="apple" />
<span>Apple</span>
</label>
<label className="flex items-center gap-2">
<Checkbox id="xiaomi" />
<span>Xiaomi</span>
</label>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="availability">
<AccordionTrigger>Наличие</AccordionTrigger>
<AccordionContent>
<div className="space-y-2">
<label className="flex items-center gap-2">
<Checkbox id="in-stock" />
<span>В наличии</span>
</label>
<label className="flex items-center gap-2">
<Checkbox id="express-delivery" />
<span>Экспресс-доставка</span>
</label>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
)
}

View File

@@ -0,0 +1,70 @@
import { ProductCard } from "./product-card"
const SAMPLE_PRODUCTS = [
{
id: 1,
title: "Кофе растворимый Жокей Крепкий, 3 в 1, с сахаром",
price: 89,
oldPrice: 172,
discount: 48,
image: "/placeholder.svg",
isHotDeal: true,
isSale: true,
},
{
id: 2,
title: "Рексона Дезодорант женский твердый стик",
price: 235,
oldPrice: 397,
discount: 40,
image: "/placeholder.svg",
isHotDeal: true,
},
{
id: 3,
title: "Сухой корм Мираторг MEAT с нежной телятиной",
price: 187,
oldPrice: 294,
discount: 36,
image: "/placeholder.svg",
isHotDeal: true,
},
{
id: 4,
title: "Сухой корм KITEKAT™ для взрослых кошек «Мясной пир»",
price: 174,
oldPrice: 209,
discount: 16,
image: "/placeholder.svg",
isHotDeal: true,
},
{
id: 5,
title: "Специальное чистящее средство для стиральных машин",
price: 197,
oldPrice: 469,
discount: 57,
image: "/placeholder.svg",
isHotDeal: true,
},
{
id: 6,
title: "Крем для лица увлажняющий",
price: 184,
oldPrice: 413,
discount: 55,
image: "/placeholder.svg",
isHotDeal: true,
},
]
export function ProductGrid() {
return (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-4">
{SAMPLE_PRODUCTS.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
)
}

View File

@@ -0,0 +1,17 @@
"use client"
import { SearchIcon } from 'lucide-react'
import { Input } from "./ui/input"
export function Search() {
return (
<div className="relative w-full max-w-lg">
<SearchIcon className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Искать на Store"
className="pl-8 w-full"
/>
</div>
)
}

View File

@@ -0,0 +1,58 @@
"use client"
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const Accordion = AccordionPrimitive.Root
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("border-b", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }

View File

@@ -0,0 +1,36 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
}
export { Badge, badgeVariants }

View File

@@ -0,0 +1,56 @@
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 buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }

View File

@@ -0,0 +1,30 @@
"use client"
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { Check } from "lucide-react"
import { cn } from "@/lib/utils"
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<Check className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
))
Checkbox.displayName = CheckboxPrimitive.Root.displayName
export { Checkbox }

View File

@@ -0,0 +1,22 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = "Input"
export { Input }

View File

@@ -0,0 +1,128 @@
import * as React from "react"
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { cva } from "class-variance-authority"
import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const NavigationMenu = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Root
ref={ref}
className={cn(
"relative z-10 flex max-w-max flex-1 items-center justify-center",
className
)}
{...props}
>
{children}
<NavigationMenuViewport />
</NavigationMenuPrimitive.Root>
))
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
const NavigationMenuList = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.List>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.List
ref={ref}
className={cn(
"group flex flex-1 list-none items-center justify-center space-x-1",
className
)}
{...props}
/>
))
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
const NavigationMenuItem = NavigationMenuPrimitive.Item
const navigationMenuTriggerStyle = cva(
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50"
)
const NavigationMenuTrigger = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Trigger
ref={ref}
className={cn(navigationMenuTriggerStyle(), "group", className)}
{...props}
>
{children}{" "}
<ChevronDown
className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
aria-hidden="true"
/>
</NavigationMenuPrimitive.Trigger>
))
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
const NavigationMenuContent = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Content
ref={ref}
className={cn(
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
className
)}
{...props}
/>
))
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
const NavigationMenuLink = NavigationMenuPrimitive.Link
const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<div className={cn("absolute left-0 top-full flex justify-center")}>
<NavigationMenuPrimitive.Viewport
className={cn(
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
className
)}
ref={ref}
{...props}
/>
</div>
))
NavigationMenuViewport.displayName =
NavigationMenuPrimitive.Viewport.displayName
const NavigationMenuIndicator = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Indicator
ref={ref}
className={cn(
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
className
)}
{...props}
>
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
</NavigationMenuPrimitive.Indicator>
))
NavigationMenuIndicator.displayName =
NavigationMenuPrimitive.Indicator.displayName
export {
navigationMenuTriggerStyle,
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuContent,
NavigationMenuTrigger,
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
}

View File

@@ -0,0 +1,28 @@
"use client"
import * as React from "react"
import * as SliderPrimitive from "@radix-ui/react-slider"
import { cn } from "@/lib/utils"
const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className
)}
{...props}
>
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
))
Slider.displayName = SliderPrimitive.Root.displayName
export { Slider }