Skip to content

Commit 272db24

Browse files
committed
refactor: improve layout and styling of stack selection and GitHub scan form
1 parent f8ddbb3 commit 272db24

File tree

1 file changed

+83
-114
lines changed

1 file changed

+83
-114
lines changed

components/Hero.tsx

Lines changed: 83 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -96,131 +96,100 @@ export function Hero() {
9696
Jump in with a ready-made stack template, explore the full wizard, or drop a GitHub repo for an automatic scan.
9797
</motion.p>
9898

99-
<motion.ul
100-
className="mx-auto flex max-w-3xl flex-col items-start gap-2 text-left text-sm text-muted-foreground md:flex-row md:flex-wrap md:justify-center"
101-
variants={itemVariants}
102-
>
103-
{featureHighlights.map((feature) => (
104-
<motion.li
105-
key={feature}
106-
className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-background/70 px-4 py-2 text-sm text-foreground shadow-sm backdrop-blur md:text-base"
107-
variants={itemVariants}
108-
>
109-
<CheckCircle2 className="size-4 text-primary" />
110-
{feature}
111-
</motion.li>
112-
))}
113-
</motion.ul>
99+
114100

115101
<motion.div
116-
className="mx-auto w-full max-w-4xl space-y-8 text-left"
102+
className="mx-auto w-full max-w-4xl text-left"
117103
variants={itemVariants}
118104
>
119-
<div className="flex flex-col gap-4">
120-
<div className="flex flex-wrap items-center justify-between gap-3">
105+
<div className="flex flex-col gap-6 lg:flex-row lg:items-start">
106+
<div className="flex-1 space-y-4">
121107
<h2 className="text-lg font-semibold uppercase tracking-wide text-muted-foreground">
122108
Start fast with popular stacks
123109
</h2>
124-
<Button variant="outline" size="sm" onClick={handleMoreStacks}>
125-
More stacks
126-
<ArrowRight className="ml-2 h-4 w-4" />
127-
</Button>
128-
</div>
129-
<div className="grid gap-3 md:grid-cols-3">
130-
{popularStacks.map((stack) => {
131-
const descriptor = getIconDescriptor(stack.icon ?? stack.value)
132-
const iconHex = descriptor ? iconColorOverrides[descriptor.slug] ?? descriptor.hex : undefined
133-
const iconColor = iconHex ? getAccessibleIconColor(iconHex) : undefined
134-
const iconBackground = iconColor ? hexToRgba(iconColor, 0.18) ?? undefined : undefined
135-
const iconRing = iconColor ? hexToRgba(iconColor, 0.32) ?? undefined : undefined
136-
const initials = getFallbackInitials(stack.label)
137-
138-
return (
139-
<button
140-
key={stack.value}
141-
type="button"
142-
onClick={() => handleStackClick(stack.value)}
143-
className="group flex h-full flex-col gap-4 rounded-3xl border border-border/70 bg-background/90 px-5 py-6 text-left shadow-sm transition-all hover:-translate-y-0.5 hover:border-primary/40 hover:shadow-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
144-
>
145-
<span
146-
className="flex h-10 w-10 items-center justify-center rounded-xl ring-1 ring-border/40"
147-
style={{
148-
color: iconColor,
149-
backgroundColor: iconBackground,
150-
boxShadow: iconRing ? `inset 0 0 0 1px ${iconRing}` : undefined,
151-
}}
152-
aria-hidden
110+
<div className="flex flex-wrap gap-3">
111+
{popularStacks.map((stack) => {
112+
const descriptor = getIconDescriptor(stack.icon ?? stack.value)
113+
const iconHex = descriptor ? iconColorOverrides[descriptor.slug] ?? descriptor.hex : undefined
114+
const iconColor = iconHex ? getAccessibleIconColor(iconHex) : undefined
115+
const iconBackground = iconColor ? hexToRgba(iconColor, 0.18) ?? undefined : undefined
116+
const iconRing = iconColor ? hexToRgba(iconColor, 0.32) ?? undefined : undefined
117+
const initials = getFallbackInitials(stack.label)
118+
119+
return (
120+
<button
121+
key={stack.value}
122+
type="button"
123+
onClick={() => handleStackClick(stack.value)}
124+
className="group inline-flex items-center gap-3 rounded-full border border-border/70 bg-background/90 px-4 py-2 text-sm font-medium text-foreground shadow-sm transition hover:-translate-y-0.5 hover:border-primary/40 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
153125
>
154-
{descriptor ? (
155-
<span
156-
className="inline-flex h-6 w-6 items-center justify-center [&>svg]:h-full [&>svg]:w-full"
157-
style={{ color: iconColor ?? "inherit" }}
158-
dangerouslySetInnerHTML={{ __html: descriptor.markup }}
159-
/>
160-
) : (
161-
<span className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
162-
{initials}
163-
</span>
164-
)}
165-
</span>
166-
<div className="space-y-2">
167-
<div className="flex items-center justify-between gap-3">
168-
<p className="text-base font-semibold text-foreground">{stack.label}</p>
169-
<ArrowRight className="h-4 w-4 text-muted-foreground transition group-hover:text-primary" />
170-
</div>
171-
{stack.tags && stack.tags.length > 0 ? (
172-
<div className="flex flex-wrap gap-1 text-[10px] uppercase tracking-wide text-muted-foreground/70">
173-
{stack.tags.slice(0, 3).map((tag) => (
174-
<span key={tag} className="rounded-full bg-muted/70 px-2 py-0.5">
175-
{tag}
176-
</span>
177-
))}
178-
</div>
179-
) : null}
180-
<p className="text-sm text-muted-foreground">
181-
Auto-fill recommended defaults and jump straight to the summary.
182-
</p>
183-
</div>
184-
</button>
185-
)
186-
})}
126+
<span
127+
className="flex h-8 w-8 items-center justify-center rounded-full ring-1 ring-border/40"
128+
style={{
129+
color: iconColor,
130+
backgroundColor: iconBackground,
131+
boxShadow: iconRing ? `inset 0 0 0 1px ${iconRing}` : undefined,
132+
}}
133+
aria-hidden
134+
>
135+
{descriptor ? (
136+
<span
137+
className="inline-flex h-5 w-5 items-center justify-center [&>svg]:h-full [&>svg]:w-full"
138+
style={{ color: iconColor ?? "inherit" }}
139+
dangerouslySetInnerHTML={{ __html: descriptor.markup }}
140+
/>
141+
) : (
142+
<span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
143+
{initials}
144+
</span>
145+
)}
146+
</span>
147+
<span className="flex items-center gap-2">
148+
{stack.label}
149+
<ArrowRight className="h-3.5 w-3.5 text-muted-foreground transition group-hover:text-primary" />
150+
</span>
151+
</button>
152+
)
153+
})}
154+
155+
<button
156+
type="button"
157+
onClick={handleMoreStacks}
158+
className="inline-flex items-center gap-2 rounded-full border border-border/70 bg-background/80 px-4 py-2 text-sm font-semibold text-foreground shadow-sm transition hover:-translate-y-0.5 hover:border-primary/40 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60"
159+
>
160+
More stacks
161+
<ArrowRight className="h-3.5 w-3.5" />
162+
</button>
163+
</div>
187164
</div>
188-
</div>
189165

190-
<div className="flex items-center gap-4">
191-
<div className="h-px flex-1 bg-border/60" />
192-
<span className="text-xs font-semibold uppercase tracking-[0.3em] text-muted-foreground">
193-
or
194-
</span>
195-
<div className="h-px flex-1 bg-border/60" />
166+
<form
167+
onSubmit={handleGithubSubmit}
168+
className="flex flex-1 flex-col gap-3 rounded-3xl border border-border/70 bg-background/95 p-6 shadow-sm"
169+
>
170+
<div className="space-y-2 text-left">
171+
<p className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
172+
Scan a GitHub repository
173+
</p>
174+
<p className="text-sm text-muted-foreground">
175+
Paste an owner/repo or URL and we&apos;ll prefill the wizard with detected tech and tooling.
176+
</p>
177+
</div>
178+
<div className="flex w-full flex-col gap-2 sm:flex-row">
179+
<input
180+
type="text"
181+
value={githubRepo}
182+
onChange={(event) => setGithubRepo(event.target.value)}
183+
placeholder="github.com/owner/repo"
184+
className="w-full rounded-xl border border-border/70 bg-background px-4 py-2 text-sm text-foreground shadow-sm transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 sm:min-w-[260px]"
185+
/>
186+
<Button type="submit" size="sm" className="gap-2">
187+
Scan repo
188+
<Github className="h-4 w-4" />
189+
</Button>
190+
</div>
191+
</form>
196192
</div>
197-
198-
<form
199-
onSubmit={handleGithubSubmit}
200-
className="flex flex-col gap-3 rounded-3xl border border-border/70 bg-background/95 p-6 shadow-sm sm:flex-row sm:items-center"
201-
>
202-
<div className="flex-1 space-y-2 text-left">
203-
<p className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
204-
Scan a GitHub repository
205-
</p>
206-
<p className="text-sm text-muted-foreground">
207-
Paste an owner/repo or URL and we&apos;ll prefill the wizard with detected tech and tooling.
208-
</p>
209-
</div>
210-
<div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row">
211-
<input
212-
type="text"
213-
value={githubRepo}
214-
onChange={(event) => setGithubRepo(event.target.value)}
215-
placeholder="github.com/owner/repo"
216-
className="w-full rounded-xl border border-border/70 bg-background px-4 py-2 text-sm text-foreground shadow-sm transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 sm:min-w-[260px]"
217-
/>
218-
<Button type="submit" size="sm" className="gap-2">
219-
Scan repo
220-
<Github className="h-4 w-4" />
221-
</Button>
222-
</div>
223-
</form>
224193
</motion.div>
225194
</motion.div>
226195
</motion.section>

0 commit comments

Comments
 (0)