Add Field

This commit is contained in:
venashial
2022-06-13 12:48:43 -07:00
parent 496c08b075
commit aa88115d45
15 changed files with 97 additions and 70 deletions

View File

@@ -48,7 +48,8 @@
stroke-linejoin="round"
stroke-miterlimit="1.5"
clip-rule="evenodd"
viewBox="0 0 104 104">
viewBox="0 0 104 104"
aria-hidden="true">
<path fill="none" d="M0 0h103.4v103.4H0z" />
<path
fill="none"

View File

@@ -1,7 +1,7 @@
<script lang="ts">
// TODO: sizes
// TODO: icon only buttons should have uniform padding
import { createEventDispatcher } from 'svelte'
import { classCombine } from '../utils/classCombine'
/** The element to be styled as a button */
@@ -42,16 +42,22 @@
`button--color-${color}`,
badge && 'has-badge',
])
const dispatch = createEventDispatcher()
function dispatchClick() {
if (!disabled) dispatch('click')
}
</script>
{#if as === 'a'}
<a class={className} {href} {disabled} {title} {target} on:click>
<a class={className} {href} {disabled} {title} {target} on:click={dispatchClick}>
<slot />
</a>
{:else if as === 'input'}
<input class={className} {value} {disabled} {title} on:click />
<input class={className} {value} {disabled} {title} on:click={dispatchClick} />
{:else}
<svelte:element this={as} class={className} {disabled} {title} on:click>
<svelte:element this={as} class={className} {disabled} {title} on:click={dispatchClick}>
<slot />
</svelte:element>
{/if}
@@ -76,13 +82,14 @@
background-color: var(--color-button-bg);
border-radius: var(--rounded);
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out, transform 0.05s ease-in-out;
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out, transform 0.05s ease-in-out,
outline 0.2s ease-in-out;
&:hover:not(&--color-transparent) {
&:hover:not(&--color-transparent, &:disabled) {
filter: brightness(0.85);
}
&:active:not(&--color-transparent) {
&:active:not(&--color-transparent, &:disabled) {
transform: scale(0.95);
filter: brightness(0.8);
}
@@ -140,9 +147,6 @@
opacity: 50%;
cursor: not-allowed;
filter: grayscale(50%);
/* Not ideal, but preventing events being fired needs to be implemented */
pointer-events: none;
}
&--pad-even {

View File

@@ -0,0 +1,46 @@
<script lang="ts">
import { uniqueId } from '../utils/uniqueId'
export let required = false
export let label: string
export let helper = ''
const id = `field-${uniqueId()}`
</script>
<div class="field">
<label for={id} class="field__label" class:required>
<span class="field__label__title">{@html label}</span>
{#if helper}
<span class="field__label__helper">{helper}</span>
{/if}
</label>
<slot {id} />
</div>
<style lang="postcss">
.field {
display: flex;
flex-direction: column;
gap: 0.5rem;
&__label {
display: flex;
flex-direction: column;
gap: 0;
&__title {
font-weight: var(--font-weight-bold);
:global(i) {
font-weight: var(--font-weight-normal);
}
}
&__helper {
font-size: var(--font-size-sm);
color: var(--color-text-light);
}
}
}
</style>

View File

@@ -1,23 +0,0 @@
<script lang="ts">
import { uniqueId } from '../utils/uniqueId'
export let required = false
export let label: string
const id = `form-field-${uniqueId()}`
</script>
<div class="form-field">
<label for={id} class="text-input__label" class:required>
{label}
</label>
<slot {id} />
</div>
<style lang="postcss">
.form-field {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
</style>

View File

@@ -6,6 +6,7 @@
import IconExclamation from 'virtual:icons/heroicons-outline/exclamation'
import IconTrash from 'virtual:icons/heroicons-outline/trash'
import { markdown } from '../utils'
import Field from './Field.svelte'
export let key: string
export let type: 'project' | 'version' | 'account' | 'image'
@@ -22,10 +23,12 @@
</div>
{/if}
{@html markdown($t(`modal.deletion.${type}.description`))}
<span class="verify-label">{@html $t('modal.deletion.generic.verify', { values: { key } })}</span>
<TextInput
placeholder={$t('modal.deletion.generic.placeholder', { values: { key } })}
bind:value={keyInput} />
<Field label={$t('modal.deletion.generic.verify', { values: { key } })} let:id>
<TextInput
placeholder={$t('modal.deletion.generic.placeholder', { values: { key } })}
bind:value={keyInput}
{id} />
</Field>
<Button color="danger" slot="button" disabled={key !== keyInput}>
<IconTrash />
{$t(`modal.deletion.${type}.action`)}
@@ -50,12 +53,4 @@
width: 1.5rem;
}
}
.verify-label {
font-weight: var(--font-weight-bold);
}
:global(i) {
font-weight: var(--font-weight-normal);
}
</style>

View File

@@ -44,7 +44,7 @@
class:is-active={query
? ($page.url.searchParams.get(query) || '') === link.href
: path[level] === link.href || path[level] === link.href.slice(0, -1)}
sveltekit:noscroll={!resetScroll}>{link.label}</a>
sveltekit:noscroll={!resetScroll || null}>{link.label}</a>
{/each}
</nav>

View File

@@ -68,7 +68,7 @@
if (!open) {
open = true
// Needs delay before trying to move focus
setTimeout(() => element.children[1].children[0].focus(), 0)
setTimeout(() => (element.children[1].children[0] as HTMLButtonElement).focus(), 0)
} else {
const option = options.find(
({ label }) => label === document.activeElement.innerHTML.trim()
@@ -112,12 +112,15 @@
transition:fade={{ duration: 70 }}
class="select__options"
style:--selected-index={options.indexOf(selected)}>
{#each options as option (option.value)}
{#each options as option, index (option.value)}
{@const isSelected = selected?.value === option.value}
<button
on:click={() => selectOption(option)}
class:is-selected={isSelected}
tabindex={isSelected ? -1 : 0}>
tabindex={isSelected ? -1 : 0}
on:focusout={() => {
if (index + 1 === options.length) open = false
}}>
{option.label || option.value}
{#if selected?.value === option.value}
<IconCheck />

View File

@@ -6,7 +6,7 @@
</script>
<div class="slider">
<input class="slider-input" type="range" name={id} {min} {max} bind:value />
<input class="slider__input" type="range" {id} {min} {max} bind:value />
<span>{value}</span>
</div>
@@ -17,7 +17,7 @@
align-items: center;
gap: 0.5rem;
.slider-input {
&__input {
-webkit-appearance: none;
appearance: none;
border-radius: var(--rounded-sm);

View File

@@ -11,9 +11,9 @@
<div class="text-input" class:fill>
{#if multiline}
<textarea name={id} {placeholder} bind:value />
<textarea {id} {placeholder} bind:value />
{:else}
<input type="text" name={id} {placeholder} bind:value class:has-icon={icon} />
<input type="text" {id} {placeholder} bind:value class:has-icon={icon} />
{#if icon}
<svelte:component this={icon} />
{/if}