From 82251d527291dcba92ec6116b28f42212475f025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyril=20=C5=A0ebek?= Date: Mon, 15 Apr 2024 16:37:54 +0200 Subject: [PATCH] idk, working on showcase XD --- package.json | 3 + pnpm-lock.yaml | 97 +++++++++------- src/components/Showcase.astro | 11 ++ src/components/ShowcaseTabs.jsx | 93 ++++++++++++++++ src/components/ui/button.jsx | 4 +- src/components/ui/card.jsx | 50 +++++++++ src/components/ui/carousel.jsx | 189 ++++++++++++++++++++++++++++++++ src/components/ui/tabs.jsx | 41 +++++++ src/pages/[lang]/index.astro | 4 +- 9 files changed, 448 insertions(+), 44 deletions(-) create mode 100644 src/components/Showcase.astro create mode 100644 src/components/ShowcaseTabs.jsx create mode 100644 src/components/ui/card.jsx create mode 100644 src/components/ui/carousel.jsx create mode 100644 src/components/ui/tabs.jsx diff --git a/package.json b/package.json index e20569b..c970049 100644 --- a/package.json +++ b/package.json @@ -17,12 +17,15 @@ "@astrojs/sitemap": "^3.1.1", "@astrojs/tailwind": "^5.1.0", "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.0.4", "@types/react": "^18.2.74", "@types/react-dom": "^18.2.24", "astro": "^4.5.6", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "cmdk": "^1.0.0", + "embla-carousel-react": "^8.0.2", "lucide-react": "^0.365.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b94c25d..29e7a38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,18 +23,15 @@ dependencies: '@astrojs/tailwind': specifier: ^5.1.0 version: 5.1.0(astro@4.5.6)(tailwindcss@3.4.1) - '@radix-ui/react-dialog': - specifier: ^1.0.5 - version: 1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 version: 2.0.6(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-popover': - specifier: ^1.0.7 - version: 1.0.7(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-tabs': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@types/react': specifier: ^18.2.74 version: 18.2.74 @@ -53,6 +50,9 @@ dependencies: cmdk: specifier: ^1.0.0 version: 1.0.0(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + embla-carousel-react: + specifier: ^8.0.2 + version: 8.0.2(react@18.2.0) lucide-react: specifier: ^0.365.0 version: 0.365.0(react@18.2.0) @@ -1116,41 +1116,6 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.74)(react@18.2.0) dev: false - /@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@types/react': 18.2.74 - '@types/react-dom': 18.2.24 - aria-hidden: 1.2.4 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.74)(react@18.2.0) - dev: false - /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} peerDependencies: @@ -1289,6 +1254,34 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-tabs@1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-egZfYY/+wRNCflXNHx+dePvnz9FbmssDTJBtgRfDY7e8SE5oIo3Py2eCB1ckAbh1Q7cQ/6yJZThJ++sgbxibog==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.74)(react@18.2.0): resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} peerDependencies: @@ -2284,6 +2277,28 @@ packages: resolution: {integrity: sha512-w+9yAVHoHhysCa+gln7AzbO9CdjFcL/wN/5dd+XW/Msl2d/4+WisEaCF1nty0xbAKaxdaJfgLB2296U7zZB7BA==} dev: false + /embla-carousel-react@8.0.2(react@18.2.0): + resolution: {integrity: sha512-RHe1GKLulOW8EDN+cJgbFbVVfRXcaLT2/89dyVw3ONGgVpZjD19wB87I1LUZ1aCzOSrTccx0PFSQanK4OOfGPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.1 || ^18.0.0 + dependencies: + embla-carousel: 8.0.2 + embla-carousel-reactive-utils: 8.0.2(embla-carousel@8.0.2) + react: 18.2.0 + dev: false + + /embla-carousel-reactive-utils@8.0.2(embla-carousel@8.0.2): + resolution: {integrity: sha512-nLZqDkQdO0hvOP49/dUwjkkepMnUXgIzhyRuDjwGqswpB4Ibnc5M+w7rSQQAM+uMj0cPaXnYOTlv8XD7I/zVNw==} + peerDependencies: + embla-carousel: 8.0.2 + dependencies: + embla-carousel: 8.0.2 + dev: false + + /embla-carousel@8.0.2: + resolution: {integrity: sha512-bogsDO8xosuh/l3PxIvA5AMl3+BnRVAse9sDW/60amzj4MbGS5re4WH5eVEXiuH8G1/3G7QUAX2QNr3Yx8z5rA==} + dev: false + /emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} dev: false diff --git a/src/components/Showcase.astro b/src/components/Showcase.astro new file mode 100644 index 0000000..075f0dd --- /dev/null +++ b/src/components/Showcase.astro @@ -0,0 +1,11 @@ +--- +import SinglePage from "../layouts/SinglePage.astro"; +import { ShowcaseTabs } from "./ShowcaseTabs.jsx"; + +import { dictionary } from "../i18n/dictionary"; +const { title, description } = dictionary[Astro.currentLocale]; +--- + + + + diff --git a/src/components/ShowcaseTabs.jsx b/src/components/ShowcaseTabs.jsx new file mode 100644 index 0000000..6d81e5b --- /dev/null +++ b/src/components/ShowcaseTabs.jsx @@ -0,0 +1,93 @@ +import { Button } from "../components/ui/button" +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "../components/ui/card" +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "../components/ui/tabs" +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "../components/ui/carousel" + +const data = [{ + value: "thisPage", + handle: "1", + title: "This Page", + description: "random text", + images: [{ src: "temp.jpg", alt: "text" }, { src: "temp.jpg", alt: "text2" }] +}, { + value: "thatPage", + title: "That Page", + handle: "2", + description: "random text", + images: [{ src: "temp.jpg", alt: "text" }, { src: "temp.jpg", alt: "text2" }] +}, { + value: "otherPge", + title: "Other Page", + handle: "3", + description: "random text", + images: [{ src: "temp.jpg", alt: "text" }, { src: "temp.jpg", alt: "text2" }] +}]; + +export function ShowcaseTabs() { + return ( + + + {data.map((item) => ( + + + + {item.title} + + {item.description} + + + + + + {item.images.map((image, index) => ( + + + + {image.alt} + + + + ))} + +
+
+ +
+
+ +
+
+
+
+
+
+ )) + } + + + {data.map((item) => ( + {item.handle} + ))} + + +
+ ) +} diff --git a/src/components/ui/button.jsx b/src/components/ui/button.jsx index 8812097..f93eb30 100644 --- a/src/components/ui/button.jsx +++ b/src/components/ui/button.jsx @@ -5,7 +5,7 @@ import { cva } from "class-variance-authority"; import { cn } from "../../lib/utils" const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + "inline-flex items-center justify-center 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", { variants: { variant: { @@ -13,7 +13,7 @@ const buttonVariants = cva( destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: - "border border-input bg-background hover:bg-primary hover:text-accent-foreground", + "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", diff --git a/src/components/ui/card.jsx b/src/components/ui/card.jsx new file mode 100644 index 0000000..525788c --- /dev/null +++ b/src/components/ui/card.jsx @@ -0,0 +1,50 @@ +import * as React from "react" + +import { cn } from "../../lib/utils" + +const Card = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/carousel.jsx b/src/components/ui/carousel.jsx new file mode 100644 index 0000000..8f0b8a5 --- /dev/null +++ b/src/components/ui/carousel.jsx @@ -0,0 +1,189 @@ +import * as React from "react" +import useEmblaCarousel from "embla-carousel-react"; +import { ArrowLeft, ArrowRight } from "lucide-react" + +import { cn } from "../../lib/utils" +import { Button } from "../../components/ui/button" + +const CarouselContext = React.createContext(null) + +function useCarousel() { + const context = React.useContext(CarouselContext) + + if (!context) { + throw new Error("useCarousel must be used within a ") + } + + return context +} + +const Carousel = React.forwardRef(( + { + orientation = "horizontal", + opts, + setApi, + plugins, + className, + children, + ...props + }, + ref +) => { + const [carouselRef, api] = useEmblaCarousel({ + ...opts, + axis: orientation === "horizontal" ? "x" : "y", + }, plugins) + const [canScrollPrev, setCanScrollPrev] = React.useState(false) + const [canScrollNext, setCanScrollNext] = React.useState(false) + + const onSelect = React.useCallback((api) => { + if (!api) { + return + } + + setCanScrollPrev(api.canScrollPrev()) + setCanScrollNext(api.canScrollNext()) + }, []) + + const scrollPrev = React.useCallback(() => { + api?.scrollPrev() + }, [api]) + + const scrollNext = React.useCallback(() => { + api?.scrollNext() + }, [api]) + + const handleKeyDown = React.useCallback((event) => { + if (event.key === "ArrowLeft") { + event.preventDefault() + scrollPrev() + } else if (event.key === "ArrowRight") { + event.preventDefault() + scrollNext() + } + }, [scrollPrev, scrollNext]) + + React.useEffect(() => { + if (!api || !setApi) { + return + } + + setApi(api) + }, [api, setApi]) + + React.useEffect(() => { + if (!api) { + return + } + + onSelect(api) + api.on("reInit", onSelect) + api.on("select", onSelect) + + return () => { + api?.off("select", onSelect) + }; + }, [api, onSelect]) + + return ( + ( +
+ {children} +
+
) + ); +}) +Carousel.displayName = "Carousel" + +const CarouselContent = React.forwardRef(({ className, ...props }, ref) => { + const { carouselRef, orientation } = useCarousel() + + return ( + (
+
+
) + ); +}) +CarouselContent.displayName = "CarouselContent" + +const CarouselItem = React.forwardRef(({ className, ...props }, ref) => { + const { orientation } = useCarousel() + + return ( + (
) + ); +}) +CarouselItem.displayName = "CarouselItem" + +const CarouselPrevious = React.forwardRef(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollPrev, canScrollPrev } = useCarousel() + + return ( + () + ); +}) +CarouselPrevious.displayName = "CarouselPrevious" + +const CarouselNext = React.forwardRef(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + () + ); +}) +CarouselNext.displayName = "CarouselNext" + +export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }; diff --git a/src/components/ui/tabs.jsx b/src/components/ui/tabs.jsx new file mode 100644 index 0000000..1c40487 --- /dev/null +++ b/src/components/ui/tabs.jsx @@ -0,0 +1,41 @@ +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "../../lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/src/pages/[lang]/index.astro b/src/pages/[lang]/index.astro index 392b474..fa28769 100644 --- a/src/pages/[lang]/index.astro +++ b/src/pages/[lang]/index.astro @@ -2,9 +2,11 @@ import MainLayout from "../../layouts/MainLayout.astro"; import Hero from "../../components/Hero.astro"; import About from "../../components/About.astro"; +import Showcase from "../../components/Showcase.astro"; //@ts-ignore import { dictionary } from "../../i18n/dictionary"; + const { title, description } = dictionary[Astro.currentLocale]; export async function getStaticPaths() { @@ -16,5 +18,5 @@ export async function getStaticPaths() { - + \ No newline at end of file