Skip to content

Commit c2f8d4e

Browse files
committed
chore: Enhanced layout and styling across components
1 parent b30460b commit c2f8d4e

File tree

18 files changed

+360
-247
lines changed

18 files changed

+360
-247
lines changed

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ yarn-error.log*
3535
.turbo
3636

3737
# Skills
38-
# .agents/skills/
39-
# .cursor/skills/
40-
# .github/skills/
38+
.agents/skills/
39+
.cursor/skills/
40+
.github/skills/

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
## [Unreleased]
44

5+
## [0.10.0] - 2026-01-25
6+
7+
### Added
8+
- Header component with logo, navigation links, and sticky positioning
9+
- SkillCardHeader component for improved skill card organization
10+
- Logo image (qae-skills.png) for branding
11+
12+
### Changed
13+
- Refactored homepage layout with improved typography and spacing
14+
- Enhanced changelog page styling and layout
15+
- Updated README with logo display and bunx installation command
16+
- Improved responsive design and component organization
17+
- Updated .gitignore to include skills directories
18+
19+
### Removed
20+
- ThemeToggle component (consolidated into header)
21+
522
## [0.9.0] - 2026-01-25
623

724
### Added

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
# qa-skills
1+
<div align="center">
2+
<img src="apps/web/public/qae-skills.png" alt="QAE Skills Icon" width="25%" />
3+
</div>
4+
5+
# QA Engineering Skills
26

37
QA Engineering process and best-practice skills for engineering teams.
48
https://skills.sh/Hiccup-za/qa-skills
59

610
## Installation
711

812
```sh
9-
npx skills add Hiccup-za/qa-skills
13+
bunx skills add Hiccup-za/qa-skills
1014
```
1115

1216
## Skills

apps/web/app/changelog/page.tsx

Lines changed: 81 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -59,75 +59,87 @@ export default async function ChangelogPage() {
5959
};
6060

6161
return (
62-
<main className="px-6 py-12">
63-
<div className="mx-auto flex max-w-3xl flex-col gap-6">
64-
<div className="sticky top-0 z-10 flex flex-wrap items-center gap-3 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 py-4 -mx-6 px-6">
65-
<Button asChild variant="ghost" size="sm">
66-
<Link href="/">
67-
<ArrowLeft className="h-4 w-4" />
68-
</Link>
69-
</Button>
70-
<h1 className="text-2xl font-semibold tracking-tight">Changelog</h1>
71-
</div>
72-
<div className="grid gap-6">
73-
{sections
74-
.map((section, index) => ({
75-
...section,
76-
index,
77-
date: section.title.match(/-\s*(\d{4}-\d{2}-\d{2})\s*$/)?.[1],
78-
}))
79-
.filter((section) => section.title.toLowerCase() !== "[unreleased]")
80-
.sort((a, b) => {
81-
if (a.date && b.date) {
82-
return b.date.localeCompare(a.date);
83-
}
84-
if (a.date) {
85-
return -1;
86-
}
87-
if (b.date) {
88-
return 1;
89-
}
90-
return b.index - a.index;
91-
})
92-
.map((section) => {
93-
const content = markdownContent(section.body);
94-
// Only render sections that have content
95-
if (!content.trim()) {
96-
return null;
97-
}
98-
return (
99-
<Card key={section.title}>
100-
<CardHeader>
101-
<CardTitle>{section.title}</CardTitle>
102-
</CardHeader>
103-
<CardContent>
104-
<div className="prose prose-sm dark:prose-invert max-w-none [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:bg-muted [&_code]:text-foreground [&_code]:text-xs [&_code]:font-mono [&_pre]:hidden">
105-
<ReactMarkdown
106-
remarkPlugins={[remarkGfm]}
107-
components={{
108-
h3: ({ children }) => (
109-
<h3 className="text-base font-semibold mt-4 mb-2 first:mt-0">{children}</h3>
110-
),
111-
ul: ({ children }) => (
112-
<ul className="list-disc pl-5 space-y-1 my-2">{children}</ul>
113-
),
114-
li: ({ children }) => (
115-
<li className="text-sm text-foreground">{children}</li>
116-
),
117-
p: ({ children }) => (
118-
<p className="text-sm text-foreground my-2">{children}</p>
119-
),
120-
pre: () => null,
121-
}}
122-
>
123-
{content}
124-
</ReactMarkdown>
125-
</div>
126-
</CardContent>
127-
</Card>
128-
);
129-
})
130-
.filter(Boolean)}
62+
<main className="min-h-screen">
63+
<div className="px-6 py-12">
64+
<div className="mx-auto flex max-w-3xl flex-col gap-6">
65+
<div className="flex flex-wrap items-center gap-3">
66+
<Button
67+
asChild
68+
variant="ghost"
69+
size="sm"
70+
>
71+
<Link href="/">
72+
<ArrowLeft className="h-4 w-4" />
73+
</Link>
74+
</Button>
75+
<h1 className="text-3xl font-semibold tracking-tight">
76+
Changelog
77+
</h1>
78+
</div>
79+
<div className="grid gap-6">
80+
{sections
81+
.map((section, index) => ({
82+
...section,
83+
index,
84+
date: section.title.match(/-\s*(\d{4}-\d{2}-\d{2})\s*$/)?.[1],
85+
}))
86+
.filter((section) => section.title.toLowerCase() !== "[unreleased]")
87+
.toSorted((a, b) => {
88+
if (a.date && b.date) {
89+
return b.date.localeCompare(a.date);
90+
}
91+
if (a.date) {
92+
return -1;
93+
}
94+
if (b.date) {
95+
return 1;
96+
}
97+
return b.index - a.index;
98+
})
99+
.map((section) => {
100+
const content = markdownContent(section.body);
101+
// Only render sections that have content
102+
if (!content.trim()) {
103+
return null;
104+
}
105+
return (
106+
<Card
107+
key={section.title}
108+
>
109+
<CardHeader>
110+
<CardTitle className="text-xl">
111+
{section.title}
112+
</CardTitle>
113+
</CardHeader>
114+
<CardContent>
115+
<div className="prose prose-sm dark:prose-invert max-w-none [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:bg-muted [&_code]:text-foreground [&_code]:text-xs [&_code]:font-mono [&_pre]:hidden">
116+
<ReactMarkdown
117+
remarkPlugins={[remarkGfm]}
118+
components={{
119+
h3: ({ children }) => (
120+
<h3 className="text-base font-semibold mt-4 mb-2 first:mt-0 text-primary">{children}</h3>
121+
),
122+
ul: ({ children }) => (
123+
<ul className="list-disc pl-5 space-y-1 my-2">{children}</ul>
124+
),
125+
li: ({ children }) => (
126+
<li className="text-sm text-foreground">{children}</li>
127+
),
128+
p: ({ children }) => (
129+
<p className="text-sm text-foreground my-2 leading-relaxed">{children}</p>
130+
),
131+
pre: () => null,
132+
}}
133+
>
134+
{content}
135+
</ReactMarkdown>
136+
</div>
137+
</CardContent>
138+
</Card>
139+
);
140+
})
141+
.filter(Boolean)}
142+
</div>
131143
</div>
132144
</div>
133145
</main>

apps/web/app/globals.css

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,52 @@
2525
}
2626

