Skip to content

Commit 024379a

Browse files
fyalavuzclaude
andcommitted
feat: upgrade all examples to production quality
Major quality overhaul of all 5 example apps: - Fix Geist font loading via next/font/google (was declared but never imported) - Social App: real posts with usernames, avatars, interactions, FooterItem.badge demo - E-commerce: real products with names, prices, star ratings, color swatches, category chips - Music Player: unique gradient per track, playlist carousel, progress bar, semantic dark tokens - Dashboard: fix Math.random() hydration bug, real activity/users data, semantic dark tokens - Messaging: avatar initials + online dot, typing indicator, date divider, attachment button - Example Picker: gradient icon circles, descriptions, navigation arrows Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0a9780e commit 024379a

8 files changed

Lines changed: 1063 additions & 188 deletions

File tree

apps/examples/app/dashboard/page.tsx

Lines changed: 293 additions & 63 deletions
Large diffs are not rendered by default.

apps/examples/app/ecommerce/page.tsx

Lines changed: 238 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,182 @@
11
"use client";
22

3+
import { useState } from "react";
34
import { AppShell, Header, Content, Footer } from "@appshell/react";
4-
import { ShoppingCart, Search } from "lucide-react";
5+
import { ShoppingCart, Search, Star } from "lucide-react";
6+
7+
const products = [
8+
{
9+
id: 1,
10+
name: "Linen Relaxed Blazer",
11+
price: 149,
12+
rating: 4.5,
13+
reviews: 234,
14+
gradient: "bg-gradient-to-br from-amber-200 to-orange-300",
15+
colors: ["#c4a882", "#2c2c2c", "#e8ddd3"],
16+
tag: "Best Seller" as const,
17+
},
18+
{
19+
id: 2,
20+
name: "Cropped Wide-Leg Trousers",
21+
price: 89,
22+
rating: 4.0,
23+
reviews: 187,
24+
gradient: "bg-gradient-to-br from-stone-300 to-zinc-400",
25+
colors: ["#1a1a1a", "#d4c5b0"],
26+
tag: "New" as const,
27+
},
28+
{
29+
id: 3,
30+
name: "Silk Camisole Top",
31+
price: 59,
32+
rating: 4.5,
33+
reviews: 312,
34+
gradient: "bg-gradient-to-br from-rose-200 to-pink-300",
35+
colors: ["#e8c4c4", "#1a1a1a", "#f5f0eb"],
36+
tag: null,
37+
},
38+
{
39+
id: 4,
40+
name: "Oversized Wool Coat",
41+
price: 189,
42+
rating: 5.0,
43+
reviews: 156,
44+
gradient: "bg-gradient-to-br from-slate-400 to-gray-600",
45+
colors: ["#3d3d3d", "#8b7d6b"],
46+
tag: "Best Seller" as const,
47+
},
48+
{
49+
id: 5,
50+
name: "Ribbed Knit Cardigan",
51+
price: 79,
52+
rating: 4.0,
53+
reviews: 98,
54+
gradient: "bg-gradient-to-br from-emerald-200 to-teal-300",
55+
colors: ["#6b8f71", "#f5f0eb", "#2c2c2c"],
56+
tag: null,
57+
},
58+
{
59+
id: 6,
60+
name: "High-Rise Slim Jeans",
61+
price: 98,
62+
rating: 4.5,
63+
reviews: 421,
64+
gradient: "bg-gradient-to-br from-blue-300 to-indigo-400",
65+
colors: ["#3b5998", "#1a1a1a"],
66+
tag: "Sale" as const,
67+
},
68+
{
69+
id: 7,
70+
name: "Cotton Poplin Shirt",
71+
price: 65,
72+
rating: 4.0,
73+
reviews: 276,
74+
gradient: "bg-gradient-to-br from-sky-200 to-cyan-300",
75+
colors: ["#f5f5f5", "#a8c8e0", "#1a1a1a"],
76+
tag: "New" as const,
77+
},
78+
{
79+
id: 8,
80+
name: "Leather Crossbody Bag",
81+
price: 129,
82+
rating: 4.5,
83+
reviews: 189,
84+
gradient: "bg-gradient-to-br from-yellow-200 to-amber-400",
85+
colors: ["#8b6914", "#1a1a1a", "#c4a882"],
86+
tag: null,
87+
},
88+
{
89+
id: 9,
90+
name: "Pleated Midi Skirt",
91+
price: 75,
92+
rating: 3.5,
93+
reviews: 143,
94+
gradient: "bg-gradient-to-br from-violet-200 to-purple-300",
95+
colors: ["#7c5cbf", "#1a1a1a"],
96+
tag: null,
97+
},
98+
{
99+
id: 10,
100+
name: "Cashmere Crewneck Sweater",
101+
price: 165,
102+
rating: 5.0,
103+
reviews: 208,
104+
gradient: "bg-gradient-to-br from-red-200 to-rose-400",
105+
colors: ["#c45c5c", "#f5f0eb", "#2c2c2c"],
106+
tag: "Best Seller" as const,
107+
},
108+
{
109+
id: 11,
110+
name: "Quilted Puffer Vest",
111+
price: 119,
112+
rating: 4.0,
113+
reviews: 87,
114+
gradient: "bg-gradient-to-br from-lime-200 to-green-400",
115+
colors: ["#4a6741", "#1a1a1a"],
116+
tag: "Sale" as const,
117+
},
118+
{
119+
id: 12,
120+
name: "Woven Straw Sun Hat",
121+
price: 45,
122+
rating: 4.5,
123+
reviews: 64,
124+
gradient: "bg-gradient-to-br from-orange-200 to-yellow-300",
125+
colors: ["#d4a76a", "#f5f0eb"],
126+
tag: "New" as const,
127+
},
128+
];
129+
130+
const categories = ["All", "Tops", "Bottoms", "Outerwear", "Accessories", "Sale"];
131+
132+
function tagColor(tag: string) {
133+
switch (tag) {
134+
case "Best Seller":
135+
return "bg-amber-500 text-white";
136+
case "New":
137+
return "bg-emerald-500 text-white";
138+
case "Sale":
139+
return "bg-destructive text-white";
140+
default:
141+
return "bg-muted text-muted-foreground";
142+
}
143+
}
144+
145+
function StarRating({ rating, reviews }: { rating: number; reviews: number }) {
146+
return (
147+
<div className="flex items-center gap-1">
148+
<div className="flex">
149+
{Array.from({ length: 5 }, (_, i) => {
150+
const filled = i < Math.floor(rating);
151+
const half = !filled && i < rating;
152+
return (
153+
<Star
154+
key={i}
155+
className={`size-3 ${
156+
filled || half
157+
? "fill-amber-400 text-amber-400"
158+
: "fill-none text-muted-foreground/40"
159+
}`}
160+
/>
161+
);
162+
})}
163+
</div>
164+
<span className="text-xs text-muted-foreground">({reviews})</span>
165+
</div>
166+
);
167+
}
5168

