initial stuff

This commit is contained in:
Henri
2025-11-21 08:15:07 +02:00
parent a38a367ac5
commit 8c18827dc5
33 changed files with 522 additions and 148 deletions

View File

@@ -1,20 +1,27 @@
<script>
export let onClick = () => {}
export let onClick = () => {};
</script>
<button on:click={onClick} class="btn">
<button onclick={onClick} class="btn">
<slot />
</button>
<style>
.btn {
background: var(--button-bg);
color: var(--button-text);
background: var(--white);
color: var(--black);
border-radius: 8px;
border: 1px solid transparent;
border: 1.5px solid transparent;
border-color: var(--orange);
padding: 0.6em 1.2em;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5em;
}
.btn:hover { border-color: var(--primary); }
</style>
.btn:hover {
background: var(--orange);
}
</style>

View File

@@ -0,0 +1,26 @@
<script>
export let onClick = () => {};
</script>
<button onclick={onClick} class="btn">
<slot />
</button>
<style>
.btn {
background: var(--white);
color: var(--black);
border-radius: 8px;
border: 1.5px solid transparent;
padding: 0.6em 1.2em;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5em;
}
.btn:hover {
background: var(--orange);
}
</style>

View File

@@ -1,8 +0,0 @@
<script>
export let className = '';
export let as = 'div';
</script>
<svelte:component this={as} class={`card ${className}`}>
<slot />
</svelte:component>

View File

@@ -1,9 +0,0 @@
<script>
export let fluid = false; // when true, removes max-width
export let className = '';
export let as = 'div';
</script>
<svelte:component this={as} class={`container ${fluid ? 'container--fluid' : ''} ${className}`}>
<slot />
</svelte:component>

View File

@@ -0,0 +1,71 @@
<script>
import Button from "./Button.svelte";
import ButtonBorderless from "./ButtonBorderless.svelte";
// Props
export let name = "";
export let variant = "default"; // 'default' | 'borderless' aka 'Button' | 'ButtonBorderless'
let isOpen = false;
const toggle = () => (isOpen = !isOpen);
const close = () => (isOpen = false);
function handleFocusOut({ relatedTarget, currentTarget }) {
if (
relatedTarget instanceof HTMLElement &&
currentTarget.contains(relatedTarget)
)
return;
close();
}
</script>
<div class="relative inline-block" on:focusout={handleFocusOut}>
{#if variant === "borderless"}
<ButtonBorderless onClick={toggle}>
{name}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
class="w-5 ml-2 mt-1 transition-transform inline-block"
style:transform={isOpen ? "rotate(180deg)" : "none"}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m19.5 8.25-7.5 7.5-7.5-7.5"
/>
</svg>
</ButtonBorderless>
{:else}
<Button onClick={toggle}>
{name}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
class="w-5 ml-2 mt-1 transition-transform inline-block"
style:transform={isOpen ? "rotate(180deg)" : "none"}
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m19.5 8.25-7.5 7.5-7.5-7.5"
/>
</svg>
</Button>
{/if}
<div
class="absolute mt-2 rounded-md shadow-lg bg-white ring-1 ring-black/5 overflow-hidden flex flex-col"
style:visibility={isOpen ? "visible" : "hidden"}
>
<slot />
</div>
</div>

View File

@@ -1,10 +0,0 @@
<script>
export let min = '220px'; // minimum column width
export let gap = 'var(--space-3)';
export let className = '';
export let as = 'div';
</script>
<svelte:component this={as} class={`grid ${className}`} style={`grid-template-columns: repeat(auto-fit, minmax(${min}, 1fr)); gap: ${gap};`}>
<slot />
</svelte:component>

View File

@@ -1,11 +0,0 @@
<script>
// Vertical stack helper. Accepts a gap and alignment so pages can tune spacing.
export let gap = 'var(--space-3)';
export let align = 'stretch';
export let className = '';
export let as = 'div';
</script>
<svelte:component this={as} class={`stack ${className}`} style={`gap: ${gap}; align-items: ${align};`}>
<slot />
</svelte:component>

View File

@@ -1,5 +1,8 @@
export { default as Container } from './Container.svelte'
export { default as Card } from './Card.svelte'
export { default as Stack } from './Stack.svelte'
export { default as Grid } from './Grid.svelte'
export { default as Container } from './layout/Container.svelte'
export { default as Card } from './layout/Card.svelte'
export { default as Stack } from './layout/Stack.svelte'
export { default as Grid } from './layout/Grid.svelte'
export { default as Button } from './Button.svelte'
export { default as ButtonBorderless } from './ButtonBorderless.svelte'
export { default as Dropdown } from './Dropdown.svelte'

View File

@@ -0,0 +1,12 @@
<!--
A simple presentational container that renders a `div` with the `card` class.
-->
<script>
export let className = "";
export let background = "var(--off-white)";
</script>
<div class={`card ${className}`} style="background: {background}">
<slot />
</div>

View File

@@ -0,0 +1,15 @@
<!--
A responsive container that centers content and optionally
removes the max-width when `fluid` is true. Use `className` to
add additional CSS classes to the root element. Content is
projected via the default slot.
-->
<script>
export let fluid = false; // true removes max-width
export let className = "";
</script>
<div class={`container ${fluid ? "container--fluid" : ""} ${className}`}>
<slot />
</div>

View File

@@ -0,0 +1,18 @@
<!--
A responsive grid wrapper using CSS Grid. It exposes `min` and
`gap` props to control the responsive column minimum width and
spacing. Content is projected into the default slot.
-->
<script>
export let min = "220px"; // minimum column width
export let gap = "var(--space-3)";
export let className = "";
</script>
<div
class={`grid ${className}`}
style={`grid-template-columns: repeat(auto-fit, minmax(${min}, 1fr)); gap: ${gap};`}
>
<slot />
</div>

View File

@@ -0,0 +1,13 @@
<!--
A simple stack/column layout that stacks children vertically.
-->
<script>
export let gap = "var(--space-3)";
export let align = "stretch";
export let className = "";
</script>
<div class={`stack ${className}`} style={`gap: ${gap}; align-items: ${align};`}>
<slot />
</div>