70 lines
1.5 KiB
Svelte
70 lines
1.5 KiB
Svelte
<script lang="ts">
|
|
import type { Snippet } from 'svelte';
|
|
import Icon from '@iconify/svelte';
|
|
|
|
let {
|
|
title,
|
|
icon,
|
|
href,
|
|
onclick,
|
|
children
|
|
}: { title?: string; icon?: string; href?: string; onclick?: () => void; children?: Snippet } = $props();
|
|
|
|
function handleKeydown(event: KeyboardEvent) {
|
|
if (!onclick || (event.key !== 'Enter' && event.key !== ' ')) return;
|
|
event.preventDefault();
|
|
onclick();
|
|
}
|
|
</script>
|
|
|
|
<svelte:element
|
|
this={href ? 'a' : 'article'}
|
|
class="panel"
|
|
class:linked={!!href || !!onclick}
|
|
{href}
|
|
role={onclick ? 'button' : undefined}
|
|
tabindex={onclick ? 0 : undefined}
|
|
{onclick}
|
|
onkeydown={onclick ? handleKeydown : undefined}
|
|
target={href?.startsWith('http') ? '_blank' : undefined}
|
|
rel={href?.startsWith('http') ? 'noopener noreferrer' : undefined}
|
|
>
|
|
{#if title}
|
|
<header class="panel-title">
|
|
{#if icon}
|
|
<Icon {icon} width="16" />
|
|
{/if}
|
|
<span>{title}</span>
|
|
</header>
|
|
{/if}
|
|
{@render children?.()}
|
|
</svelte:element>
|
|
|
|
<style>
|
|
.panel {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
padding: 0.8rem 0.9rem;
|
|
border: 1px solid color-mix(in srgb, var(--foreground) 22%, transparent);
|
|
background: color-mix(in srgb, var(--foreground) 3%, transparent);
|
|
}
|
|
|
|
.linked {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.linked:hover {
|
|
border-color: var(--accent);
|
|
background: color-mix(in srgb, var(--foreground) 7%, transparent);
|
|
}
|
|
|
|
.panel-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
color: var(--accent);
|
|
font-weight: 700;
|
|
}
|
|
</style>
|