home page

This commit is contained in:
cdricms
2025-01-13 11:08:33 +01:00
parent a26516c6e8
commit 7813e42e3a
13 changed files with 1197 additions and 70 deletions

View File

@@ -1,6 +1,7 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google"; import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css"; import "./globals.css";
import Navbar from "@/components/nav-bar";
const geistSans = Geist({ const geistSans = Geist({
variable: "--font-geist-sans", variable: "--font-geist-sans",
@@ -27,6 +28,7 @@ export default function RootLayout({
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased`} className={`${geistSans.variable} ${geistMono.variable} antialiased`}
> >
<Navbar />
{children} {children}
</body> </body>
</html> </html>

View File

@@ -1,69 +1,109 @@
import { Button } from "@/components/ui/button"; import Features, { FeatureItem } from "@/components/features";
import { import Hero from "@/components/hero";
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import Image from "next/image";
export default function Home() { export default function Home() {
return ( return (
<Card className="w-[350px]"> <main>
<CardHeader> <Hero />
<CardTitle>Create project</CardTitle> <Features
<CardDescription> title="DÉVELOPPEMENT DU SYSTÈME"
Deploy your new project in one-click. description="Latosa Escrima Concepts est un système martial dynamique et en constante évolution. Ce système repose sur une approche logique, qui progresse au fil du développement des compétences techniques des pratiquants."
</CardDescription> cta="Envie de découvrir Latosa Escrima ?"
</CardHeader> >
<CardContent> <FeatureItem
<form> title="Les Fondements de Latosa Escrima Concepts"
<div className="grid w-full items-center gap-4"> position="left"
<div className="flex flex-col space-y-1.5"> image="https://shadcnblocks.com/images/block/placeholder-2.svg"
<Label htmlFor="name">Name</Label> >
<Input <ol className="list-decimal text-justify flex flex-col gap-4">
id="name" <li>
placeholder="Name of your project" Un Système Centré sur les Concepts{" "}
/> <ul className="list-disc list-inside">
</div> <li>
<div className="flex flex-col space-y-1.5"> Étude et application des meilleurs concepts
<Label htmlFor="framework">Framework</Label> et stratégies issus de différentes approches
<Select> martiales.
<SelectTrigger id="framework"> </li>
<SelectValue placeholder="Select" /> <li>
</SelectTrigger> Comprendre ce que lon fait, comment on le
<SelectContent position="popper"> fait et pourquoi on le fait.
<SelectItem value="next"> </li>
Next.js </ul>
</SelectItem> </li>
<SelectItem value="sveltekit"> <li>
SvelteKit Éducation au Mouvement et à lEfficacité
</SelectItem> <ul className="list-disc list-inside">
<SelectItem value="astro">Astro</SelectItem> <li>
<SelectItem value="nuxt"> Plus quun enchaînement de techniques : une
Nuxt.js véritable éducation aux mouvements corporels
</SelectItem> et à lefficacité des armes.
</SelectContent> </li>
</Select> <li>
</div> Priorité à lauthenticité et à la réalité.
</div> </li>
</form> </ul>
</CardContent> </li>
<CardFooter className="flex justify-between"> </ol>
<Button variant="outline">Cancel</Button> </FeatureItem>
<Button>Deploy</Button> <FeatureItem
</CardFooter> title="LÉvolution du Système"
</Card> position="right"
image="https://shadcnblocks.com/images/block/placeholder-2.svg"
>
<ol className="list-none text-justify flex flex-col gap-4">
<li>
<span className="font-bold">
Les Premières Étapes
</span>
<ul className="list-disc list-inside">
<li>
Initialement centré sur les techniques et
mouvements, le système sest montré efficace
mais incomplet.
</li>
<li>
Recherche de ce qui différencie les arts
martiaux philippins des autres disciplines.
</li>
</ul>
</li>
<li>
<span className="font-bold">
La Découverte des Concepts Clés
</span>{" "}
<ul className="list-disc list-inside">
<li>
Rôle central des concepts de combat :
<ul className="list-disc list-inside pl-4">
<li>Puissance dans les frappes.</li>
<li>Blocage ferme.</li>
<li>Équilibre et attitude.</li>
</ul>
</li>
<li>
Restructuration des exercices pour intégrer
et transmettre ces concepts fondamentaux.
</li>
</ul>
</li>
</ol>
</FeatureItem>
<FeatureItem
title="Les Principes du Système Aujourdhui"
position="left"
image="https://shadcnblocks.com/images/block/placeholder-2.svg"
>
Latosa Escrima Concepts repose sur cinq concepts
fondamentaux :
<ul className="list-disc list-inside">
<li>Équilibre</li>
<li>Vitesse (Timing et Distance)</li>
<li>Puissance</li>
<li>Concentration</li>
<li>Transition</li>
</ul>
</FeatureItem>
</Features>
</main>
); );
} }

View File

@@ -0,0 +1,79 @@
import { ArrowRight } from "lucide-react";
const Features: React.FC<
React.PropsWithChildren<{
title: string;
description: string;
cta: string;
}>
> = ({ title, description, cta, children }) => {
return (
<section className="py-32 px-4">
<div className="container flex flex-col gap-16 lg:px-16">
<div className="lg:max-w-sm">
<h2 className="mb-3 text-xl font-semibold md:mb-4 md:text-4xl lg:mb-6">
{title}
</h2>
<p className="mb-8 text-muted-foreground lg:text-lg">
{description}
</p>
<a
href="#"
className="group flex items-center text-xs font-medium md:text-base lg:text-lg"
>
{cta}
<ArrowRight className="ml-2 size-4 transition-transform group-hover:translate-x-1" />
</a>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:gap-8">
{children}
</div>
</div>
</section>
);
};
export default Features;
export const FeatureItem: React.FC<
React.PropsWithChildren<{
title: string;
image: string;
position: "left" | "right";
}>
> = ({ title, children, image, position }) => {
const _image = () => (
<div className="md:min-h-[24rem] lg:min-h-[28rem] xl:min-h-[32rem]">
<img
src={image}
alt={title}
className="aspect-[16/9] h-full w-full object-cover object-center"
/>
</div>
);
const _content = () => (
<div className="flex flex-col justify-center px-6 py-8 md:px-8 md:py-10 lg:px-10 lg:py-12">
<h3 className="mb-3 text-lg font-semibold md:mb-4 md:text-2xl lg:mb-6">
{title}
</h3>
<div className="text-muted-foreground lg:text-lg">{children}</div>
</div>
);
return (
<div
className={`flex ${position === "left" ? "flex-col" : "flex-col-reverse"} overflow-clip rounded-xl border border-border md:col-span-2 md:grid md:grid-cols-2 md:gap-6 lg:gap-8`}
>
{position === "left" ? (
<>
<_image />
<_content />
</>
) : (
<>
<_content />
<_image />
</>
)}
</div>
);
};

View File

@@ -0,0 +1,46 @@
import { ExternalLink } from "lucide-react";
import { cn } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
import { Button, buttonVariants } from "@/components/ui/button";
const Hero = () => {
return (
<section
style={{ height: "calc(100vh - 68px)" }}
className="flex justify-center items-center relative overflow-hidden py-32"
>
<div className="">
<div className="bg-blue-50 magicpattern absolute inset-x-0 top-0 -z-10 flex h-full w-full items-center justify-center opacity-100" />
<div className="mx-auto flex max-w-5xl flex-col items-center">
<div className="z-10 flex flex-col items-center gap-6 text-center">
<img
src="https://shadcnblocks.com/images/block/block-1.svg"
alt="logo"
className="h-16"
/>
<Badge variant="outline">Latosa-Escrima</Badge>
<div>
<h1 className="mb-6 text-pretty text-2xl font-bold lg:text-5xl">
Trouvez votre équilibre avec Latosa-Escrima
</h1>
<p className="text-muted-foreground lg:text-xl">
Une évolution des arts martiaux Philippins
</p>
</div>
<div className="mt-4 flex justify-center gap-2">
<Button>Nous contacter</Button>
<Button variant="outline">
À propos
<ExternalLink className="ml-2 h-4" />
</Button>
</div>
</div>
</div>
</div>
</section>
);
};
export default Hero;

View File

@@ -0,0 +1,416 @@
import { Book, Menu, Sunset, Trees, Zap } from "lucide-react";
import { cn } from "@/lib/utils";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Button, buttonVariants } from "@/components/ui/button";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
const subMenuItemsOne = [
{
title: "Blog",
description: "The latest industry news, updates, and info",
icon: <Book className="size-5 shrink-0" />,
},
{
title: "Compnay",
description: "Our mission is to innovate and empower the world",
icon: <Trees className="size-5 shrink-0" />,
},
{
title: "Careers",
description: "Browse job listing and discover our workspace",
icon: <Sunset className="size-5 shrink-0" />,
},
{
title: "Support",
description:
"Get in touch with our support team or visit our community forums",
icon: <Zap className="size-5 shrink-0" />,
},
];
const subMenuItemsTwo = [
{
title: "Help Center",
description: "Get all the answers you need right here",
icon: <Zap className="size-5 shrink-0" />,
},
{
title: "Contact Us",
description: "We are here to help you with any questions you have",
icon: <Sunset className="size-5 shrink-0" />,
},
{
title: "Status",
description: "Check the current status of our services and APIs",
icon: <Trees className="size-5 shrink-0" />,
},
{
title: "Terms of Service",
description: "Our terms and conditions for using our services",
icon: <Book className="size-5 shrink-0" />,
},
];
const Navbar = () => {
return (
<section className="p-4">
<div className="">
<nav className="hidden justify-between lg:flex">
<div className="flex items-center gap-6">
<div className="flex items-center gap-2">
<img
src="https://shadcnblocks.com/images/block/block-1.svg"
className="w-8"
alt="logo"
/>
<span className="text-xl font-bold">
Latosa-Escrima
</span>
</div>
<div className="flex items-center">
<a
className={cn(
"text-muted-foreground",
navigationMenuTriggerStyle,
buttonVariants({
variant: "ghost",
}),
)}
href="#"
>
Home
</a>
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem className="text-muted-foreground">
<NavigationMenuTrigger>
<span>Products</span>
</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="w-80 p-3">
<NavigationMenuLink>
{subMenuItemsOne.map(
(item, idx) => (
<li key={idx}>
<a
className={cn(
"flex select-none gap-4 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
)}
href="#"
>
{item.icon}
<div>
<div className="text-sm font-semibold">
{
item.title
}
</div>
<p className="text-sm leading-snug text-muted-foreground">
{
item.description
}
</p>
</div>
</a>
</li>
),
)}
</NavigationMenuLink>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem className="text-muted-foreground">
<NavigationMenuTrigger>
Resources
</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="w-80 p-3">
<NavigationMenuLink>
{subMenuItemsTwo.map(
(item, idx) => (
<li key={idx}>
<a
className={cn(
"flex select-none gap-4 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
)}
href="#"
>
{item.icon}
<div>
<div className="text-sm font-semibold">
{
item.title
}
</div>
<p className="text-sm leading-snug text-muted-foreground">
{
item.description
}
</p>
</div>
</a>
</li>
),
)}
</NavigationMenuLink>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
<a
className={cn(
"text-muted-foreground",
navigationMenuTriggerStyle,
buttonVariants({
variant: "ghost",
}),
)}
href="#"
>
Pricing
</a>
<a
className={cn(
"text-muted-foreground",
navigationMenuTriggerStyle,
buttonVariants({
variant: "ghost",
}),
)}
href="#"
>
Blog
</a>
</div>
</div>
<div className="flex gap-2">
<Button variant="outline">Log in</Button>
<Button>Sign up</Button>
</div>
</nav>
<div className="block lg:hidden">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<img
src="https://shadcnblocks.com/images/block/block-1.svg"
className="w-8"
alt="logo"
/>
<span className="text-xl font-bold">
Shadcn Blocks
</span>
</div>
<Sheet>
<SheetTrigger asChild>
<Button variant="outline" size="icon">
<Menu className="size-4" />
</Button>
</SheetTrigger>
<SheetContent className="overflow-y-auto">
<SheetHeader>
<SheetTitle>
<div className="flex items-center gap-2">
<img
src="https://shadcnblocks.com/images/block/block-1.svg"
className="w-8"
alt="logo"
/>
<span className="text-xl font-bold">
Shadcn Blocks
</span>
</div>
</SheetTitle>
</SheetHeader>
<div className="mb-8 mt-8 flex flex-col gap-4">
<a href="#" className="font-semibold">
Home
</a>
<Accordion
type="single"
collapsible
className="w-full"
>
<AccordionItem
value="products"
className="border-b-0"
>
<AccordionTrigger className="mb-4 py-0 font-semibold hover:no-underline">
Products
</AccordionTrigger>
<AccordionContent className="mt-2">
{subMenuItemsOne.map(
(item, idx) => (
<a
key={idx}
className={cn(
"flex select-none gap-4 rounded-md p-3 leading-none outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
)}
href="#"
>
{item.icon}
<div>
<div className="text-sm font-semibold">
{item.title}
</div>
<p className="text-sm leading-snug text-muted-foreground">
{
item.description
}
</p>
</div>
</a>
),
)}
</AccordionContent>
</AccordionItem>
<AccordionItem
value="resources"
className="border-b-0"
>
<AccordionTrigger className="py-0 font-semibold hover:no-underline">
Resources
</AccordionTrigger>
<AccordionContent className="mt-2">
{subMenuItemsTwo.map(
(item, idx) => (
<a
key={idx}
className={cn(
"flex select-none gap-4 rounded-md p-3 leading-none outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
)}
href="#"
>
{item.icon}
<div>
<div className="text-sm font-semibold">
{item.title}
</div>
<p className="text-sm leading-snug text-muted-foreground">
{
item.description
}
</p>
</div>
</a>
),
)}
</AccordionContent>
</AccordionItem>
</Accordion>
<a href="#" className="font-semibold">
Pricing
</a>
<a href="#" className="font-semibold">
Blog
</a>
</div>
<div className="border-t pt-4">
<div className="grid grid-cols-2 justify-start">
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Press
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Contact
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Imprint
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Sitemap
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Legal
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Cookie Settings
</a>
</div>
<div className="mt-2 flex flex-col gap-3">
<Button variant="outline">
Log in
</Button>
<Button>Sign up</Button>
</div>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</div>
</section>
);
};
export default Navbar;

View File

@@ -0,0 +1,57 @@
"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.ComponentRef<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.ComponentRef<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 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
className,
)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ComponentRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm 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-md 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 shadow hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow 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,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.ComponentRef<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.ComponentRef<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-9 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.ComponentRef<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-300 group-data-[state=open]:rotate-180"
aria-hidden="true"
/>
</NavigationMenuPrimitive.Trigger>
));
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
const NavigationMenuContent = React.forwardRef<
React.ComponentRef<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.ComponentRef<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 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.ComponentRef<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

@@ -33,7 +33,7 @@ const SelectTrigger = React.forwardRef<
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectScrollUpButton = React.forwardRef< const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>, React.ComponentRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton> React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton <SelectPrimitive.ScrollUpButton
@@ -50,7 +50,7 @@ const SelectScrollUpButton = React.forwardRef<
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
const SelectScrollDownButton = React.forwardRef< const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>, React.ComponentRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton> React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton <SelectPrimitive.ScrollDownButton
@@ -68,7 +68,7 @@ SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName; SelectPrimitive.ScrollDownButton.displayName;
const SelectContent = React.forwardRef< const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>, React.ComponentRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => ( >(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal> <SelectPrimitive.Portal>
@@ -100,7 +100,7 @@ const SelectContent = React.forwardRef<
SelectContent.displayName = SelectPrimitive.Content.displayName; SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef< const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>, React.ComponentRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.Label <SelectPrimitive.Label
@@ -112,7 +112,7 @@ const SelectLabel = React.forwardRef<
SelectLabel.displayName = SelectPrimitive.Label.displayName; SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef< const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>, React.ComponentRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item <SelectPrimitive.Item
@@ -134,7 +134,7 @@ const SelectItem = React.forwardRef<
SelectItem.displayName = SelectPrimitive.Item.displayName; SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef< const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>, React.ComponentRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.Separator <SelectPrimitive.Separator

View File

@@ -0,0 +1,138 @@
"use client";
import * as React from "react";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";
const Sheet = SheetPrimitive.Root;
const SheetTrigger = SheetPrimitive.Trigger;
const SheetClose = SheetPrimitive.Close;
const SheetPortal = SheetPrimitive.Portal;
const SheetOverlay = React.forwardRef<
React.ComponentRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
ref={ref}
/>
));
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
{
variants: {
side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
},
);
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ComponentRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
{children}
</SheetPrimitive.Content>
</SheetPortal>
));
SheetContent.displayName = SheetPrimitive.Content.displayName;
const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className,
)}
{...props}
/>
);
SheetHeader.displayName = "SheetHeader";
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
);
SheetFooter.displayName = "SheetFooter";
const SheetTitle = React.forwardRef<
React.ComponentRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
));
SheetTitle.displayName = SheetPrimitive.Title.displayName;
const SheetDescription = React.forwardRef<
React.ComponentRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
SheetDescription.displayName = SheetPrimitive.Description.displayName;
export {
Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
};

View File

@@ -8,7 +8,10 @@
"name": "latosa-frontend", "name": "latosa-frontend",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@radix-ui/react-accordion": "^1.2.2",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-label": "^2.1.1", "@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-navigation-menu": "^1.2.3",
"@radix-ui/react-select": "^2.1.4", "@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-slot": "^1.1.1",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
@@ -923,6 +926,37 @@
"integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@radix-ui/react-accordion": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.2.tgz",
"integrity": "sha512-b1oh54x4DMCdGsB4/7ahiSrViXxaBwRPotiZNnYXjLha9vfuURSAZErki6qjDoSIV0eXx5v57XnTGVtGwnfp2g==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-collapsible": "1.1.2",
"@radix-ui/react-collection": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-arrow": { "node_modules/@radix-ui/react-arrow": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz",
@@ -946,6 +980,36 @@
} }
} }
}, },
"node_modules/@radix-ui/react-collapsible": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz",
"integrity": "sha512-PliMB63vxz7vggcyq0IxNYk8vGDrLXVWw4+W4B8YnwI1s18x7YZYqlG9PLX7XxAJUi0g2DxP4XKJMFHh/iVh9A==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-presence": "1.1.2",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-controllable-state": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection": { "node_modules/@radix-ui/react-collection": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz",
@@ -1002,6 +1066,42 @@
} }
} }
}, },
"node_modules/@radix-ui/react-dialog": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz",
"integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-dismissable-layer": "1.1.3",
"@radix-ui/react-focus-guards": "1.1.1",
"@radix-ui/react-focus-scope": "1.1.1",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-portal": "1.1.3",
"@radix-ui/react-presence": "1.1.2",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-use-controllable-state": "1.1.0",
"aria-hidden": "^1.1.1",
"react-remove-scroll": "^2.6.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-direction": { "node_modules/@radix-ui/react-direction": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
@@ -1125,6 +1225,42 @@
} }
} }
}, },
"node_modules/@radix-ui/react-navigation-menu": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.3.tgz",
"integrity": "sha512-IQWAsQ7dsLIYDrn0WqPU+cdM7MONTv9nqrLVYoie3BPiabSfUVDe6Fr+oEt0Cofsr9ONDcDe9xhmJbL1Uq1yKg==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-collection": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-dismissable-layer": "1.1.3",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-presence": "1.1.2",
"@radix-ui/react-primitive": "2.0.1",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0",
"@radix-ui/react-use-previous": "1.1.0",
"@radix-ui/react-visually-hidden": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popper": { "node_modules/@radix-ui/react-popper": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz",
@@ -1181,6 +1317,30 @@
} }
} }
}, },
"node_modules/@radix-ui/react-presence": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
"integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-primitive": { "node_modules/@radix-ui/react-primitive": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",

View File

@@ -9,7 +9,10 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-accordion": "^1.2.2",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-label": "^2.1.1", "@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-navigation-menu": "^1.2.3",
"@radix-ui/react-select": "^2.1.4", "@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-slot": "^1.1.1",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",

View File

@@ -56,6 +56,28 @@ export default {
md: "calc(var(--radius) - 2px)", md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)", sm: "calc(var(--radius) - 4px)",
}, },
keyframes: {
"accordion-down": {
from: {
height: "0",
},
to: {
height: "var(--radix-accordion-content-height)",
},
},
"accordion-up": {
from: {
height: "var(--radix-accordion-content-height)",
},
to: {
height: "0",
},
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
}, },
}, },
plugins: [require("tailwindcss-animate")], plugins: [require("tailwindcss-animate")],