aboutsummaryrefslogtreecommitdiffstats
path: root/apps/kit/src
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-09-28 17:05:08 +0200
committerivarlovlie <git@ivarlovlie.no>2022-09-28 17:05:08 +0200
commitf24de70526d6cb20edfc21bf1ded9c7b405a4f3b (patch)
treeb22ec77eb255210a960e1fac020915034bae9366 /apps/kit/src
parentaa79ab6d0e3699118aae0ffde6b2c19192b544d5 (diff)
downloadgreatoffice-f24de70526d6cb20edfc21bf1ded9c7b405a4f3b.tar.xz
greatoffice-f24de70526d6cb20edfc21bf1ded9c7b405a4f3b.zip
feat: Add input component
Diffstat (limited to 'apps/kit/src')
-rw-r--r--apps/kit/src/lib/components/icons/exclamation-circle.svelte13
-rw-r--r--apps/kit/src/lib/components/icons/index.ts3
-rw-r--r--apps/kit/src/lib/components/input.svelte121
-rw-r--r--apps/kit/src/routes/book/inputs/+page.svelte48
4 files changed, 185 insertions, 0 deletions
diff --git a/apps/kit/src/lib/components/icons/exclamation-circle.svelte b/apps/kit/src/lib/components/icons/exclamation-circle.svelte
new file mode 100644
index 0000000..2ce79b1
--- /dev/null
+++ b/apps/kit/src/lib/components/icons/exclamation-circle.svelte
@@ -0,0 +1,13 @@
+<svg
+ class="h-5 w-5 {$$restProps.class ?? ''}"
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ aria-hidden="true"
+>
+ <path
+ fill-rule="evenodd"
+ d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
+ clip-rule="evenodd"
+ />
+</svg>
diff --git a/apps/kit/src/lib/components/icons/index.ts b/apps/kit/src/lib/components/icons/index.ts
index b220f37..e846dc4 100644
--- a/apps/kit/src/lib/components/icons/index.ts
+++ b/apps/kit/src/lib/components/icons/index.ts
@@ -9,6 +9,8 @@ import XCircle from "./x-circle.svelte";
import CheckCircle from "./check-circle.svelte";
import XMark from "./x-mark.svelte";
import Spinner from "./spinner.svelte";
+import ExclamationCircle from "./exclamation-circle.svelte";
+
export {
XIcon,
MenuIcon,
@@ -17,6 +19,7 @@ export {
AdjustmentsIcon,
InformationCircle,
ExclamationTriangle,
+ ExclamationCircle,
XCircle,
CheckCircle,
XMark,
diff --git a/apps/kit/src/lib/components/input.svelte b/apps/kit/src/lib/components/input.svelte
new file mode 100644
index 0000000..0847f3e
--- /dev/null
+++ b/apps/kit/src/lib/components/input.svelte
@@ -0,0 +1,121 @@
+<script lang="ts">
+ import { random_string } from "$lib/helpers";
+ import { ExclamationCircle } from "./icons";
+
+ export let label: string | undefined = undefined;
+ export let type: string = "text";
+ export let id: string | undefined = "input__" + random_string(4);
+ export let name: string | undefined = undefined;
+ export let placeholder: string | undefined = undefined;
+ export let helpText: string | undefined = undefined;
+ export let errorText: string | undefined = undefined;
+ export let disabled = false;
+ export let hideLabel = false;
+ export let cornerHint: string | undefined = undefined;
+ export let icon: any = undefined;
+ export let addon: string | undefined = undefined;
+ export let value: string | undefined;
+
+ $: ariaErrorDescribedBy = id + "__" + "error";
+ $: attributes = {
+ "aria-describedby": errorText ? ariaErrorDescribedBy : null,
+ "aria-invalid": errorText ? "true" : null,
+ disabled: disabled || null,
+ } as any;
+ $: hasBling = icon || addon || errorText;
+ const defaultColorClass =
+ "border-gray-300 focus:border-teal-500 focus:ring-teal-500";
+ let colorClass = defaultColorClass;
+ $: if (errorText) {
+ colorClass =
+ "placeholder-red-300 focus:border-red-500 focus:outline-none focus:ring-red-500 text-red-900 pr-10 border-red-300";
+ } else {
+ colorClass = defaultColorClass;
+ }
+
+ function typeAction(node: HTMLInputElement) {
+ node.type = type;
+ }
+</script>
+
+<div>
+ {#if label && !cornerHint && !hideLabel}
+ <label
+ for={id}
+ class={hideLabel
+ ? "sr-only"
+ : "block text-sm font-medium text-gray-700"}
+ >
+ {label}
+ </label>
+ {:else if cornerHint && !hideLabel}
+ <div class="flex justify-between">
+ {#if label}
+ <label
+ for={id}
+ class={hideLabel
+ ? "sr-only"
+ : "block text-sm font-medium text-gray-700"}
+ >
+ {label}
+ </label>
+ {/if}
+ <span class="text-sm text-gray-500">
+ {cornerHint}
+ </span>
+ </div>
+ {/if}
+ <div
+ class="mt-1 {hasBling ? 'relative rounded-md' : ''} {addon
+ ? 'flex'
+ : ''}"
+ >
+ {#if icon}
+ <div
+ class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"
+ >
+ <svelte:component
+ this={icon}
+ class={errorText ? "text-red-500" : "text-gray-400"}
+ />
+ </div>
+ {:else if addon}
+ <div
+ class="inline-flex items-center rounded-l-md border border-r-0 border-gray-300 bg-gray-50 px-3 text-gray-500 sm:text-sm"
+ >
+ <span class="text-gray-500 sm:text-sm">{addon}</span>
+ </div>
+ {/if}
+ <input
+ use:typeAction
+ {name}
+ {id}
+ {...attributes}
+ bind:value
+ class="block w-full rounded-md shadow-sm sm:text-sm {colorClass} {disabled
+ ? 'disabled:cursor-not-allowed disabled:border-gray-200 disabled:bg-gray-50 disabled:text-gray-500'
+ : ''}
+ {addon ? 'min-w-0 flex-1 rounded-none rounded-r-md' : ''} {icon
+ ? 'pl-10'
+ : ''}"
+ {placeholder}
+ />
+ {#if errorText}
+ <div
+ class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3"
+ >
+ <ExclamationCircle class="text-red-500" />
+ </div>
+ {/if}
+ </div>
+ {#if helpText && !errorText}
+ <p class="mt-2 text-sm text-gray-500">
+ {helpText}
+ </p>
+ {/if}
+ {#if errorText}
+ <p class="mt-2 text-sm text-red-600" id={ariaErrorDescribedBy}>
+ {errorText}
+ </p>
+ {/if}
+</div>
diff --git a/apps/kit/src/routes/book/inputs/+page.svelte b/apps/kit/src/routes/book/inputs/+page.svelte
new file mode 100644
index 0000000..a693f69
--- /dev/null
+++ b/apps/kit/src/routes/book/inputs/+page.svelte
@@ -0,0 +1,48 @@
+<script lang="ts">
+ import Input from "$lib/components/input.svelte";
+ import { DatabaseIcon } from "$lib/components/icons";
+</script>
+
+<section>
+ <h2>Default</h2>
+ <Input label="Input me" placeholder="Hello" />
+</section>
+
+<section>
+ <h2>With icon</h2>
+ <Input label="Input me" placeholder="Hello" icon={DatabaseIcon} />
+</section>
+
+<section>
+ <h2>With corner hint</h2>
+ <Input label="Input me ->" placeholder="Hello" cornerHint="Hint hint" />
+</section>
+
+<section>
+ <h2>Disabled</h2>
+ <Input label="No" placeholder="Sorry" disabled />
+</section>
+
+<section>
+ <h2>Errored</h2>
+ <Input
+ label="No"
+ placeholder="Sorry"
+ errorText="That's not right"
+ icon={DatabaseIcon}
+ />
+</section>
+
+<section>
+ <h2>Help</h2>
+ <Input label="Go ahead" placeholder="Write here" helpText="Write above" />
+</section>
+<section>
+ <h2>Addon</h2>
+ <Input
+ label="Go ahead"
+ placeholder="Write here"
+ helpText="Write above"
+ addon="To the right"
+ />
+</section>