feat(frontend): i18n shared state components + UsersAdminPage + CHANGELOG

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Knacky
2026-06-21 23:56:47 +02:00
parent ad0a3f5cac
commit 2931e4aaf9
8 changed files with 125 additions and 69 deletions

View File

@@ -1,6 +1,8 @@
import { useTranslation } from 'react-i18next';
import { useToast } from '@/hooks/useToast';
export function ToastViewport(): JSX.Element {
const { t } = useTranslation();
const { toasts, dismiss } = useToast();
return (
<div
@@ -8,9 +10,9 @@ export function ToastViewport(): JSX.Element {
aria-atomic="true"
className="fixed bottom-xl right-xl z-50 flex flex-col gap-sm w-[320px] pointer-events-none"
>
{toasts.map((t) => {
const isError = t.kind === 'error';
const isSuccess = t.kind === 'success';
{toasts.map((toast) => {
const isError = toast.kind === 'error';
const isSuccess = toast.kind === 'success';
const surface = isError
? 'bg-paper text-ink border border-hairline border-l-4 border-l-bloom-deep'
: isSuccess
@@ -18,18 +20,18 @@ export function ToastViewport(): JSX.Element {
: 'bg-paper text-ink border border-hairline border-l-4 border-l-primary';
return (
<div
key={t.id}
key={toast.id}
role="status"
data-testid="toast"
data-kind={t.kind}
data-kind={toast.kind}
className={`pointer-events-auto rounded-none px-md py-sm text-[14px] leading-[1.4] ${surface}`}
>
<div className="flex items-start justify-between gap-sm">
<span className="flex-1">{t.message}</span>
<span className="flex-1">{toast.message}</span>
<button
type="button"
onClick={() => dismiss(t.id)}
aria-label="Dismiss notification"
onClick={() => dismiss(toast.id)}
aria-label={t('toast.dismiss')}
className="text-current opacity-70 hover:opacity-100"
>
×