6169
export default function EcommerceExample() {
170+
const [activeCategory, setActiveCategory] = useState("All");
171+
7172
return (
8173
<AppShell safeArea>
9174
<Header
10175
behavior="fixed"
11176
theme="light"
12-
logo={<span className="text-lg font-bold tracking-tight">ShopNow</span>}
177+
logo={
178+
<span className="text-lg font-bold tracking-tight">ShopNow</span>
179+
}
13180
title="New Arrivals"
14181
subtitle="Spring Collection"
15182
searchContent={
@@ -24,31 +191,80 @@ export default function EcommerceExample() {
24191
</div>
25192
}
26193
actions={
27-
<button aria-label="Cart (3 items)" className="relative p-2 rounded-lg hover:bg-accent transition-colors">
194+
<button
195+
aria-label="Cart (3 items)"
196+
className="relative p-2 rounded-lg hover:bg-accent transition-colors"
197+
>
28198
<ShoppingCart className="size-5" />
29-
<span aria-hidden="true" className="absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-bold text-white">
199+
<span
200+
aria-hidden="true"
201+
className="absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-bold text-white"
202+
>
30203
3
31204
</span>
32205
</button>
33206
}
34207
/>
35208

36209
<Content className="pb-24">
37-
<div className="mx-auto max-w-7xl px-4 py-6">
210+
<div className="mx-auto max-w-7xl px-4 py-6 space-y-6">
211+
{/* Category chips */}
212+
<div className="flex gap-2 overflow-x-auto no-scrollbar">
213+
{categories.map((category) => (
214+
<button
215+
key={category}
216+
onClick={() => setActiveCategory(category)}
217+
className={`rounded-full px-4 py-1.5 text-sm whitespace-nowrap transition-colors ${
218+
activeCategory === category
219+
? "bg-primary text-primary-foreground"
220+
: "bg-muted text-muted-foreground"
221+
}`}
222+
>
223+
{category}
224+
</button>
225+
))}
226+
</div>
227+
228+
{/* Product grid */}
38229
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
39-
{Array.from({ length: 12 }, (_, i) => (
40-
<div key={i} className="rounded-xl border bg-card overflow-hidden">
41-
<div className="aspect-square bg-muted" />
42-
<div className="p-3 space-y-2">
43-
<div className="h-3.5 w-3/4 rounded bg-muted" />
44-
<div className="h-3 w-1/2 rounded bg-muted" />
45-
<div className="flex items-center justify-between mt-2">
46-
<div className="h-4 w-16 rounded bg-muted" />
47-
<div className="flex gap-1">
48-
{Array.from({ length: 5 }, (_, j) => (
49-
<div key={j} className="size-2.5 rounded-full bg-muted" />
50-
))}
51-
</div>
230+
{products.map((product) => (
231+
<div
232+
key={product.id}
233+
className="rounded-xl border bg-card overflow-hidden"
234+
>
235+
{/* Image placeholder */}
236+
<div className={`relative aspect-square ${product.gradient}`}>
237+
{product.tag && (
238+
<span
239+
className={`absolute top-2 left-2 rounded-full px-2 py-0.5 text-[11px] font-semibold ${tagColor(product.tag)}`}
240+
>
241+
{product.tag}
242+
</span>
243+
)}
244+
</div>
245+
246+
{/* Product info */}
247+
<div className="p-3 space-y-1.5">
248+
<h3 className="text-sm font-medium text-foreground leading-snug line-clamp-1">
249+
{product.name}
250+
</h3>
251+
252+
<StarRating rating={product.rating} reviews={product.reviews} />
253+
254+
<p className="text-sm font-bold text-foreground">
255+
${product.price}
256+
</p>
257+
258+
{/* Color swatches */}
259+
<div className="flex items-center gap-1.5 pt-0.5">
260+
{product.colors.map((color) => (
261+
<span
262+
key={color}
263+
className="size-4 rounded-full border border-border"
264+
style={{ backgroundColor: color }}
265+
aria-label={`Color ${color}`}
266+
/>
267+
))}
52268
</div>
53269
</div>
54270
</div>
@@ -58,8 +274,11 @@ export default function EcommerceExample() {
58274
</Content>
59275

60276
<Footer variant="floating" position="right">
61-
<button aria-label="Add to cart" className="flex items-center justify-center size-14 rounded-full bg-primary text-primary-foreground shadow-xl hover:scale-105 transition-transform">
277+
<button className="relative flex items-center justify-center size-14 rounded-full bg-primary text-primary-foreground shadow-xl hover:scale-105 transition-transform">
62278
<ShoppingCart className="size-6" />
279+
<span className="absolute -top-1 -right-1 flex h-5 min-w-5 items-center justify-center rounded-full bg-destructive px-1 text-[11px] font-bold text-white">
280+
3
281+
</span>
63282
</button>
64283
</Footer>
65284
</AppShell>

apps/examples/app/globals.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@
5959
}
6060

6161
@theme inline {
62-
--font-sans: 'Geist', 'Geist Mono Fallback';
63-
--font-mono: 'Geist Mono', 'Geist Mono Fallback';
62+
--font-sans: var(--font-geist), ui-sans-serif, system-ui, sans-serif;
63+
--font-mono: ui-monospace, SFMono-Regular, monospace;
6464
--color-background: var(--background);
6565
--color-foreground: var(--foreground);
6666
--color-card: var(--card);

apps/examples/app/layout.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import type { Metadata } from "next";
2+
import { Geist } from "next/font/google";
23
import "./globals.css";
34

5+
const geist = Geist({
6+
subsets: ["latin"],
7+
variable: "--font-geist",
8+
});
9+
410
export const metadata: Metadata = {
511
title: "AppShell Examples",
612
description: "Fullscreen examples of @appshell/react components",
@@ -12,7 +18,7 @@ export default function RootLayout({
1218
children: React.ReactNode;
1319
}) {
1420
return (
15-
<html lang="en">
21+
<html lang="en" className={geist.variable}>
1622
<head>
1723
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
1824
</head>

apps/examples/app/messaging/page.tsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { AppShell, Header, Content, Footer } from "@appshell/react";
4-
import { ArrowLeft, Send, Phone, MoreVertical } from "lucide-react";
4+
import { ArrowLeft, Send, Phone, MoreVertical, Paperclip } from "lucide-react";
55

66
const messages = [
77
{ id: 1, from: "them", text: "Hey! How are you doing?" },
@@ -37,7 +37,12 @@ export default function MessagingExample() {
3737
<button aria-label="Go back" className="p-1 rounded-md hover:bg-white/10 transition-colors">
3838
<ArrowLeft className="size-5" />
3939
</button>
40-
<div className="size-9 rounded-full bg-white/20" />
40+
<div className="relative">
41+
<div className="size-9 rounded-full bg-white/20 flex items-center justify-center text-xs font-bold">
42+
JS
43+
</div>
44+
<div className="absolute bottom-0 right-0 size-2.5 rounded-full bg-green-400 border-2 border-primary" />
45+
</div>
4146
<div>
4247
<div className="text-sm font-semibold leading-tight">Jane Smith</div>
4348
<div className="text-xs opacity-80">Online</div>
@@ -58,6 +63,9 @@ export default function MessagingExample() {
5863

5964
<Content className="pb-16">
6065
<div className="mx-auto max-w-lg px-4 py-4 space-y-3">
66+
<div className="flex justify-center my-4">
67+
<span className="text-xs bg-muted text-muted-foreground px-3 py-1 rounded-full">Today</span>
68+
</div>
6169
{messages.map((msg) => (
6270
<div
6371
key={msg.id}
@@ -81,17 +89,31 @@ export default function MessagingExample() {
8189
</div>
8290
</div>
8391
))}
92+
<div className="flex justify-start">
93+
<div className="bg-muted rounded-2xl rounded-bl-md px-4 py-3">
94+
<div className="flex gap-1">
95+
<div className="size-2 rounded-full bg-muted-foreground/40 animate-bounce [animation-delay:0ms]" />
96+
<div className="size-2 rounded-full bg-muted-foreground/40 animate-bounce [animation-delay:150ms]" />
97+
<div className="size-2 rounded-full bg-muted-foreground/40 animate-bounce [animation-delay:300ms]" />
98+
</div>
99+
</div>
100+
</div>
84101
</div>
85102
</Content>
86103

87104
<Footer variant="mini">
88105
<div className="flex w-full items-center gap-2">
89-
<input
90-
type="text"
91-
placeholder="Type a message..."
92-
aria-label="Type a message"
93-
className="flex-1 rounded-full border border-border bg-muted/50 px-4 py-1.5 text-sm outline-none placeholder:text-muted-foreground"
94-
/>
106+
<button aria-label="Attach file" className="p-1.5 text-muted-foreground hover:text-foreground transition-colors">
107+
<Paperclip className="size-5" />
108+
</button>
109+
<div className="flex-1">
110+
<input
111+
type="text"
112+
placeholder="Type a message..."
113+
aria-label="Type a message"
114+
className="w-full rounded-full border border-border bg-muted/50 px-4 py-1.5 text-sm outline-none placeholder:text-muted-foreground focus:ring-2 focus:ring-primary/20"
115+
/>
116+
</div>
95117
<button aria-label="Send message" className="flex items-center justify-center size-8 rounded-full bg-primary text-primary-foreground shrink-0">
96118
<Send className="size-4" />
97119
</button>

0 commit comments

Comments
 (0)