Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d7752ed
✨ Add --card / --card-hover design tokens
hveraus Jul 29, 2026
02dbd17
💄 Redesign /consulting index with themed sidebar sections
hveraus Jul 29, 2026
7ab7abb
💄 Sync homepage image cards to shared card tokens
hveraus Jul 29, 2026
586e93f
🔥 Remove dead consulting index components from the old design
hveraus Jul 29, 2026
92ad98e
🎨 Fix prettier formatting in consulting index
hveraus Jul 29, 2026
b2552ef
✨ Add POPULAR tag toggle to /consulting cards
hveraus Jul 29, 2026
6d4ed94
Mark Artificial Intelligence as popular on /consulting
hveraus Jul 29, 2026
9d78da1
Merge branch 'main' into feature/consulting-card-tokens
tiagov8 Aug 5, 2026
5ed47b8
♻️ Convert /consulting styling from CSS module to Tailwind
hveraus Aug 5, 2026
74e3c12
🐛 Fix /consulting review feedback: dropped cards, dead links, filter UX
hveraus Aug 5, 2026
09ad80a
🐛 Make /consulting's full-height background robust to layout changes
hveraus Aug 5, 2026
36ae5e5
🐛 Add missing light-mode --card / --card-hover values
hveraus Aug 5, 2026
016e508
🐛 Move /consulting's <h1> out of the complementary landmark
hveraus Aug 5, 2026
9f77db8
🐛 Use aria-current="location" for the /consulting sidebar's active fi…
hveraus Aug 5, 2026
b49632c
🐛 Fix /consulting landing on a tag hash scrolling to the bottom
hveraus Aug 5, 2026
34df6cf
Merge branch 'main' into feature/consulting-card-tokens
tiagov8 Aug 5, 2026
7a2fc5c
📝 Remove repeated "SSW" wording from /consulting service tags
hveraus Aug 6, 2026
4380955
🎨 Use theme-aware gray for /consulting sidebar and breadcrumbs
hveraus Aug 6, 2026
e42a3a8
🐛 Add brand-red border and arrow hover state to /consulting cards
hveraus Aug 6, 2026
3da234e
🐛 Fix /consulting filter clicks scrolling to the wrong spot
hveraus Aug 6, 2026
f24734f
Merge remote-tracking branch 'origin/feature/consulting-card-tokens' …
hveraus Aug 6, 2026
282843a
🐛 Fix review findings on /consulting redesign
isaaclombardssw Aug 6, 2026
07361f8
🐛 Address round 2 review on /consulting
isaaclombardssw Aug 6, 2026
cc89c86
🐛 Fix ?tag= precedence and dead sidebar rows on /consulting
isaaclombardssw Aug 6, 2026
73e04d9
📝 Drop reverted imageCards.tsx from the --card token comment
isaaclombardssw Aug 6, 2026
5c583df
🐛 Pin the /consulting mobile filter bar to the viewport top
isaaclombardssw Aug 6, 2026
20533e3
🐛 Restore the active red state in the /consulting sidebar in dark mode
isaaclombardssw Aug 6, 2026
19ac2b4
Merge branch 'main' into feature/consulting-card-tokens
tiagov8 Aug 6, 2026
dd3a9e3
🤖 Empty commit to re-trigger PR checks
isaaclombardssw Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions __tests__/helpers/consultingSections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
ALL_SERVICES,
OTHER_SERVICES,
buildConsultingSections,
sectionIdFor,
} from "@/helpers/consultingSections";

const tag = (name: string) => ({ tag: { name } });

const node = {
sidebar: [
{ label: "All Services", tag: { name: ALL_SERVICES } },
{ label: "Website Development", tag: { name: "Website Development" } },
{ label: "Content Management Systems", tag: { name: "CMS" } },
{ label: "Other Services", tag: { name: OTHER_SERVICES } },
{ label: "Row an editor left untagged" },
],
categories: [
{
pages: [
{
title: "Umbraco",
externalUrl: "/consulting/umbraco",
tags: [tag("Website Development"), tag("CMS")],
},
{
title: "Web Apps",
externalUrl: "/consulting/web-apps",
tags: [tag("Website Development")],
},
{ title: "Untagged Thing", externalUrl: "/consulting/untagged" },
{ title: "No Destination" },
],
},
],
};

const section = (sections, name: string) =>
sections.find((s) => s.name === name);
const titles = (s) => s?.pages.map((p) => p.title) ?? [];