2727
.dark {
28-
--background: 0 0% 4%;
29-
--foreground: 0 0% 96%;
30-
--card: 0 0% 9%;
31-
--card-foreground: 0 0% 96%;
32-
--primary: 0 0% 96%;
33-
--primary-foreground: 0 0% 10%;
34-
--secondary: 0 0% 16%;
35-
--secondary-foreground: 0 0% 96%;
36-
--muted: 0 0% 16%;
28+
--background: 0 0% 0%;
29+
--foreground: 0 0% 98%;
30+
--card: 0 0% 6%;
31+
--card-foreground: 0 0% 98%;
32+
--primary: 0 0% 98%;
33+
--primary-foreground: 0 0% 3%;
34+
--secondary: 0 0% 15%;
35+
--secondary-foreground: 0 0% 98%;
36+
--muted: 0 0% 15%;
3737
--muted-foreground: 0 0% 65%;
38-
--accent: 0 0% 16%;
39-
--accent-foreground: 0 0% 96%;
40-
--destructive: 0 72% 34%;
41-
--destructive-foreground: 0 0% 96%;
38+
--accent: 0 0% 15%;
39+
--accent-foreground: 0 0% 98%;
40+
--destructive: 0 72% 50%;
41+
--destructive-foreground: 0 0% 98%;
4242
--border: 0 0% 20%;
4343
--input: 0 0% 20%;
44-
--ring: 0 0% 75%;
44+
--ring: 0 0% 98%;
4545
}
4646
}
4747

4848
@layer base {
4949
* {
5050
@apply border-border;
5151
}
52+
5253
body {
5354
@apply bg-background text-foreground;
55+
font-family: var(--font-geist-sans), -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
56+
font-feature-settings: 'kern' 1, 'liga' 1;
57+
-webkit-font-smoothing: antialiased;
58+
-moz-osx-font-smoothing: grayscale;
59+
}
60+
61+
h1, h2, h3, h4, h5, h6 {
62+
font-family: var(--font-geist-sans), sans-serif;
63+
font-weight: 600;
64+
letter-spacing: -0.02em;
65+
}
66+
67+
h1 {
68+
line-height: 1.1;
69+
padding-bottom: 0.125rem;
70+
}
71+
72+
code, pre, .font-mono {
73+
font-family: var(--font-geist-mono), 'Courier New', monospace;
74+
font-feature-settings: 'liga' 0;
5475
}
5576
}

apps/web/app/layout.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import "./globals.css";
22
import type { Metadata } from "next";
3+
import { GeistSans } from "geist/font/sans";
4+
import { GeistMono } from "geist/font/mono";
5+
import { Header } from "@/components/header";
36
import { Footer } from "@/components/footer";
47

58
export const metadata: Metadata = {
6-
title: "QA Skills",
9+
title: "QA Engineering Skills",
710
description: "Browse QA skills and best practices.",
811
};
912

@@ -14,10 +17,23 @@ export default async function RootLayout({
1417
}) {
1518
return (
1619
<html lang="en" className="dark" suppressHydrationWarning>
17-
<body className="flex flex-col min-h-screen">
18-
<div className="flex-1">
20+
<body className={`${GeistSans.variable} ${GeistMono.variable} flex flex-col min-h-screen`}>
21+
<script
22+
dangerouslySetInnerHTML={{
23+
__html: `
24+
(function() {
25+
try {
26+
// Always ensure dark mode is on
27+
document.documentElement.classList.add('dark');
28+
} catch (e) {}
29+
})();
30+
`,
31+
}}
32+
/>
33+
<Header />
34+
<main className="flex-1">
1935
{children}
20-
</div>
36+
</main>
2137
<Footer />
2238
</body>
2339
</html>

0 commit comments

Comments
 (0)