Files
cairnobs/web/src/lib/components/ui/Select.svelte
T
jcoffey-dev f1a68455e0 Build the ui/ component library and persistent app shell
Button, Input, Select, Badge, SeverityBadge, Table, Card, Modal,
Tooltip, Tabs, Skeleton, EmptyState -- a shared library so pages stop
hand-rolling markup per page (web/src/lib/components/ui, barrel export
in index.ts). Modal and CommandPalette are built on native <dialog>
for a real focus trap, Escape-to-close, and top-layer stacking instead
of hand-rolling those. Tabs uses roving tabindex with arrow-key nav.

NavSidebar replaces the old top-nav with a persistent sidebar
(Search/Dashboards/Alerts/Data Sources/Settings), a live tenant
indicator (api.ts's new getCurrentSession(), a client for the
already-existing POST /internal/authorize -- zero new backend surface),
theme/density quick-toggles, and a command-palette hint. Collapses to
an off-canvas drawer under 860px. CommandPalette (Cmd/Ctrl+K) indexes
the five static destinations plus live-fetched dashboards/alert rules.

Data Sources is a new, honestly-scoped placeholder page (one data
source per tenant today, no UI needed yet). Settings and Select-tenant
are re-tokened onto the new component library. +layout.svelte's content
wrapper is a plain <div>, not a second <main> -- every page already
renders its own top-level <main>.
2026-08-16 12:35:25 -07:00

61 lines
1.2 KiB
Svelte

<script lang="ts">
import type { Snippet } from 'svelte';
let {
value = $bindable(''),
disabled = false,
id,
children,
...rest
}: {
value?: string;
disabled?: boolean;
id?: string;
children: Snippet;
[key: string]: unknown;
} = $props();
</script>
<div class="wrap">
<select {id} {disabled} bind:value class="select" {...rest}>
{@render children()}
</select>
<span class="chev" aria-hidden="true"></span>
</div>
<style>
.wrap {
position: relative;
display: inline-block;
}
.select {
appearance: none;
height: var(--control-height);
padding: 0 var(--space-6) 0 var(--space-3);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
color: var(--color-text);
font-family: var(--font-ui);
font-size: var(--text-base);
width: 100%;
cursor: pointer;
}
.select:hover:not(:disabled) {
border-color: var(--color-border-strong);
}
.select:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.chev {
position: absolute;
right: var(--space-3);
top: 50%;
transform: translateY(-50%);
color: var(--color-text-muted);
pointer-events: none;
font-size: var(--text-sm);
}
</style>