Skip to content

Commit 2872bdb

Browse files
authored
footer redesign and cleanup (#57)
* fix footer bg pattern on long pages, add sticky footer with min-h-screen * remove redundant min-h-screen from page content components * add flex-col grow wrapper for sticky footer layout * center 404 and error page content vertically in grow container * move star/share buttons above text in footer CTA * extract ShareTwitterButton, ShareLinkedInButton, StarButton as generic components * replace SocialShareButtons with individual ShareTwitterButton and ShareLinkedInButton * polish footer: fix link/button sizing, update copy and URLs * add top padding to footer * remove unused public assets, serve OG image locally * vertically center external link icons in quotes * more external link icon changes * footer: add data-testid attrs, update copy, fix grid proportions, update tests * footer: switch to flex layout, center text on mobile * disable star glow animation after user clicks star * header star button: center count, remove GitHub icon
1 parent 09b3204 commit 2872bdb

29 files changed

Lines changed: 304 additions & 261 deletions

packages/app/cypress/component/footer.cy.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,48 +25,45 @@ describe('Footer', () => {
2525
cy.get('[data-testid="footer-copyright"]').should('contain', year);
2626
});
2727

28-
it('shows the GitHub star CTA linking to GitHub repo', () => {
28+
it('shows the GitHub star CTA', () => {
2929
cy.get('[data-testid="footer-star-cta"]').should('be.visible');
30-
cy.get('[data-testid="footer-star-cta"]')
31-
.should('have.attr', 'href')
32-
.and('include', 'github.com/SemiAnalysisAI/InferenceX');
33-
});
34-
35-
it('footer star CTA opens in new tab', () => {
36-
cy.get('[data-testid="footer-star-cta"]').should('have.attr', 'target', '_blank');
30+
cy.get('[data-testid="footer-star-cta"]').should('contain', 'Star');
3731
});
3832

3933
it('shows social share buttons', () => {
40-
cy.get('[data-testid="social-share-buttons"]').should('be.visible');
34+
cy.get('[data-testid="footer-social-buttons"]').should('be.visible');
35+
cy.get('[data-testid="footer-social-buttons"]')
36+
.find('button')
37+
.should('have.length.greaterThan', 1);
4138
});
4239

4340
it('has Privacy Policy link', () => {
44-
cy.get('[data-testid="footer"]')
45-
.contains('Privacy Policy')
41+
cy.get('[data-testid="footer-link-privacy"]')
4642
.should('have.attr', 'href')
4743
.and('include', 'semianalysis.com/privacy-policy');
4844
});
4945

5046
it('has Cookie Policy link', () => {
51-
cy.get('[data-testid="footer"]')
52-
.contains('Cookie Policy')
47+
cy.get('[data-testid="footer-link-cookies"]')
5348
.should('have.attr', 'href')
5449
.and('include', 'semianalysis.com/cookie-policy');
5550
});
5651

57-
it('has Contribute link pointing to GitHub', () => {
58-
cy.get('[data-testid="footer"]')
59-
.contains('Contribute')
52+
it('has Contribute section with GitHub links', () => {
53+
cy.get('[data-testid="footer-link-benchmarks"]')
6054
.should('have.attr', 'href')
6155
.and('include', 'github.com/SemiAnalysisAI/InferenceX');
56+
cy.get('[data-testid="footer-link-frontend"]')
57+
.should('have.attr', 'href')
58+
.and('include', 'github.com/SemiAnalysisAI/InferenceX-app');
6259
});
6360

6461
it('shows the SemiAnalysis logo', () => {
65-
cy.get('[data-testid="footer"]').find('img[alt="SemiAnalysis logo"]').should('exist');
62+
cy.get('[data-testid="footer-brand"]').find('img[alt="SemiAnalysis logo"]').should('exist');
6663
});
6764

6865
it('all external links open in a new tab', () => {
69-
cy.get('[data-testid="footer"]')
66+
cy.get('[data-testid="footer-links"]')
7067
.find('a[target="_blank"]')
7168
.should('have.length.greaterThan', 0);
7269
});
Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,29 @@
1-
import { SocialShareButtons } from '@/components/social-share-buttons';
1+
import { ShareTwitterButton, ShareLinkedInButton } from '@/components/share-buttons';
22

3-
describe('Social Share Buttons', () => {
4-
beforeEach(() => {
5-
cy.mount(<SocialShareButtons />);
6-
});
7-
8-
it('social share buttons container is visible', () => {
9-
cy.get('[data-testid="social-share-buttons"]').should('be.visible');
10-
});
11-
12-
it('Twitter share button is present and is a button element', () => {
3+
describe('Share Buttons', () => {
4+
it('Twitter share button renders and is a button element', () => {
5+
cy.mount(<ShareTwitterButton />);
136
cy.get('[data-testid="share-twitter"]').should('exist');
147
cy.get('[data-testid="share-twitter"]').should('have.prop', 'tagName', 'BUTTON');
158
});
169

17-
it('LinkedIn share button is present and is a button element', () => {
18-
cy.get('[data-testid="share-linkedin"]').should('exist');
19-
cy.get('[data-testid="share-linkedin"]').should('have.prop', 'tagName', 'BUTTON');
20-
});
21-
2210
it('Twitter share button has a descriptive title referencing Twitter or X', () => {
11+
cy.mount(<ShareTwitterButton />);
2312
cy.get('[data-testid="share-twitter"]')
2413
.should('have.attr', 'title')
2514
.and('match', /Twitter|X/i);
2615
});
2716

17+
it('LinkedIn share button renders and is a button element', () => {
18+
cy.mount(<ShareLinkedInButton />);
19+
cy.get('[data-testid="share-linkedin"]').should('exist');
20+
cy.get('[data-testid="share-linkedin"]').should('have.prop', 'tagName', 'BUTTON');
21+
});
22+
2823
it('LinkedIn share button has a descriptive title referencing LinkedIn', () => {
24+
cy.mount(<ShareLinkedInButton />);
2925
cy.get('[data-testid="share-linkedin"]')
3026
.should('have.attr', 'title')
3127
.and('include', 'LinkedIn');
3228
});
3329
});
34-
35-
describe('Social Share Buttons (compact)', () => {
36-
it('renders in compact mode', () => {
37-
cy.mount(<SocialShareButtons compact />);
38-
cy.get('[data-testid="social-share-buttons"]').should('be.visible');
39-
cy.get('[data-testid="share-twitter"]').should('exist');
40-
cy.get('[data-testid="share-linkedin"]').should('exist');
41-
});
42-
});

packages/app/public/file.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/app/public/github.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/app/public/globe.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/app/public/next.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/app/public/vercel.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/app/public/window.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/app/src/app/error.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default function Error({
1616
}, [error]);
1717

1818
return (
19-
<div className="flex flex-col items-center justify-center min-h-screen text-foreground">
19+
<div className="flex flex-col items-center justify-center grow text-foreground">
2020
<h2 className="text-4xl font-bold mb-4">Something went wrong!</h2>
2121
<p className="text-lg mb-4">An unexpected error has occurred.</p>
2222
<p className="text-md text-red-500 mb-8">{error.message}</p>

packages/app/src/app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export default function RootLayout({
159159
<link rel="preconnect" href={SITE_URL} />
160160
<link rel="dns-prefetch" href={SITE_URL} />
161161
</head>
162-
<body className={`${dm_sans.variable} antialiased relative`}>
162+
<body className={`${dm_sans.variable} antialiased relative min-h-screen flex flex-col`}>
163163
<PostHogProvider>
164164
<script
165165
type="application/ld+json"
@@ -174,7 +174,7 @@ export default function RootLayout({
174174
>
175175
<PostHogPageView />
176176
<Header />
177-
{children}
177+
<div className="grow flex flex-col">{children}</div>
178178
<Footer />
179179
</ThemeProvider>
180180
</QueryProvider>

0 commit comments

Comments
 (0)