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:
32
frontend/src/lib/components/SettingsCard.svelte
Normal file
32
frontend/src/lib/components/SettingsCard.svelte
Normal 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>
|
||||
43
frontend/src/lib/components/SettingsCard.test.ts
Normal file
43
frontend/src/lib/components/SettingsCard.test.ts
Normal 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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user