d14f86478a
New token system in global.css (near-white surfaces, one ink-blue accent, no sub-12px type), self-hosted Schibsted Grotesk, rewritten primitives (buttons, fields, modal shell, segmented, disclosure, skeleton), a borderless 56px header with an SV | EN language toggle, an Icon component replacing glyphs, page skeletons that keep the layout during loading, and leave-type colours moved out of TS into CSS variables. Feature blocks keep their structure for later phases. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
32 lines
989 B
TypeScript
32 lines
989 B
TypeScript
import { ReactNode } from 'react'
|
|
import { useTranslation } from '@/i18n'
|
|
import './loading-spinner.css'
|
|
|
|
interface LoadingSpinnerProps {
|
|
message?: string | undefined
|
|
ariaLabel?: string | undefined
|
|
}
|
|
|
|
/**
|
|
* A ring spinner with a message. Defaults come from the i18n bundle so a
|
|
* bare `<LoadingSpinner />` reads correctly in either language; callers
|
|
* with a more specific message ("Laddar kalender…") pass it in.
|
|
*/
|
|
export function LoadingSpinner({ message, ariaLabel }: LoadingSpinnerProps): ReactNode {
|
|
const { t } = useTranslation()
|
|
return (
|
|
<div
|
|
className="loading-spinner"
|
|
role="status"
|
|
aria-label={ariaLabel ?? t('common.loading')}
|
|
aria-busy={true}
|
|
data-testid="loading-spinner"
|
|
>
|
|
<div className="loading-spinner__icon" data-testid="spinner-icon" role="presentation" />
|
|
<p className="loading-spinner__message" data-testid="spinner-message">
|
|
{message ?? t('common.loadingEllipsis')}
|
|
</p>
|
|
</div>
|
|
)
|
|
}
|