Skip to content

Commit b7f1639

Browse files
committed
Improve Hero section
1 parent 91d6b3f commit b7f1639

12 files changed

Lines changed: 490 additions & 186 deletions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { render, screen } from '@testing-library/react'
2+
import Home from '../page'
3+
4+
describe('Home Page Avatar Requirements', () => {
5+
it('renders the avatar image in hero section', () => {
6+
render(<Home />)
7+
8+
const avatar = screen.getByRole('img', { name: /profile picture/i })
9+
expect(avatar).toBeInTheDocument()
10+
expect(avatar).toHaveAttribute('src')
11+
expect(avatar).toHaveClass('rounded-full')
12+
})
13+
14+
it('has proper avatar styling with border and size', () => {
15+
render(<Home />)
16+
17+
const avatar = screen.getByRole('img', { name: /profile picture/i })
18+
const avatarContainer = avatar.parentElement
19+
20+
expect(avatar).toHaveClass('border-4', 'border-accent', 'object-cover')
21+
expect(avatarContainer).toHaveClass('w-32', 'h-32', 'relative')
22+
})
23+
})
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { render, screen } from '@testing-library/react'
2+
import Home from '../page'
3+
4+
describe('Home Page Content Requirements', () => {
5+
it('renders the correct hero heading from portfolio specification', () => {
6+
render(<Home />)
7+
const heading = screen.getByRole('heading', { level: 1 })
8+
expect(heading).toHaveTextContent('Senior Full-Stack Developer & Problem Solver')
9+
expect(heading).toBeInTheDocument()
10+
})
11+
12+
it('renders the correct hero description from portfolio specification', () => {
13+
render(<Home />)
14+
const description = screen.getByText(/20\+ years crafting scalable web applications with React, Node\.js, and modern architectures/)
15+
expect(description).toBeInTheDocument()
16+
})
17+
18+
it('renders the location badge', () => {
19+
render(<Home />)
20+
const locationBadge = screen.getByText('Istanbul, Turkey • Remote Worldwide')
21+
expect(locationBadge).toBeInTheDocument()
22+
})
23+
24+
it('renders the View Projects CTA button', () => {
25+
render(<Home />)
26+
const viewProjectsButton = screen.getByRole('link', { name: /view projects/i })
27+
expect(viewProjectsButton).toBeInTheDocument()
28+
expect(viewProjectsButton).toHaveAttribute('href', '#projects')
29+
})
30+
31+
it('renders the Download CV CTA button', () => {
32+
render(<Home />)
33+
const downloadCvButton = screen.getByRole('link', { name: /download cv/i })
34+
expect(downloadCvButton).toBeInTheDocument()
35+
expect(downloadCvButton).toHaveAttribute('href', '/cv.pdf')
36+
})
37+
38+
it('renders the Contact Me CTA button', () => {
39+
render(<Home />)
40+
const contactButton = screen.getByRole('link', { name: /contact me/i })
41+
expect(contactButton).toBeInTheDocument()
42+
expect(contactButton).toHaveAttribute('href', '#contact')
43+
})
44+
45+
it('renders the theme toggle button', () => {
46+
render(<Home />)
47+
const themeToggle = screen.getByRole('button', { name: /switch to (light|dark) theme/i })
48+
expect(themeToggle).toBeInTheDocument()
49+
})
50+
51+
it('renders the scroll indicator', () => {
52+
render(<Home />)
53+
const scrollIndicator = screen.getByTestId('scroll-indicator')
54+
expect(scrollIndicator).toBeInTheDocument()
55+
})
56+
57+
describe('Theme Toggle Positioning', () => {
58+
it('has theme toggle positioned correctly in header', () => {
59+
render(<Home />)
60+
const header = screen.getByRole('banner')
61+
const themeToggle = screen.getByRole('button', { name: /switch to (light|dark) theme/i })
62+
63+
expect(header).toContainElement(themeToggle)
64+
expect(header).toHaveClass('fixed', 'top-0', 'right-0', 'z-50')
65+
})
66+
})
67+
})
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { render, screen } from '@testing-library/react'
2+
import Home from '../page'
3+
4+
describe('Home Page Layout Requirements', () => {
5+
it('has full-width hero section without width constraints', () => {
6+
render(<Home />)
7+
8+
const heroSection = screen.getByRole('heading', { level: 1 }).closest('section')
9+
expect(heroSection).toHaveClass('w-full')
10+
// Should not have max-width constraints that limit the section
11+
expect(heroSection).not.toHaveClass('max-w-7xl')
12+
expect(heroSection).not.toHaveClass('max-w-6xl')
13+
expect(heroSection).not.toHaveClass('max-w-5xl')
14+
})
15+
16+
it('has proper full viewport height', () => {
17+
render(<Home />)
18+
19+
const heroSection = screen.getByRole('heading', { level: 1 }).closest('section')
20+
expect(heroSection).toHaveClass('min-h-screen')
21+
})
22+
23+
it('has centered content container with reasonable max width', () => {
24+
render(<Home />)
25+
26+
const contentContainer = screen.getByRole('heading', { level: 1 }).closest('div')
27+
expect(contentContainer).toHaveClass('container', 'mx-auto', 'max-w-4xl', 'text-center')
28+
})
29+
})

