mirror of
https://github.com/hex248/ob248.com.git
synced 2026-02-07 18:23:04 +00:00
tabs
This commit is contained in:
25
src/App.tsx
25
src/App.tsx
@@ -10,6 +10,7 @@ import { Link, Route, Routes, useNavigate, useParams } from "react-router-dom";
|
||||
import { AskAI } from "@/components/ask-ai";
|
||||
import { ProjectListItem } from "@/components/ProjectListItem";
|
||||
import { TimeSince } from "@/components/time-since";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { type ProjectEntry, projectList, projects } from "@/projects";
|
||||
import { ThemeToggle } from "./components/theme-toggle";
|
||||
|
||||
@@ -180,7 +181,9 @@ function Home() {
|
||||
Age: <TimeSince date={new Date(2004, 10, 4, 11, 47, 0)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full max-w-5xl grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<Tabs defaultValue="work" className="w-full max-w-5xl gap-0">
|
||||
<TabsContent value="work" className="-mb-[1.5px] p-2 border">
|
||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||
{visibleProjects.map((project, index) => (
|
||||
<ProjectListItem
|
||||
key={project.metadata.slug}
|
||||
@@ -191,6 +194,26 @@ function Home() {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="travel" className="-mb-[1.5px] p-2 border">
|
||||
test{" "}
|
||||
</TabsContent>
|
||||
<TabsList variant="line" className="h-auto w-full gap-0 p-0">
|
||||
<TabsTrigger
|
||||
value="work"
|
||||
className="border-border -mr-[1px] after:hidden data-[state=active]:text-accent"
|
||||
>
|
||||
Work
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value="travel"
|
||||
className="border-border after:hidden data-[state=active]:text-accent"
|
||||
>
|
||||
Travel
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="travel" className="pt-2" />
|
||||
</Tabs>
|
||||
<div className="w-full max-w-5xl grid grid-cols-1 md:grid-cols-[1fr_auto_1fr] items-center gap-3 md:gap-4">
|
||||
<div className="flex items-center gap-6">
|
||||
<AskAI name="me" inline />
|
||||
|
||||
102
src/components/ui/tabs.tsx
Normal file
102
src/components/ui/tabs.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { Tabs as TabsPrimitive } from "radix-ui";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Tabs({
|
||||
className,
|
||||
orientation = "horizontal",
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
||||
return (
|
||||
<TabsPrimitive.Root
|
||||
data-slot="tabs"
|
||||
data-orientation={orientation}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const tabsListVariants = cva(
|
||||
cn(
|
||||
"group-data-[orientation=horizontal]/tabs:h-9 group/tabs-list text-muted-foreground inline-flex",
|
||||
"w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
|
||||
),
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-muted",
|
||||
line: "gap-1 bg-transparent",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
function TabsList({
|
||||
className,
|
||||
variant = "default",
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.List> &
|
||||
VariantProps<typeof tabsListVariants>) {
|
||||
return (
|
||||
<TabsPrimitive.List
|
||||
data-slot="tabs-list"
|
||||
data-variant={variant}
|
||||
className={cn(tabsListVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function TabsTrigger({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
||||
return (
|
||||
<TabsPrimitive.Trigger
|
||||
data-slot="tabs-trigger"
|
||||
className={cn(
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring",
|
||||
"text-foreground/60 dark:text-muted-foreground data-[state=active]:text-accent",
|
||||
"relative inline-flex h-[calc(100%-1px)]",
|
||||
"flex-1 items-center justify-center border border-transparent",
|
||||
"px-2 py-1 text-sm font-medium whitespace-nowrap group-data-[orientation=vertical]/tabs:w-full",
|
||||
"group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px]",
|
||||
"focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50",
|
||||
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"data-[state=active]:bg-background dark:data-[state=active]:text-accent",
|
||||
"dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30",
|
||||
"data-[state=active]:text-accent after:bg-foreground after:absolute after:opacity-0",
|
||||
"group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px]",
|
||||
"group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0",
|
||||
"group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 cursor-pointer",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function TabsContent({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
||||
return (
|
||||
<TabsPrimitive.Content
|
||||
data-slot="tabs-content"
|
||||
className={cn("flex-1 outline-none", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
|
||||
Reference in New Issue
Block a user