describe("buildConsultingSections", () => {
const { sections, contentSections, allViewSections } =
buildConsultingSections(node);

test("drops entries with no destination", () => {
const all = section(sections, ALL_SERVICES);
expect(titles(all)).not.toContain("No Destination");
expect(titles(all)).toHaveLength(3);
});

test("untagged pages fall back to Other Services", () => {
expect(titles(section(sections, OTHER_SERVICES))).toEqual([
"Untagged Thing",
]);
});

test("the All Services tag is not itself a content section", () => {
expect(section(contentSections, ALL_SERVICES)).toBeUndefined();
});

test("sidebar rows with no tag are dropped, not rendered as dead filters", () => {
// Selecting one would set the filter to undefined and blank the page.
expect(sections.every((s) => !!s.name)).toBe(true);
expect(sections.map((s) => s.label)).not.toContain(
"Row an editor left untagged"
);
});

test("filtering a section shows every page tagged with it", () => {
// Umbraco is tagged both, so it appears under each when filtered directly.
expect(titles(section(contentSections, "Website Development"))).toEqual([
"Umbraco",
"Web Apps",
]);
expect(titles(section(contentSections, "CMS"))).toEqual(["Umbraco"]);
});

test("the All view gives a shared page to its smallest section", () => {
// The regression this guards: claiming in sidebar order would hand Umbraco
// to Website Development and leave CMS empty, so its heading would vanish.
expect(titles(section(allViewSections, "CMS"))).toEqual(["Umbraco"]);
expect(titles(section(allViewSections, "Website Development"))).toEqual([
"Web Apps",
]);
});

test("the All view shows each page exactly once", () => {
const shown = allViewSections.flatMap((s) => s.pages.map((p) => p.title));
expect(shown).toHaveLength(new Set(shown).size);
expect(shown.sort()).toEqual(["Umbraco", "Untagged Thing", "Web Apps"]);
});
});

describe("sectionIdFor", () => {
test("matches the anchors hardcoded in content/megamenu/menu.json", () => {
expect(sectionIdFor("Platform Development")).toBe(
"consulting-platform-development"
);
expect(sectionIdFor("Cloud and Infrastructure")).toBe(
"consulting-cloud-and-infrastructure"
);
});
});
10 changes: 5 additions & 5 deletions app/components/breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const Breadcrumbs: FC<BreadcrumbsProps> = ({
<BreadcrumbLink
href="/"
className={
"text-sm text-gray-700 underline-offset-1 hover:text-sswRed"
"text-sm text-muted-foreground underline-offset-1 hover:text-sswRed"
}
>
Home
Expand All @@ -88,7 +88,7 @@ export const Breadcrumbs: FC<BreadcrumbsProps> = ({
items.push(
<BreadcrumbSeparator
key={`separator-${index}`}
className="text-sm text-gray-700"
className="text-sm text-muted-foreground"
>
{"/"}
</BreadcrumbSeparator>
Expand All @@ -98,7 +98,7 @@ export const Breadcrumbs: FC<BreadcrumbsProps> = ({
<BreadcrumbItem key={`item-${index}`}>
{isLast ? (
<BreadcrumbPage
className={"text-sm text-gray-700 no-underline"}
className={"text-sm text-muted-foreground no-underline"}
{...(seoSchema
? { "data-tina-field": tinaField(seoSchema, "title") }
: {})}
Expand All @@ -109,7 +109,7 @@ export const Breadcrumbs: FC<BreadcrumbsProps> = ({
<BreadcrumbLink
href={href}
className={
"text-sm text-gray-700 underline-offset-1 hover:text-sswRed"
"text-sm text-muted-foreground underline-offset-1 hover:text-sswRed"
}
>
{displayName}
Expand Down Expand Up @@ -143,7 +143,7 @@ export const Breadcrumbs: FC<BreadcrumbsProps> = ({
<nav className="sm:hidden" aria-label={`Back to ${mobileParent.label}`}>
<a
href={mobileParent.href}
className="unstyled inline-flex items-center gap-1 text-sm text-gray-700 no-underline hover:text-sswRed hover:no-underline"
className="unstyled inline-flex items-center gap-1 text-sm text-muted-foreground no-underline hover:text-sswRed hover:no-underline"
aria-label={`Back to ${mobileParent.label}`}
>
<ArrowLeft className="size-3.5" aria-hidden="true" />
Expand Down
Loading
Loading