Feature/brutalism overhaul #10
@@ -12,6 +12,7 @@ import { Link } from './Link';
|
|||||||
|
|
||||||
const PRIMARY = 'underline underline-offset-2 hover:opacity-60 transition-opacity';
|
const PRIMARY = 'underline underline-offset-2 hover:opacity-60 transition-opacity';
|
||||||
const SECONDARY = 'no-underline opacity-60 hover:opacity-100 sm:brutal-border-bottom transition-opacity';
|
const SECONDARY = 'no-underline opacity-60 hover:opacity-100 sm:brutal-border-bottom transition-opacity';
|
||||||
|
const TERTIARY = 'no-underline opacity-100 hover:opacity-60 sm:brutal-border-bottom transition-opacity';
|
||||||
|
|
||||||
describe('internal link', () => {
|
describe('internal link', () => {
|
||||||
it('renders an anchor element', () => {
|
it('renders an anchor element', () => {
|
||||||
@@ -92,6 +93,18 @@ describe('variant', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('tertiary applies reversed-hover classes', () => {
|
||||||
|
render(
|
||||||
|
<Link href="/about" variant="tertiary">
|
||||||
|
About
|
||||||
|
</Link>,
|
||||||
|
);
|
||||||
|
const link = screen.getByRole('link', { name: 'About' });
|
||||||
|
for (const cls of TERTIARY.split(' ')) {
|
||||||
|
expect(link).toHaveClass(cls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('secondary does not apply underline', () => {
|
it('secondary does not apply underline', () => {
|
||||||
render(
|
render(
|
||||||
<Link href="/about" variant="secondary">
|
<Link href="/about" variant="secondary">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import NextLink from 'next/link';
|
|||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { cn } from '$shared/lib';
|
import { cn } from '$shared/lib';
|
||||||
|
|
||||||
export type LinkVariant = 'primary' | 'secondary';
|
export type LinkVariant = 'primary' | 'secondary' | 'tertiary';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Props for Link.
|
* Props for Link.
|
||||||
@@ -24,6 +24,7 @@ interface Props {
|
|||||||
* Visual variant.
|
* Visual variant.
|
||||||
* primary — text-decoration underline.
|
* primary — text-decoration underline.
|
||||||
* secondary — border-bottom at sm+, no underline on mobile (for icon+label links).
|
* secondary — border-bottom at sm+, no underline on mobile (for icon+label links).
|
||||||
|
* tertiary — like secondary but reversed: bright by default, dims on hover.
|
||||||
* @default 'primary'
|
* @default 'primary'
|
||||||
*/
|
*/
|
||||||
variant?: LinkVariant;
|
variant?: LinkVariant;
|
||||||
@@ -37,6 +38,7 @@ interface Props {
|
|||||||
const VARIANTS = {
|
const VARIANTS = {
|
||||||
primary: 'underline underline-offset-2 hover:opacity-60 transition-opacity',
|
primary: 'underline underline-offset-2 hover:opacity-60 transition-opacity',
|
||||||
secondary: 'no-underline opacity-60 hover:opacity-100 sm:brutal-border-bottom transition-opacity',
|
secondary: 'no-underline opacity-60 hover:opacity-100 sm:brutal-border-bottom transition-opacity',
|
||||||
|
tertiary: 'no-underline opacity-100 hover:opacity-60 sm:brutal-border-bottom transition-opacity',
|
||||||
} as const satisfies Record<LinkVariant, string>;
|
} as const satisfies Record<LinkVariant, string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export async function Footer() {
|
|||||||
<div className="w-full flex flex-row justify-between gap-4">
|
<div className="w-full flex flex-row justify-between gap-4">
|
||||||
<div className="flex flex-wrap items-center gap-6 sm:gap-4">
|
<div className="flex flex-wrap items-center gap-6 sm:gap-4">
|
||||||
{email && (
|
{email && (
|
||||||
<Link href={email.url} external variant="secondary" className="flex items-center gap-1.5 text-sm">
|
<Link href={email.url} external variant="tertiary" className="flex items-center gap-1.5 text-sm">
|
||||||
{email.icon && <InlineSvg svg={email.icon} className="inline-flex w-8 h-8 sm:hidden" />}
|
{email.icon && <InlineSvg svg={email.icon} className="inline-flex w-8 h-8 sm:hidden" />}
|
||||||
<span className="hidden sm:block">{email.label}</span>
|
<span className="hidden sm:block">{email.label}</span>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -33,7 +33,7 @@ export async function Footer() {
|
|||||||
key={social.id}
|
key={social.id}
|
||||||
href={social.url}
|
href={social.url}
|
||||||
external
|
external
|
||||||
variant="secondary"
|
variant="tertiary"
|
||||||
className="flex items-center gap-1.5 text-sm"
|
className="flex items-center gap-1.5 text-sm"
|
||||||
>
|
>
|
||||||
{social.icon && <InlineSvg svg={social.icon} className="inline-flex w-8 h-8 sm:hidden" />}
|
{social.icon && <InlineSvg svg={social.icon} className="inline-flex w-8 h-8 sm:hidden" />}
|
||||||
|
|||||||
Reference in New Issue
Block a user