This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / components / repo / pipelines / PipelineSearch.svelte
1.7 kB 78 lines
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>