Github

Toggle

A button with aria-pressed. Default is ghost until pressed (muted fill). .toggle-outline adds a hairline. Sizes: toggle-sm / toggle-lg. The bookmark icon can stay stroke-only, or take fill="currentColor" when pressed. There is no wrapper.

Preview

Code

<script>
	let on = $state(false);
	let outline = $state(true);
	let sm = $state(false);
	let mid = $state(false);
	let lg = $state(false);
</script>

<button
	class="toggle"
	type="button"
	aria-pressed={on}
	aria-label="Bookmark"
	onclick={() => on = !on}
>
	<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
		<path d="M6 4h10v16l-5-3-5 3z"></path>
	</svg>
	Bookmark
</button>

<button class="toggle toggle-outline" type="button" aria-pressed={outline} onclick={() => outline = !outline}>Outline</button>
<button class="toggle toggle-sm" type="button" aria-pressed={sm} onclick={() => sm = !sm}>Small</button>
<button class="toggle" type="button" aria-pressed={mid} onclick={() => mid = !mid}>Default</button>
<button class="toggle toggle-lg" type="button" aria-pressed={lg} onclick={() => lg = !lg}>Large</button>

Pressed fill

<script>
	let saved = $state(true);
</script>

<button
	class="toggle"
	type="button"
	aria-pressed={saved}
	aria-label="Bookmark"
	onclick={() => saved = !saved}
>
	<svg viewBox="0 0 24 24" fill={saved ? "currentColor" : "none"} stroke="currentColor" stroke-width="2" aria-hidden="true">
		<path d="M6 4h10v16l-5-3-5 3z"></path>
	</svg>
	Bookmark
</button>