Skip to content

Commit b30771b

Browse files
Merge pull request #17 from New1Direction/feat/icons-polish
feat(website): de-emoji to a clean line-icon set (GSAP draw-on + scrub)
2 parents 0638a2e + 24cf80d commit b30771b

7 files changed

Lines changed: 167 additions & 18 deletions

File tree

website/app/(home)/styles/home.css

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,29 @@
317317
var(--bg-2);
318318
}
319319
.feat-ic {
320-
font-size: 26px;
321-
line-height: 1;
320+
display: inline-grid;
321+
place-items: center;
322+
width: 44px;
323+
height: 44px;
324+
border-radius: 12px;
325+
color: var(--accent);
326+
background: var(--accent-weak);
327+
border: 1px solid var(--accent-line);
328+
}
329+
.feat-ic .icon {
330+
display: block;
331+
}
332+
/* The wide "hero" feature tiles take the warm accent — the complementary pop. */
333+
.feat-wide .feat-ic {
334+
color: var(--warm);
335+
background: var(--warm-weak);
336+
border-color: var(--warm-line);
337+
}
338+
/* Line icons are drawn in by GSAP on scroll (pathLength=1); fully drawn by
339+
default so they're visible without JS / under reduced-motion. */
340+
.icon-stroke {
341+
stroke-dasharray: 1;
342+
stroke-dashoffset: 0;
322343
}
323344
.feat h3 {
324345
margin: 14px 0 7px;

website/app/global.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
--accent-3: #38bdf8;
3030
--grad: linear-gradient(120deg, #60a5fa 0%, #3b82f6 55%, #22d3ee 120%);
3131
--grad-soft: linear-gradient(120deg, #3b82f6, #22d3ee);
32-
--accent-glow: rgba(59, 130, 246, 0.5);
32+
--accent-glow: rgba(59, 130, 246, 0.4);
3333
--accent-weak: rgba(59, 130, 246, 0.12);
3434
--accent-line: rgba(59, 130, 246, 0.3);
3535

website/components/home/FeatureBento.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { Icon, type IconName } from '@/components/site/Icon';
2+
13
type Feature = {
2-
icon: string;
4+
icon: IconName;
35
title: string;
46
body: string;
57
tags: string[];
@@ -8,63 +10,63 @@ type Feature = {
810

911
const FEATURES: Feature[] = [
1012
{
11-
icon: '⚖️',
13+
icon: 'verdict',
1214
title: 'Verdict-first',
1315
body: 'A fit call — strong / solid / care / risky — plus a one-line bottom line, before anything else. The decision, then the evidence.',
1416
tags: ['fit', 'bottom line', 'health'],
1517
span: 'wide',
1618
},
1719
{
18-
icon: '🔍',
20+
icon: 'search',
1921
title: 'Discovery & recommendations',
2022
body: 'Search GitHub from inside the extension, or let RepoLens recommend peers from the repos you’ve already adopted — same capabilities, same language, ones you haven’t seen yet.',
2123
tags: ['discover', 'recommend', 'github'],
2224
span: 'wide',
2325
},
2426
{
25-
icon: '📚',
27+
icon: 'rows',
2628
title: 'Library + triage',
2729
body: 'Every scan becomes a sortable, filterable grid. Decide with the keyboard, in flow.',
2830
tags: ['triage', 'keyboard'],
2931
span: 'normal',
3032
},
3133
{
32-
icon: '🗂️',
34+
icon: 'kanban',
3335
title: 'Boards',
3436
body: 'Group the repos you’re weighing into collections you can compare and revisit.',
3537
tags: ['collections'],
3638
span: 'normal',
3739
},
3840
{
39-
icon: '',
41+
icon: 'star',
4042
title: 'Evaluations',
4143
body: 'Score repos 1–5 against your own weighted rubric. The badge follows each card.',
4244
tags: ['rubric', 'scoring'],
4345
span: 'normal',
4446
},
4547
{
46-
icon: '',
48+
icon: 'bars',
4749
title: 'N-way compare',
4850
body: 'Put any 2–10 repos side-by-side in a structured matrix; export to CSV or Markdown.',
4951
tags: ['matrix', 'export'],
5052
span: 'normal',
5153
},
5254
{
53-
icon: '🧠',
55+
icon: 'layers',
5456
title: 'Deep Dive',
5557
body: 'Atoms → lineage → a Feynman-style explanation, optionally grounded in measured facts from the source: real file counts, the dependency graph, tests, and a secret scan.',
5658
tags: ['eli5', 'lineage', 'grounded'],
5759
span: 'wide',
5860
},
5961
{
60-
icon: '',
62+
icon: 'clock',
6163
title: 'Drift alerts',
6264
body: 'A daily background check flags repos that have gone stale, so your shortlist stays honest.',
6365
tags: ['stale', 'daily'],
6466
span: 'normal',
6567
},
6668
{
67-
icon: '🎛️',
69+
icon: 'sliders',
6870
title: 'Bring any model',
6971
body: 'Your keys, 20+ providers, route each part of a scan to a different model — or run local Ollama for $0.',
7072
tags: ['byo-keys', 'local'],
@@ -89,7 +91,7 @@ export function FeatureBento() {
8991
{FEATURES.map((f) => (
9092
<article key={f.title} className={`feat feat-${f.span}`}>
9193
<div className="feat-ic" aria-hidden="true">
92-
{f.icon}
94+
<Icon name={f.icon} size={26} />
9395
</div>
9496
<h3>{f.title}</h3>
9597
<p>{f.body}</p>

website/components/home/SiteMotion.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ export function SiteMotion() {
3434
{ opacity: 0, y: 26, duration: 0.7, stagger: 0.09, ease, clearProps: 'transform' },
3535
);
3636

37+
// Scrubbed parallax — the mascot port drifts up as the hero scrolls away.
38+
gsap.to('.hero .hero-mascot-stage', {
39+
yPercent: -14,
40+
ease: 'none',
41+
scrollTrigger: { trigger: '.hero', start: 'top top', end: 'bottom top', scrub: 0.4 },
42+
});
43+
3744
// 2) Section reveals (every .reveal except the bento, handled below).
3845
const reveals = gsap.utils.toArray<HTMLElement>('.reveal:not(.feature-section)');
3946
ScrollTrigger.batch(reveals, {
@@ -73,6 +80,12 @@ export function SiteMotion() {
7380
delay: 0.15,
7481
clearProps: 'transform',
7582
});
83+
// Draw the line icons in (stroke-dashoffset 1 → 0).
84+
gsap.fromTo(
85+
bento.querySelectorAll('.feat .icon-stroke'),
86+
{ strokeDashoffset: 1 },
87+
{ strokeDashoffset: 0, duration: 0.7, stagger: 0.035, ease: 'power2.out', delay: 0.35 },
88+
);
7689
},
7790
});
7891
}

website/components/home/VerdictDemo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function VerdictDemo() {
3939
<span className="vd-dot" />
4040
<span className="vd-dot" />
4141
<span className="vd-dot" />
42-
<span className="vd-cache">⚡ Loaded from cache — no AI call</span>
42+
<span className="vd-cache">Cached — no AI call</span>
4343
</div>
4444

4545
<div className="vd-head">

website/components/site/Icon.tsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import type { ReactNode } from 'react';
2+
3+
export type IconName =
4+
| 'verdict'
5+
| 'search'
6+
| 'rows'
7+
| 'kanban'
8+
| 'star'
9+
| 'bars'
10+
| 'layers'
11+
| 'clock'
12+
| 'sliders'
13+
| 'lens';
14+
15+
/**
16+
* Clean line icons (replacing emoji per the taste audit). Every stroke carries
17+
* `pathLength={1}` and the `icon-stroke` class so GSAP can draw them in on
18+
* scroll. Decorative — the SVG is aria-hidden; meaning lives in the label.
19+
*/
20+
const PATHS: Record<IconName, ReactNode> = {
21+
verdict: (
22+
<>
23+
<circle className="icon-stroke" cx="12" cy="12" r="8" pathLength={1} />
24+
<path className="icon-stroke" d="M8.4 12.3l2.5 2.5 4.7-5.1" pathLength={1} />
25+
</>
26+
),
27+
search: (
28+
<>
29+
<circle className="icon-stroke" cx="11" cy="11" r="6" pathLength={1} />
30+
<line className="icon-stroke" x1="15.5" y1="15.5" x2="20" y2="20" pathLength={1} />
31+
</>
32+
),
33+
rows: (
34+
<>
35+
<line className="icon-stroke" x1="5" y1="8" x2="19" y2="8" pathLength={1} />
36+
<line className="icon-stroke" x1="5" y1="12" x2="19" y2="12" pathLength={1} />
37+
<line className="icon-stroke" x1="5" y1="16" x2="14" y2="16" pathLength={1} />
38+
</>
39+
),
40+
kanban: (
41+
<>
42+
<rect className="icon-stroke" x="4.5" y="5" width="4" height="14" rx="1.3" pathLength={1} />
43+
<rect className="icon-stroke" x="10" y="5" width="4" height="10" rx="1.3" pathLength={1} />
44+
<rect className="icon-stroke" x="15.5" y="5" width="4" height="14" rx="1.3" pathLength={1} />
45+
</>
46+
),
47+
star: (
48+
<path
49+
className="icon-stroke"
50+
d="M12 4.2l2.3 4.7 5.2.8-3.8 3.7.9 5.1-4.6-2.4-4.6 2.4.9-5.1L6.5 9.7l5.2-.8z"
51+
pathLength={1}
52+
/>
53+
),
54+
bars: (
55+
<>
56+
<line className="icon-stroke" x1="7" y1="19" x2="7" y2="12.5" pathLength={1} />
57+
<line className="icon-stroke" x1="12" y1="19" x2="12" y2="6" pathLength={1} />
58+
<line className="icon-stroke" x1="17" y1="19" x2="17" y2="14.5" pathLength={1} />
59+
</>
60+
),
61+
layers: (
62+
<>
63+
<path className="icon-stroke" d="M12 4l8 4-8 4-8-4z" pathLength={1} />
64+
<path className="icon-stroke" d="M4 12l8 4 8-4" pathLength={1} />
65+
<path className="icon-stroke" d="M4 16l8 4 8-4" pathLength={1} />
66+
</>
67+
),
68+
clock: (
69+
<>
70+
<circle className="icon-stroke" cx="12" cy="12" r="8" pathLength={1} />
71+
<path className="icon-stroke" d="M12 7.8v4.4l2.8 1.7" pathLength={1} />
72+
</>
73+
),
74+
sliders: (
75+
<>
76+
<line className="icon-stroke" x1="4" y1="8.5" x2="20" y2="8.5" pathLength={1} />
77+
<circle className="icon-stroke" cx="9" cy="8.5" r="2.2" pathLength={1} />
78+
<line className="icon-stroke" x1="4" y1="15.5" x2="20" y2="15.5" pathLength={1} />
79+
<circle className="icon-stroke" cx="15" cy="15.5" r="2.2" pathLength={1} />
80+
</>
81+
),
82+
lens: (
83+
<>
84+
<circle className="icon-stroke" cx="12" cy="12" r="8" pathLength={1} />
85+
<circle className="icon-stroke" cx="12" cy="12" r="3.4" pathLength={1} />
86+
<circle cx="12" cy="12" r="1" fill="currentColor" />
87+
</>
88+
),
89+
};
90+
91+
type Props = {
92+
name: IconName;
93+
size?: number;
94+
className?: string;
95+
};
96+
97+
export function Icon({ name, size = 24, className }: Props) {
98+
return (
99+
<svg
100+
className={`icon ${className ?? ''}`.trim()}
101+
viewBox="0 0 24 24"
102+
width={size}
103+
height={size}
104+
fill="none"
105+
stroke="currentColor"
106+
strokeWidth="1.6"
107+
strokeLinecap="round"
108+
strokeLinejoin="round"
109+
aria-hidden="true"
110+
focusable="false"
111+
>
112+
{PATHS[name]}
113+
</svg>
114+
);
115+
}

website/components/site/SiteFooter.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ export function SiteFooter() {
5454
</div>
5555

5656
<div className="site-footer-base">
57-
<span>
58-
<span aria-hidden="true">🔭</span> RepoLens — v3.0 · client-side only
59-
</span>
57+
<span>RepoLens — v3.0 · client-side only</span>
6058
<span>Bring your own model. Nothing leaves your browser.</span>
6159
</div>
6260
</footer>

0 commit comments

Comments
 (0)