diff --git a/app/selects/page.tsx b/app/selects/page.tsx index 00c59fa..09d3f7e 100644 --- a/app/selects/page.tsx +++ b/app/selects/page.tsx @@ -4,91 +4,91 @@ import PageHeader from "@/demo/page-header"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "Select Components - Origin UI", - description: - "A collection of beautiful and accessible select components built with Tailwind CSS and Next.js.", + title: "Select Components - Origin UI", + description: + "A collection of beautiful and accessible select components built with Tailwind CSS and Next.js.", }; const directory = "selects"; const files = [ - "select-01", - "select-02", - "select-03", - "select-04", - "select-05", - "select-06", - "select-07", - "select-08", - "select-09", - "select-10", - "select-11", - "select-12", - "select-13", - "select-14", - "select-15", - "select-16", - "select-17", - "select-18", - "select-19", - "select-20", - "select-21", - "select-22", - "select-23", - "select-24", - "select-25", - "select-26", - "select-27", - "select-28", - "select-29", - "select-30", - "select-31", - "select-32", - "select-33", - "select-34", - "select-35", - "select-36", - "select-37", - "select-38", - "select-39", - "select-40", - "select-41", - "select-42", - "select-43", - "select-44", - "select-45", - "select-46", - "select-47", - "select-48", - "select-49", - "select-50", - "select-51", + "select-01", + "select-02", + "select-03", + "select-04", + "select-05", + "select-06", + "select-07", + "select-08", + "select-09", + "select-10", + "select-11", + "select-12", + "select-13", + "select-14", + "select-15", + "select-16", + "select-17", + "select-18", + "select-19", + "select-20", + "select-21", + "select-22", + "select-23", + "select-24", + "select-25", + "select-26", + "select-27", + "select-28", + "select-29", + "select-30", + "select-31", + "select-32", + "select-33", + "select-34", + "select-35", + "select-36", + "select-37", + "select-38", + "select-39", + "select-40", + "select-41", + "select-42", + "select-43", + "select-44", + "select-45", + "select-46", + "select-47", + "select-48", + "select-49", + "select-50", + "select-51", ]; export default function Page() { - return ( -
-
-
- - A growing collection of {files.length} select components built with Next.js and - TailwindCSS. - + return ( +
+
+
+ + A growing collection of {files.length} select components built with + Next.js and TailwindCSS. + -
- {files.map((componentName) => { - return ( - - ); - })} -
+
+ {files.map((componentName) => { + return ( + + ); + })} +
- -
-
-
- ); + +
+
+
+ ); } diff --git a/demo/card-component.tsx b/demo/card-component.tsx new file mode 100644 index 0000000..fbbcead --- /dev/null +++ b/demo/card-component.tsx @@ -0,0 +1,59 @@ +"use client"; +import { cn } from "@/lib/utils"; +import LinkButton from "./link-button"; +import CopyButton from "./copy-button"; +import { useEffect, useRef } from "react"; +import { useState } from "react"; +import NameComponent from "./name-component"; + +const CardComponent = ({ + componentName, + directory, + className, + children, + source, +}: { + componentName: string; + directory: string; + className?: string; + children: React.ReactNode; + source: string; +}) => { + const ref = useRef(null); + const [selected, setSelected] = useState(false); + + useEffect(() => { + const isSelected = + typeof window !== "undefined" && + window.location.hash === `#${componentName}`; + + if (isSelected) { + setTimeout(() => { + window.scrollTo({ + top: (ref.current?.offsetTop || 0) - window.innerHeight / 2 + 160, + behavior: "smooth", + }); + setSelected(isSelected); + }, 300); + } + }, [componentName]); + + return ( +
+ {children} + + + +
+ ); +}; + +export default CardComponent; diff --git a/demo/copy-button.tsx b/demo/copy-button.tsx index 92b0160..f9640d3 100644 --- a/demo/copy-button.tsx +++ b/demo/copy-button.tsx @@ -1,87 +1,78 @@ "use client"; import { Button } from "@/components/ui/button"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; +import { Check, Code, Copy } from "lucide-react"; import { useState } from "react"; const CopyButton = ({ componentSource }: { componentSource: string }) => { - const [copied, setCopied] = useState(false); + const [copied, setCopied] = useState(false); - const handleCopy = async () => { - try { - await navigator.clipboard.writeText(componentSource); - setCopied(true); - setTimeout(() => setCopied(false), 1500); - } catch (err) { - console.error("Failed to copy text: ", err); - } - }; + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(componentSource); + setCopied(true); + setTimeout(() => setCopied(false), 1500); + } catch (err) { + console.error("Failed to copy text: ", err); + } + }; - return ( -
- - - - - - - Copy - - - -
- ); + return ( +
+ + + + + + + Copy Code + + + +
+ ); }; export default CopyButton; diff --git a/demo/demo-component.tsx b/demo/demo-component.tsx index 85ec640..bc764af 100644 --- a/demo/demo-component.tsx +++ b/demo/demo-component.tsx @@ -1,23 +1,28 @@ -import { cn } from "@/lib/utils"; -import CopyButton from "./copy-button"; import { readComponentSource } from "./read-component-source"; +import CardComponent from "./card-component"; export default async function DemoComponent({ - directory, - componentName, - className, + directory, + componentName, + className, }: { - directory: string; - componentName: string; - className?: string; + directory: string; + componentName: string; + className?: string; }) { - const Component = (await import(`@/components/${directory}/${componentName}`)).default; - const source = await readComponentSource(directory, componentName); + // get anchor from url + const Component = (await import(`@/components/${directory}/${componentName}`)) + .default; + const source = await readComponentSource(directory, componentName); - return ( -
- - -
- ); + return ( + + + + ); } diff --git a/demo/link-button.tsx b/demo/link-button.tsx new file mode 100644 index 0000000..c57fb49 --- /dev/null +++ b/demo/link-button.tsx @@ -0,0 +1,86 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; +import { useState } from "react"; +import { Check, Link2 } from "lucide-react"; + +interface ShareButtonProps { + componentName: string; + directory: string; +} + +const ShareButton = ({ componentName, directory }: ShareButtonProps) => { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + try { + const url = + typeof window !== "undefined" && + `${window.location.origin}/${directory}#${componentName}`; + await navigator.clipboard.writeText(url || ""); + setCopied(true); + setTimeout(() => setCopied(false), 1500); + } catch (err) { + console.error("Failed to copy link: ", err); + } + }; + + return ( +
+ + + + + + + Copy Link + + + +
+ ); +}; + +export default ShareButton; diff --git a/demo/name-component.tsx b/demo/name-component.tsx new file mode 100644 index 0000000..44b7b03 --- /dev/null +++ b/demo/name-component.tsx @@ -0,0 +1,21 @@ +import { cn } from "@/lib/utils"; + +interface NameComponentProps { + componentName: string; + isSelected: boolean; +} + +const NameComponent = ({ componentName, isSelected }: NameComponentProps) => { + return ( +
+ {componentName} +
+ ); +}; + +export default NameComponent;