Files
web-pwa/src/lib/components/ui/Textbox.svelte
2026-03-16 20:31:28 +00:00

95 lines
1.7 KiB
Svelte

<script lang="ts">
import { fade } from 'svelte/transition';
import type { HTMLInputAttributes } from 'svelte/elements';
interface Props extends HTMLInputAttributes {
value?: string;
label?: string;
placeholder?: string;
type?: 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url';
error?: string;
uppercase?: boolean;
[key: string]: any;
}
let {
value = $bindable(''),
label,
placeholder = '',
type = 'text',
error = '',
uppercase = false,
...rest
}: Props = $props();
let isFocussed = $state(false);
</script>
<div class="input-wrapper" class:focussed={isFocussed} class:has-error={!!error}>
{#if label}
<label for="adaptive-input">{label}</label>
{/if}
<input
id="adaptive-input"
class:all-caps={uppercase}
{type}
{placeholder}
bind:value
onfocus={() => (isFocussed = true)}
onblur={() => (isFocussed = false)}
{...rest}
/>
{#if error}
<span class="error-message" transition:fade>{error}</span>
{/if}
</div>
<style>
.input-wrapper {
display: flex;
flex-direction: column;
gap: 8px;
width: 100%;
font-family: 'URW Gothic', sans-serif;
}
label {
font-size: 0.9rem;
font-weight: 400;
color: var(--color-title);
}
input {
min-height: 40px;
padding: 0 16px;
background-color: var(--color-title);
border: 2px solid transparent;
border-radius: 20px;
color: var(--color-bg-dark);
font-size: 1.2rem;
transition: all 0.2s ease-in-out;
outline: none;
text-align: center;
}
.all-caps {
text-transform: uppercase;
}
.focussed input {
border-color: var(--color-bg-light);
}
.has-error input {
border-color: #ff4d4d;
}
.error-message {
color: #ff4d4d;
font-size: 1rem;
text-align: center;
}
</style>