Skip to content

Commit 38926d6

Browse files
feat(web): add hover-reveal links for VS pages and use cases in footer (#2134)
* feat(web): add dropdown menus for Compare and Platforms in footer Resources column - Add hover-based dropdown for VS comparison pages (Otter, Granola, Fireflies, etc.) - Add hover-based dropdown for platform-specific download pages (macOS, Windows, Linux) - Include accessibility improvements: ARIA attributes, keyboard support, touch/click support - Follow existing header dropdown pattern for consistency Co-Authored-By: [email protected] <[email protected]> * refactor(web): simplify footer links to hover-reveal pattern - Replace dropdown menus with simpler hover-reveal links - 'Versus ???' reveals random competitor name on hover, links to VS page - 'Hyprnote for ???' reveals random use case on hover, links to solution page - Cleaner, less cluttered footer design Co-Authored-By: [email protected] <[email protected]> * feat(web): shuffle random item on each hover - Each hover picks a different random item from the list - Uses getNextRandomIndex helper to avoid showing same item twice in a row - Versus ??? and Hyprnote for ??? now shuffle on repeated hovers Co-Authored-By: [email protected] <[email protected]> * chore(web): change 'Hyprnote for ???' to 'For ???' Co-Authored-By: [email protected] <[email protected]> * feat(web): replace ??? with blurred text that reveals on hover - Remove hover boolean states (no longer needed) - Use Tailwind blur-sm and group-hover:blur-none for reveal effect - Only blur the dynamic part (competitor name / use case label) - Add smooth transition with duration-150 Co-Authored-By: [email protected] <[email protected]> * feat(footer): improve accessibility and interaction for links * feat(web): add research solution page for Hyprnote * feat(footer): update footer links and navigation structure --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent ae4c416 commit 38926d6

File tree

6 files changed

+1167
-18
lines changed

6 files changed

+1167
-18
lines changed

apps/web/src/components/footer.tsx

Lines changed: 106 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
import { Link, useRouterState } from "@tanstack/react-router";
22
import { ExternalLinkIcon, MailIcon } from "lucide-react";
3+
import { useState } from "react";
4+
5+
import { Image } from "@/components/image";
6+
7+
function getNextRandomIndex(length: number, prevIndex: number): number {
8+
if (length <= 1) return 0;
9+
let next = prevIndex;
10+
while (next === prevIndex) {
11+
next = Math.floor(Math.random() * length);
12+
}
13+
return next;
14+
}
15+
16+
const vsList = [
17+
{ slug: "otter", name: "Otter.ai" },
18+
{ slug: "granola", name: "Granola" },
19+
{ slug: "fireflies", name: "Fireflies" },
20+
{ slug: "fathom", name: "Fathom" },
21+
{ slug: "notion", name: "Notion" },
22+
{ slug: "obsidian", name: "Obsidian" },
23+
];
24+
25+
const useCasesList = [
26+
{ to: "/solution/sales", label: "Sales" },
27+
{ to: "/solution/recruiting", label: "Recruiting" },
28+
{ to: "/solution/consulting", label: "Consulting" },
29+
{ to: "/solution/coaching", label: "Coaching" },
30+
{ to: "/solution/research", label: "Research" },
31+
{ to: "/solution/journalism", label: "Journalism" },
32+
];
333

434
function getMaxWidthClass(pathname: string): string {
535
const isBlogOrDocs =
@@ -30,7 +60,7 @@ function BrandSection({ currentYear }: { currentYear: number }) {
3060
return (
3161
<div className="lg:flex-1">
3262
<Link to="/" className="inline-block mb-4">
33-
<img
63+
<Image
3464
src="/api/images/hyprnote/logo.svg"
3565
alt="Hyprnote"
3666
className="h-6"
@@ -146,12 +176,30 @@ function ProductLinks() {
146176
}
147177

148178
function ResourcesLinks() {
179+
const [vsIndex, setVsIndex] = useState(() =>
180+
Math.floor(Math.random() * vsList.length),
181+
);
182+
const [useCaseIndex, setUseCaseIndex] = useState(() =>
183+
Math.floor(Math.random() * useCasesList.length),
184+
);
185+
186+
const currentVs = vsList[vsIndex];
187+
const currentUseCase = useCasesList[useCaseIndex];
188+
149189
return (
150190
<div>
151191
<h3 className="text-sm font-semibold text-neutral-900 mb-4 font-serif">
152192
Resources
153193
</h3>
154194
<ul className="space-y-3">
195+
<li>
196+
<Link
197+
to="/pricing"
198+
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
199+
>
200+
Pricing
201+
</Link>
202+
</li>
155203
<li>
156204
<a
157205
href="/docs/faq"
@@ -161,13 +209,20 @@ function ResourcesLinks() {
161209
</a>
162210
</li>
163211
<li>
164-
<a
165-
href="mailto:[email protected]"
166-
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors inline-flex items-center gap-1 no-underline hover:underline hover:decoration-dotted"
212+
<Link
213+
to="/company-handbook"
214+
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
167215
>
168-
Support
169-
<MailIcon className="size-3" />
170-
</a>
216+
Company Handbook
217+
</Link>
218+
</li>
219+
<li>
220+
<Link
221+
to="/gallery"
222+
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
223+
>
224+
Prompt Gallery
225+
</Link>
171226
</li>
172227
<li>
173228
<a
@@ -181,27 +236,60 @@ function ResourcesLinks() {
181236
</a>
182237
</li>
183238
<li>
184-
<Link
185-
to="/pricing"
186-
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
239+
<a
240+
href="mailto:[email protected]"
241+
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors inline-flex items-center gap-1 no-underline hover:underline hover:decoration-dotted"
187242
>
188-
Pricing
189-
</Link>
243+
Support
244+
<MailIcon className="size-3" />
245+
</a>
190246
</li>
191247
<li>
192248
<Link
193-
to="/gallery"
194-
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
249+
to={currentUseCase.to}
250+
className="group text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
251+
aria-label={`Hyprnote for ${currentUseCase.label}`}
252+
onMouseEnter={() => {
253+
setUseCaseIndex((prev) =>
254+
getNextRandomIndex(useCasesList.length, prev),
255+
);
256+
}}
257+
onFocus={() => {
258+
setUseCaseIndex((prev) =>
259+
getNextRandomIndex(useCasesList.length, prev),
260+
);
261+
}}
195262
>
196-
Prompt Gallery
263+
👍 for{" "}
264+
<span className="inline-block blur-sm group-hover:blur-none group-focus:blur-none transition-all duration-150">
265+
{currentUseCase.label}
266+
</span>
197267
</Link>
198268
</li>
199269
<li>
200270
<Link
201-
to="/company-handbook"
202-
className="text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
271+
to="/vs/$slug"
272+
params={{ slug: currentVs.slug }}
273+
className="group text-sm text-neutral-600 hover:text-stone-600 transition-colors no-underline hover:underline hover:decoration-dotted"
274+
aria-label={`Versus ${currentVs.name}`}
275+
onMouseEnter={() => {
276+
setVsIndex((prev) => getNextRandomIndex(vsList.length, prev));
277+
}}
278+
onFocus={() => {
279+
setVsIndex((prev) => getNextRandomIndex(vsList.length, prev));
280+
}}
203281
>
204-
Company Handbook
282+
<img
283+
src="/api/images/hyprnote/icon.png"
284+
alt="Hyprnote"
285+
width={12}
286+
height={12}
287+
className="size-4 rounded border border-neutral-100 inline"
288+
/>{" "}
289+
vs{" "}
290+
<span className="inline-block blur-sm group-hover:blur-none group-focus:blur-none transition-all duration-150">
291+
{currentVs.name}
292+
</span>
205293
</Link>
206294
</li>
207295
</ul>

0 commit comments

Comments
 (0)