This repository has no description
1<script module lang="ts">
2 import { tv } from "tailwind-variants";
3
4 export const pipelineSearch = tv({
5 slots: {
6 form: "flex w-full",
7 field: "relative flex w-full items-center",
8 input: "w-full",
9 clear: "absolute right-0.5"
10 },
11 variants: {
12 // room for the clear button so the text does not run under it
13 filled: {
14 true: { input: "pr-9" },
15 false: {}
16 }
17 },
18 defaultVariants: {
19 filled: false
20 }
21 });
22</script>
23
24<script lang="ts">
25 import { page } from "$app/state";
26 import Search from "$icon/search";
27 import X from "$icon/x";
28 import Button from "$lib/components/ui/Button.svelte";
29 import Input from "$lib/components/ui/Input.svelte";
30 import type { PipelineFilter } from "./pipeline";
31
32 interface Props {
33 /** kept in the form so searching does not reset the tab */
34 filter: PipelineFilter;
35 }
36
37 let { filter }: Props = $props();
38
39 let form: HTMLFormElement;
40 // seed from the url so the query (and the clear button) survive a submit
41 let value = $state(page.url.searchParams.get("q") ?? "");
42
43 const clear = () => {
44 value = "";
45 form.requestSubmit();
46 };
47
48 const classes = $derived(pipelineSearch({ filled: value !== "" }));
49</script>
50
51<form bind:this={form} class={classes.form()} method="GET">
52 {#if filter !== "all"}
53 <input type="hidden" name="trigger" value={filter} />
54 {/if}
55
56 <div class={classes.field()}>
57 <Input
58 bind:value
59 type="text"
60 name="q"
61 placeholder="Search pipelines..."
62 aria-label="Search pipelines"
63 iconLeft={Search}
64 class={classes.input()}
65 />
66 {#if value}
67 <Button
68 type="button"
69 variant="ghost"
70 size="sm"
71 icon={X}
72 onclick={clear}
73 aria-label="Clear search"
74 class={classes.clear()}
75 />
76 {/if}
77 </div>
78</form>