src/app/__tests__/page.test.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,28 @@ import { render, screen } from '@testing-library/react'
22
import Home from '../page'
33

44
describe('Home Page', () => {
5-
it('renders UI Component Showcase heading', () => {
5+
it('renders the main hero heading', () => {
66
render(<Home />)
7-
const heading = screen.getByText('UI Component Showcase')
7+
const heading = screen.getByRole('heading', { level: 1 })
8+
expect(heading).toHaveTextContent('Senior Full-Stack Developer & Problem Solver')
89
expect(heading).toBeInTheDocument()
910
})
1011

11-
it('renders component sections', () => {
12+
it('renders the hero description', () => {
1213
render(<Home />)
13-
expect(screen.getByText('Badges')).toBeInTheDocument()
14-
expect(screen.getByText('Buttons')).toBeInTheDocument()
15-
expect(screen.getByText('Card Title')).toBeInTheDocument()
16-
expect(screen.getByText('Section Title')).toBeInTheDocument()
17-
expect(screen.getByText('Typography')).toBeInTheDocument()
14+
const description = screen.getByText(/20\+ years crafting scalable web applications with React, Node\.js, and modern architectures/)
15+
expect(description).toBeInTheDocument()
1816
})
1917

20-
it('renders footer links', () => {
18+
it('renders the theme toggle button', () => {
2119
render(<Home />)
22-
expect(screen.getByText('Learn')).toBeInTheDocument()
23-
expect(screen.getByText('Examples')).toBeInTheDocument()
24-
expect(screen.getByText('Go to nextjs.org →')).toBeInTheDocument()
20+
const themeToggle = screen.getByRole('button', { name: /switch to (light|dark) theme/i })
21+
expect(themeToggle).toBeInTheDocument()
2522
})
2623

27-
it('renders footer icons', () => {
24+
it('renders the scroll indicator', () => {
2825
render(<Home />)
29-
expect(screen.getByAltText('File icon')).toBeInTheDocument()
30-
expect(screen.getByAltText('Window icon')).toBeInTheDocument()
31-
expect(screen.getByAltText('Globe icon')).toBeInTheDocument()
26+
const scrollIndicator = screen.getByTestId('scroll-indicator')
27+
expect(scrollIndicator).toBeInTheDocument()
3228
})
3329
})

src/app/page.tsx

Lines changed: 20 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,34 @@
1-
import Image from "next/image";
2-
import {
3-
Badge,
4-
Button,
5-
Card,
6-
CardHeader,
7-
CardTitle,
8-
CardDescription,
9-
CardContent,
10-
CardFooter,
11-
Section,
12-
Heading,
13-
Text,
14-
Hero,
15-
} from "@/components/ui";
16-
import { ThemeToggle } from '../components/ui/ThemeToggle'
1+
import { HeroSection } from "@/components/sections";
2+
import { ThemeToggle } from '@/components/ui/ThemeToggle';
173

184
export default function Home() {
195
return (
206
<div className="min-h-screen bg-background text-text">
21-
<Hero
22-
title="Senior Full-Stack Developer"
23-
description="Building modern web applications with React, Next.js, and TypeScript. Passionate about creating beautiful, performant, and accessible user experiences."
24-
location="San Francisco, CA"
7+
{/* Header with theme toggle */}
8+
<header className="fixed top-0 right-0 z-50 p-4">
9+
<ThemeToggle />
10+
</header>
11+
12+
{/* Hero Section */}
13+
<HeroSection
14+
title="Senior Full-Stack Developer & Problem Solver"
15+
description="20+ years crafting scalable web applications with React, Node.js, and modern architectures"
16+
location="Istanbul, Turkey • Remote Worldwide"
2517
avatarSrc="/avatar.png"
2618
avatarAlt="Profile picture"
2719
ctaPrimary={{
28-
text: "Contact Me",
29-
link: "/contact",
20+
text: "View Projects",
21+
link: "#projects"
3022
}}
3123
ctaSecondary={{
32-
text: "View Work",
33-
link: "/work",
24+
text: "Download CV",
25+
link: "/cv.pdf"
26+
}}
27+
ctaTertiary={{
28+
text: "Contact Me",
29+
link: "#contact"
3430
}}
3531
/>
36-
37-
<Section variant="surface" spacing="lg" className="border-b border-accent/20">
38-
<div className="container mx-auto flex justify-between items-center">
39-
<Heading as="h1" size="h2" className="text-accent">UI Component Showcase</Heading>
40-
<ThemeToggle />
41-
</div>
42-
</Section>
43-
44-
<Section spacing="lg" maxWidth="4xl" align="center" className="container mx-auto">
45-
<div className="grid gap-8 md:grid-cols-2">
46-
<div className="space-y-4">
47-
<Heading as="h2" size="h3" className="text-accent">Buttons</Heading>
48-
<div className="flex flex-wrap gap-4">
49-
<Button>Default</Button>
50-
<Button variant="secondary">Secondary</Button>
51-
<Button variant="destructive">Destructive</Button>
52-
<Button variant="outline">Outline</Button>
53-
<Button variant="ghost">Ghost</Button>
54-
<Button variant="link">Link</Button>
55-
<Button isLoading>Loading</Button>
56-
</div>
57-
</div>
58-
59-
<div className="space-y-4">
60-
<Heading as="h2" size="h3" className="text-accent">Badges</Heading>
61-
<div className="flex flex-wrap gap-4">
62-
<Badge>Default</Badge>
63-
<Badge variant="secondary">Secondary</Badge>
64-
<Badge variant="outline">Outline</Badge>
65-
</div>
66-
</div>
67-
</div>
68-
69-
<div className="mt-12 grid gap-8 md:grid-cols-2">
70-
<Card className="bg-surface">
71-
<CardHeader>
72-
<CardTitle>Card Title</CardTitle>
73-
<CardDescription>Card description goes here.</CardDescription>
74-
</CardHeader>
75-
<CardContent>
76-
<Text>This is the card content area with some example text to demonstrate the theme integration.</Text>
77-
</CardContent>
78-
<CardFooter>
79-
<Button size="sm">Action</Button>
80-
</CardFooter>
81-
</Card>
82-
83-
<Section variant="accent" spacing="md" maxWidth="md" align="center" className="rounded-lg">
84-
<Heading as="h3" size="h4">Section Title</Heading>
85-
<Text>This is a section container with accent background and centered text.</Text>
86-
</Section>
87-
</div>
88-
89-
<div className="mt-12">
90-
<Heading as="h2" size="h3" className="text-accent mb-6">Typography</Heading>
91-
<div className="space-y-4">
92-
<Heading as="h1" size="h1">Heading 1</Heading>
93-
<Heading as="h2" size="h2">Heading 2</Heading>
94-
<Heading as="h3" size="h3">Heading 3</Heading>
95-
<Heading as="h4" size="h4">Heading 4</Heading>
96-
<Heading as="h5" size="h5">Heading 5</Heading>
97-
<Heading as="h6" size="h6">Heading 6</Heading>
98-
<Text size="xl">Body text xl</Text>
99-
<Text size="lg">Body text lg</Text>
100-
<Text size="base">Body text base</Text>
101-
<Text size="sm">Body text sm</Text>
102-
<Text size="xs">Body text xs</Text>
103-
<Text variant="muted">Muted text</Text>
104-
<Text variant="subtle">Subtle text</Text>
105-
<Text weight="bold">Bold text</Text>
106-
<Text weight="semibold">Semibold text</Text>
107-
<Text weight="medium">Medium text</Text>
108-
</div>
109-
</div>
110-
</Section>
111-
112-
<Section variant="surface" spacing="md" className="border-t border-accent/20">
113-
<div className="container mx-auto flex flex-wrap gap-6 items-center justify-center">
114-
<a
115-
className="flex items-center gap-2 hover:underline hover:underline-offset-4 text-accent"
116-
href="https://nextjs.org/learn"
117-
target="_blank"
118-
rel="noopener noreferrer"
119-
>
120-
<Image
121-
aria-hidden
122-
src="/file.svg"
123-
alt="File icon"
124-
width={16}
125-
height={16}
126-
/>
127-
Learn
128-
</a>
129-
<a
130-
className="flex items-center gap-2 hover:underline hover:underline-offset-4 text-accent"
131-
href="https://vercel.com/templates"
132-
target="_blank"
133-
rel="noopener noreferrer"
134-
>
135-
<Image
136-
aria-hidden
137-
src="/window.svg"
138-
alt="Window icon"
139-
width={16}
140-
height={16}
141-
/>
142-
Examples
143-
</a>
144-
<a
145-
className="flex items-center gap-2 hover:underline hover:underline-offset-4 text-accent"
146-
href="https://nextjs.org"
147-
target="_blank"
148-
rel="noopener noreferrer"
149-
>
150-
<Image
151-
aria-hidden
152-
src="/globe.svg"
153-
alt="Globe icon"
154-
width={16}
155-
height={16}
156-
/>
157-
Go to nextjs.org →
158-
</a>
159-
</div>
160-
</Section>
16132
</div>
16233
);
16334
}

0 commit comments

Comments
 (0)