feat(settings): add SettingsCard component with title, href, cta, meta, accent props

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 16:24:38 +02:00
parent 33cccd3d63
commit 3f9fb900c4
2 changed files with 75 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
<script lang="ts">
interface Props {
title: string;
href: string;
cta: string;
meta?: string;
accent?: boolean;
}
let { title, href, cta, meta, accent = false }: Props = $props();
</script>
<a
{href}
data-accent={accent ? 'true' : undefined}
class="flex flex-col gap-3 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface)] p-4 no-underline text-[var(--color-text)] hover:shadow-[var(--shadow-raised)] hover:border-[#C0BFB8] transition-[box-shadow,border-color] duration-150 ease focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--green-dark)] focus-visible:outline-offset-2"
style={accent ? 'border-left: 3px solid var(--green-dark);' : undefined}
>
<span class="font-[var(--font-sans)] text-[14px] font-medium text-[var(--color-text)]">
{title}
</span>
{#if meta}
<p data-testid="card-meta" class="font-[var(--font-sans)] text-[13px] text-[var(--color-text-muted)] m-0">
{meta}
</p>
{/if}
<span class="font-[var(--font-sans)] text-[12px] font-medium text-[var(--green-dark)] mt-auto">
{cta}
</span>
</a>

View File

@@ -0,0 +1,43 @@
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/svelte';
import SettingsCard from './SettingsCard.svelte';
describe('SettingsCard', () => {
it('renders the title', () => {
render(SettingsCard, { props: { title: 'Vorräte', href: '/household/staples', cta: 'Vorräte bearbeiten →' } });
expect(screen.getByText('Vorräte')).toBeInTheDocument();
});
it('renders as an anchor tag with the given href', () => {
render(SettingsCard, { props: { title: 'Vorräte', href: '/household/staples?ctx=settings', cta: 'Bearbeiten →' } });
const link = screen.getByRole('link');
expect(link).toHaveAttribute('href', '/household/staples?ctx=settings');
});
it('renders the cta text', () => {
render(SettingsCard, { props: { title: 'Vorräte', href: '/household/staples', cta: 'Vorräte bearbeiten →' } });
expect(screen.getByText('Vorräte bearbeiten →')).toBeInTheDocument();
});
it('renders meta text when provided', () => {
render(SettingsCard, { props: { title: 'Haushalt', href: '/members', cta: 'Mitglieder anzeigen →', meta: '3 Mitglieder' } });
expect(screen.getByText('3 Mitglieder')).toBeInTheDocument();
});
it('does not render meta element when meta is not provided', () => {
render(SettingsCard, { props: { title: 'Haushalt', href: '/members', cta: 'Mitglieder anzeigen →' } });
expect(screen.queryByTestId('card-meta')).not.toBeInTheDocument();
});
it('applies accent border style when accent=true', () => {
render(SettingsCard, { props: { title: 'Vorräte', href: '/household/staples', cta: 'Bearbeiten →', accent: true } });
const link = screen.getByRole('link');
expect(link).toHaveAttribute('data-accent', 'true');
});
it('does not apply accent when accent is not set', () => {
render(SettingsCard, { props: { title: 'Haushalt', href: '/members', cta: 'Anzeigen →' } });
const link = screen.getByRole('link');
expect(link).not.toHaveAttribute('data-accent', 'true');
});
});