Skip to content

Commit 05ab45f

Browse files
committed
feature: ひとまずの進捗
Add UI components and navigation structure Introduce reusable Avatar and Button components using Radix UI. Implement a Header component with navigation links for improved site structure. Enhance app layout and theming via Tailwind extension, and include new assets for visuals.
1 parent afabe52 commit 05ab45f

File tree

10 files changed

+300
-58
lines changed

10 files changed

+300
-58
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
},
1111
"dependencies": {
1212
"@kuma-ui/core": "^1.5.8",
13+
"@radix-ui/react-avatar": "^1.1.2",
14+
"@radix-ui/react-slot": "^1.1.1",
1315
"class-variance-authority": "^0.7.1",
1416
"clsx": "^2.1.1",
1517
"framer-motion": "^11.15.0",

public/images/name_plate.svg

Lines changed: 23 additions & 0 deletions
Loading

public/images/ryuzu.png

30.3 KB
Loading

src/app/about/page.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {Avatar, AvatarFallback, AvatarImage} from "@/components/ui/avatar";
2+
import Image from "next/image";
3+
4+
5+
export default function Page() {
6+
return (
7+
<div className="w-full flex flex-col items-center py-4 px-8 gap-16">
8+
<div className="flex w-full max-w-6xl">
9+
<h1 className="text-6xl font-black italic text-gray-700 text-6rem tracking-[1rem]">
10+
About
11+
</h1>
12+
</div>
13+
14+
<div className="w-full flex justify-center max-w-2xl">
15+
<div className="flex relative">
16+
<Image src="/images/ryuzu.png" alt="avatar" width={16} height={128} className="absolute left-0"/>
17+
<Avatar className="absolute right-0 w-128 h-128">
18+
<AvatarImage src="https://github.com/Y-RyuZU.png" alt="@shadcn" />
19+
<AvatarFallback>CN</AvatarFallback>
20+
</Avatar>
21+
</div>
22+
</div>
23+
</div>
24+
);
25+
}

src/app/layout.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {Metadata} from "next";
22
import {Geist, Geist_Mono} from "next/font/google";
33
import "./globals.css";
4+
import Header from "@/components/header";
45

56
const geistSans = Geist({
67
variable: "--font-geist-sans",
@@ -25,7 +26,10 @@ export default function RootLayout({children,}: Readonly<{
2526
<body
2627
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
2728
>
28-
{children}
29+
<Header />
30+
<main>
31+
{children}
32+
</main>
2933
</body>
3034
</html>
3135
);

src/components/header.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Link from "next/link";
2+
import {Button} from "@/components/ui/button";
3+
4+
const items = [
5+
{text: "Home", link: "/"},
6+
{text: "About", link: "/about"},
7+
{text: "Works", link: "/works"},
8+
{text: "Contact", link: "/contact"},
9+
]
10+
11+
export default function Header() {
12+
return (
13+
<header className="w-full py-4 px-8 bg-gray-100 dark:bg-gray-800 flex items-center shadow-md">
14+
<div className="flex justify-between mx-auto w-full max-w-screen-xl">
15+
<Button asChild>
16+
<Link href="/">
17+
Portfolio
18+
</Link>
19+
</Button>
20+
21+
<nav className="flex gap-6 text-sm sm:text-base">
22+
{items.map((item, index) => (
23+
<Button asChild key={index}>
24+
<Link href={item.text.toLowerCase()} className="hover:underline">
25+
{item.text}
26+
</Link>
27+
</Button>
28+
))}
29+
</nav>
30+
</div>
31+
</header>
32+
);
33+
}

src/components/ui/avatar.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as AvatarPrimitive from "@radix-ui/react-avatar"
5+
6+
import { cn } from "@/lib/utils"
7+
8+
const Avatar = React.forwardRef<
9+
React.ElementRef<typeof AvatarPrimitive.Root>,
10+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11+
>(({ className, ...props }, ref) => (
12+
<AvatarPrimitive.Root
13+
ref={ref}
14+
className={cn(
15+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
16+
className
17+
)}
18+
{...props}
19+
/>
20+
))
21+
Avatar.displayName = AvatarPrimitive.Root.displayName
22+
23+
const AvatarImage = React.forwardRef<
24+
React.ElementRef<typeof AvatarPrimitive.Image>,
25+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
26+
>(({ className, ...props }, ref) => (
27+
<AvatarPrimitive.Image
28+
ref={ref}
29+
className={cn("aspect-square h-full w-full", className)}
30+
{...props}
31+
/>
32+
))
33+
AvatarImage.displayName = AvatarPrimitive.Image.displayName
34+
35+
const AvatarFallback = React.forwardRef<
36+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
37+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
38+
>(({ className, ...props }, ref) => (
39+
<AvatarPrimitive.Fallback
40+
ref={ref}
41+
className={cn(
42+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
43+
className
44+
)}
45+
{...props}
46+
/>
47+
))
48+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49+
50+
export { Avatar, AvatarImage, AvatarFallback }

src/components/ui/button.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9+
{
10+
variants: {
11+
variant: {
12+
default:
13+
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
14+
destructive:
15+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
16+
outline:
17+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
18+
secondary:
19+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
20+
ghost: "hover:bg-accent hover:text-accent-foreground",
21+
link: "text-primary underline-offset-4 hover:underline",
22+
},
23+
size: {
24+
default: "h-9 px-4 py-2",
25+
sm: "h-8 rounded-md px-3 text-xs",
26+
lg: "h-10 rounded-md px-8",
27+
icon: "h-9 w-9",
28+
},
29+
},
30+
defaultVariants: {
31+
variant: "default",
32+
size: "default",
33+
},
34+
}
35+
)
36+
37+
export interface ButtonProps
38+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39+
VariantProps<typeof buttonVariants> {
40+
asChild?: boolean
41+
}
42+
43+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
44+
({ className, variant, size, asChild = false, ...props }, ref) => {
45+
const Comp = asChild ? Slot : "button"
46+
return (
47+
<Comp
48+
className={cn(buttonVariants({ variant, size, className }))}
49+
ref={ref}
50+
{...props}
51+
/>
52+
)
53+
}
54+
)
55+
Button.displayName = "Button"
56+
57+
export { Button, buttonVariants }

tailwind.config.ts

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,66 @@
1-
import type { Config } from "tailwindcss";
1+
import type {Config} from "tailwindcss";
2+
import tailwindcssAnimate from "tailwindcss-animate";
23

34
export default {
45
darkMode: ["class"],
56
content: [
6-
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
7-
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
8-
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
9-
],
10-
theme: {
11-
extend: {
12-
colors: {
13-
background: 'hsl(var(--background))',
14-
foreground: 'hsl(var(--foreground))',
15-
card: {
16-
DEFAULT: 'hsl(var(--card))',
17-
foreground: 'hsl(var(--card-foreground))'
18-
},
19-
popover: {
20-
DEFAULT: 'hsl(var(--popover))',
21-
foreground: 'hsl(var(--popover-foreground))'
22-
},
23-
primary: {
24-
DEFAULT: 'hsl(var(--primary))',
25-
foreground: 'hsl(var(--primary-foreground))'
26-
},
27-
secondary: {
28-
DEFAULT: 'hsl(var(--secondary))',
29-
foreground: 'hsl(var(--secondary-foreground))'
30-
},
31-
muted: {
32-
DEFAULT: 'hsl(var(--muted))',
33-
foreground: 'hsl(var(--muted-foreground))'
34-
},
35-
accent: {
36-
DEFAULT: 'hsl(var(--accent))',
37-
foreground: 'hsl(var(--accent-foreground))'
38-
},
39-
destructive: {
40-
DEFAULT: 'hsl(var(--destructive))',
41-
foreground: 'hsl(var(--destructive-foreground))'
42-
},
43-
border: 'hsl(var(--border))',
44-
input: 'hsl(var(--input))',
45-
ring: 'hsl(var(--ring))',
46-
chart: {
47-
'1': 'hsl(var(--chart-1))',
48-
'2': 'hsl(var(--chart-2))',
49-
'3': 'hsl(var(--chart-3))',
50-
'4': 'hsl(var(--chart-4))',
51-
'5': 'hsl(var(--chart-5))'
52-
}
53-
},
54-
borderRadius: {
55-
lg: 'var(--radius)',
56-
md: 'calc(var(--radius) - 2px)',
57-
sm: 'calc(var(--radius) - 4px)'
58-
}
59-
}
60-
},
61-
plugins: [require("tailwindcss-animate")],
7+
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
8+
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
9+
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
10+
],
11+
theme: {
12+
extend: {
13+
fontFamily: {
14+
15+
},
16+
colors: {
17+
background: 'hsl(var(--background))',
18+
foreground: 'hsl(var(--foreground))',
19+
card: {
20+
DEFAULT: 'hsl(var(--card))',
21+
foreground: 'hsl(var(--card-foreground))'
22+
},
23+
popover: {
24+
DEFAULT: 'hsl(var(--popover))',
25+
foreground: 'hsl(var(--popover-foreground))'
26+
},
27+
primary: {
28+
DEFAULT: 'hsl(var(--primary))',
29+
foreground: 'hsl(var(--primary-foreground))'
30+
},
31+
secondary: {
32+
DEFAULT: 'hsl(var(--secondary))',
33+
foreground: 'hsl(var(--secondary-foreground))'
34+
},
35+
muted: {
36+
DEFAULT: 'hsl(var(--muted))',
37+
foreground: 'hsl(var(--muted-foreground))'
38+
},
39+
accent: {
40+
DEFAULT: 'hsl(var(--accent))',
41+
foreground: 'hsl(var(--accent-foreground))'
42+
},
43+
destructive: {
44+
DEFAULT: 'hsl(var(--destructive))',
45+
foreground: 'hsl(var(--destructive-foreground))'
46+
},
47+
border: 'hsl(var(--border))',
48+
input: 'hsl(var(--input))',
49+
ring: 'hsl(var(--ring))',
50+
chart: {
51+
'1': 'hsl(var(--chart-1))',
52+
'2': 'hsl(var(--chart-2))',
53+
'3': 'hsl(var(--chart-3))',
54+
'4': 'hsl(var(--chart-4))',
55+
'5': 'hsl(var(--chart-5))'
56+
}
57+
},
58+
borderRadius: {
59+
lg: 'var(--radius)',
60+
md: 'calc(var(--radius) - 2px)',
61+
sm: 'calc(var(--radius) - 4px)'
62+
}
63+
}
64+
},
65+
plugins: [tailwindcssAnimate],
6266
} satisfies Config;

yarn.lock

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,50 @@
13911391
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
13921392
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
13931393

1394+
"@radix-ui/react-avatar@^1.1.2":
1395+
version "1.1.2"
1396+
resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.1.2.tgz#24af4c66bb5271460a4a6b74c4f4f9d4789d3d90"
1397+
integrity sha512-GaC7bXQZ5VgZvVvsJ5mu/AEbjYLnhhkoidOboC50Z6FFlLA03wG2ianUoH+zgDQ31/9gCF59bE4+2bBgTyMiig==
1398+
dependencies:
1399+
"@radix-ui/react-context" "1.1.1"
1400+
"@radix-ui/react-primitive" "2.0.1"
1401+
"@radix-ui/react-use-callback-ref" "1.1.0"
1402+
"@radix-ui/react-use-layout-effect" "1.1.0"
1403+
1404+
"@radix-ui/[email protected]":
1405+
version "1.1.1"
1406+
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec"
1407+
integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==
1408+
1409+
"@radix-ui/[email protected]":
1410+
version "1.1.1"
1411+
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a"
1412+
integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
1413+
1414+
"@radix-ui/[email protected]":
1415+
version "2.0.1"
1416+
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz#6d9efc550f7520135366f333d1e820cf225fad9e"
1417+
integrity sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==
1418+
dependencies:
1419+
"@radix-ui/react-slot" "1.1.1"
1420+
1421+
"@radix-ui/[email protected]", "@radix-ui/react-slot@^1.1.1":
1422+
version "1.1.1"
1423+
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.1.tgz#ab9a0ffae4027db7dc2af503c223c978706affc3"
1424+
integrity sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==
1425+
dependencies:
1426+
"@radix-ui/react-compose-refs" "1.1.1"
1427+
1428+
"@radix-ui/[email protected]":
1429+
version "1.1.0"
1430+
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1"
1431+
integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==
1432+
1433+
"@radix-ui/[email protected]":
1434+
version "1.1.0"
1435+
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27"
1436+
integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==
1437+
13941438
"@rtsao/scc@^1.1.0":
13951439
version "1.1.0"
13961440
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"

0 commit comments

Comments
 (0)