feat(phase9): SettingsGroup component
Reusable progressive-disclosure wrapper around the native <details> element. Animated chevron, hover + focus-visible affordances, and prefers-reduced-motion guard. Designed to host the six collapsed groups in the Phase 9 SettingsPage restructure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
src/lib/components/SettingsGroup.svelte
Normal file
55
src/lib/components/SettingsGroup.svelte
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
// Phase 9. Progressive-disclosure wrapper around the native <details>
|
||||||
|
// element. The chevron animates on open via a CSS transform; height
|
||||||
|
// animation uses interpolate-size where the engine supports it
|
||||||
|
// (modern Chromium / WebKit), and falls back to instant open/close
|
||||||
|
// elsewhere. prefers-reduced-motion disables both.
|
||||||
|
import { ChevronRight } from "lucide-svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
open?: boolean;
|
||||||
|
children?: import("svelte").Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { title, description = "", open = false, children }: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<details {open} class="settings-group border-t border-border-subtle">
|
||||||
|
<summary
|
||||||
|
class="flex items-start gap-2 cursor-pointer list-none py-3 px-1 rounded hover:bg-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent"
|
||||||
|
>
|
||||||
|
<ChevronRight
|
||||||
|
class="chevron size-4 mt-0.5 shrink-0 text-text-tertiary"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
<div class="flex-1">
|
||||||
|
<p class="text-sm text-text font-medium">{title}</p>
|
||||||
|
{#if description}
|
||||||
|
<p class="text-[11px] text-text-tertiary mt-0.5">{description}</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</summary>
|
||||||
|
<div class="pl-6 pr-2 pb-3">
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.settings-group :global(summary)::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
:global(.chevron) {
|
||||||
|
transition: transform 180ms ease;
|
||||||
|
}
|
||||||
|
details[open] > summary :global(.chevron) {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
:global(.chevron) {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user