forked from Rosetta/landing
Move support into React Router
This commit is contained in:
@@ -13,7 +13,7 @@ export function Footer() {
|
||||
© {currentYear} {LEGAL_NAME}. All rights reserved.
|
||||
</Text>
|
||||
<nav className={classes.links} aria-label="Legal information">
|
||||
<Anchor href="/support/" size="sm" c="dimmed">
|
||||
<Anchor component={Link} to="/support" size="sm" c="dimmed">
|
||||
Support
|
||||
</Anchor>
|
||||
<Anchor component={Link} to="/privacy" size="sm" c="dimmed">
|
||||
|
||||
@@ -13,12 +13,13 @@ import { Link } from 'react-router-dom';
|
||||
import { RosettaLogo } from '../RosettaLogo/RosettaLogo';
|
||||
import classes from './LegalPage.module.css';
|
||||
|
||||
type LegalRoute = 'privacy' | 'terms';
|
||||
type ContentRoute = 'support' | 'privacy' | 'terms';
|
||||
|
||||
interface LegalPageProps {
|
||||
active: LegalRoute;
|
||||
active: ContentRoute;
|
||||
title: string;
|
||||
updated: string;
|
||||
updated?: string;
|
||||
eyebrow?: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
@@ -27,7 +28,19 @@ interface LegalSectionProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function LegalPage({ active, title, updated, children }: LegalPageProps) {
|
||||
const NAV_LINKS = [
|
||||
{ route: 'support', label: 'Support' },
|
||||
{ route: 'privacy', label: 'Privacy' },
|
||||
{ route: 'terms', label: 'Terms' },
|
||||
] as const;
|
||||
|
||||
export function LegalPage({
|
||||
active,
|
||||
title,
|
||||
updated,
|
||||
eyebrow = 'Rosetta Legal',
|
||||
children,
|
||||
}: LegalPageProps) {
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
@@ -38,7 +51,7 @@ export function LegalPage({ active, title, updated, children }: LegalPageProps)
|
||||
component={Link}
|
||||
to="/"
|
||||
className={classes.brand}
|
||||
aria-label="Rosetta home"
|
||||
aria-label="Rosetta"
|
||||
>
|
||||
<RosettaLogo size={34} />
|
||||
<Text component="span" fw={700} fz="lg">
|
||||
@@ -46,44 +59,36 @@ export function LegalPage({ active, title, updated, children }: LegalPageProps)
|
||||
</Text>
|
||||
</Anchor>
|
||||
|
||||
<Group component="nav" gap="lg" aria-label="Legal pages">
|
||||
<Anchor href="/support/" c="dimmed" size="sm">
|
||||
Support
|
||||
</Anchor>
|
||||
<Anchor
|
||||
component={Link}
|
||||
to="/privacy"
|
||||
c={active === 'privacy' ? 'blue' : 'dimmed'}
|
||||
fw={active === 'privacy' ? 600 : 400}
|
||||
size="sm"
|
||||
aria-current={active === 'privacy' ? 'page' : undefined}
|
||||
>
|
||||
Privacy
|
||||
</Anchor>
|
||||
<Anchor
|
||||
component={Link}
|
||||
to="/terms"
|
||||
c={active === 'terms' ? 'blue' : 'dimmed'}
|
||||
fw={active === 'terms' ? 600 : 400}
|
||||
size="sm"
|
||||
aria-current={active === 'terms' ? 'page' : undefined}
|
||||
>
|
||||
Terms
|
||||
</Anchor>
|
||||
<Group component="nav" gap="lg" aria-label="Rosetta pages">
|
||||
{NAV_LINKS.map(({ route, label }) => (
|
||||
<Anchor
|
||||
key={route}
|
||||
component={Link}
|
||||
to={`/${route}`}
|
||||
c={active === route ? 'blue' : 'dimmed'}
|
||||
fw={active === route ? 600 : 400}
|
||||
size="sm"
|
||||
aria-current={active === route ? 'page' : undefined}
|
||||
>
|
||||
{label}
|
||||
</Anchor>
|
||||
))}
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
<Box component="main" className={classes.main}>
|
||||
<Box className={classes.intro}>
|
||||
<Text tt="uppercase" fw={700} fz="xs" c="blue" lts="0.08em">
|
||||
Rosetta legal
|
||||
{eyebrow}
|
||||
</Text>
|
||||
<Title order={1} className={classes.title}>
|
||||
{title}
|
||||
</Title>
|
||||
<Text c="dimmed" mt="md">
|
||||
Last updated: {updated}
|
||||
</Text>
|
||||
{updated && (
|
||||
<Text c="dimmed" mt="md">
|
||||
Last updated: {updated}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Paper
|
||||
@@ -103,18 +108,16 @@ export function LegalPage({ active, title, updated, children }: LegalPageProps)
|
||||
</Text>
|
||||
<Group component="nav" gap="md" aria-label="Footer links">
|
||||
<Anchor component={Link} to="/" c="dimmed" size="xs">
|
||||
Rosetta home
|
||||
Rosetta
|
||||
</Anchor>
|
||||
<Anchor href="/support/" c="dimmed" size="xs">
|
||||
<Anchor component={Link} to="/support" c="dimmed" size="xs">
|
||||
Support
|
||||
</Anchor>
|
||||
<Anchor
|
||||
component={Link}
|
||||
to={active === 'privacy' ? '/terms' : '/privacy'}
|
||||
c="dimmed"
|
||||
size="xs"
|
||||
>
|
||||
{active === 'privacy' ? 'Terms of Use' : 'Privacy Policy'}
|
||||
<Anchor component={Link} to="/privacy" c="dimmed" size="xs">
|
||||
Privacy Policy
|
||||
</Anchor>
|
||||
<Anchor component={Link} to="/terms" c="dimmed" size="xs">
|
||||
Terms of Use
|
||||
</Anchor>
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useEffect } from 'react';
|
||||
interface SEOProps {
|
||||
title?: string;
|
||||
description?: string;
|
||||
ogImage?: string;
|
||||
keywords?: string;
|
||||
canonical?: string;
|
||||
}
|
||||
@@ -11,7 +10,6 @@ interface SEOProps {
|
||||
export function SEO({
|
||||
title = 'Rosetta - Secure Messaging for Everyone',
|
||||
description = 'End-to-end encrypted messaging app with military-grade security. Download for Windows, Linux, and Android.',
|
||||
ogImage = '/og.png',
|
||||
keywords = 'secure messaging, encrypted chat, private messenger',
|
||||
canonical = 'https://rosetta.im/'
|
||||
}: SEOProps) {
|
||||
@@ -22,14 +20,14 @@ export function SEO({
|
||||
updateMetaTag('name', 'keywords', keywords);
|
||||
updateMetaTag('property', 'og:title', title);
|
||||
updateMetaTag('property', 'og:description', description);
|
||||
updateMetaTag('property', 'og:image', ogImage);
|
||||
updateMetaTag('property', 'og:url', canonical);
|
||||
updateMetaTag('name', 'twitter:title', title);
|
||||
updateMetaTag('name', 'twitter:description', description);
|
||||
updateMetaTag('name', 'twitter:image', ogImage);
|
||||
updateMetaTag('name', 'twitter:url', canonical);
|
||||
removeMetaTag('property', 'og:image');
|
||||
removeMetaTag('name', 'twitter:image');
|
||||
updateCanonical(canonical);
|
||||
}, [title, description, ogImage, keywords, canonical]);
|
||||
}, [title, description, keywords, canonical]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -46,6 +44,10 @@ function updateMetaTag(attr: string, name: string, content: string) {
|
||||
element.setAttribute('content', content);
|
||||
}
|
||||
|
||||
function removeMetaTag(attr: string, name: string) {
|
||||
document.querySelector(`meta[${attr}="${name}"]`)?.remove();
|
||||
}
|
||||
|
||||
function updateCanonical(href: string) {
|
||||
let element = document.querySelector<HTMLLinkElement>('link[rel="canonical"]');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user