feat(SearchBar): component redesign

This commit is contained in:
Ilia Mashkov
2026-02-25 10:03:34 +03:00
parent 81d228290b
commit 629dd15628
2 changed files with 22 additions and 40 deletions

View File

@@ -9,8 +9,7 @@ const { Story } = defineMeta({
parameters: {
docs: {
description: {
component:
'Search input with popover dropdown for results/suggestions. Features keyboard navigation (ArrowDown/Up/Enter) and auto-focus prevention on popover open. The input field serves as the popover trigger.',
component: 'Wrapper around Input with a search icon',
},
story: { inline: false }, // Render stories in iframe for state isolation
},
@@ -40,6 +39,6 @@ let defaultSearchValue = $state('');
}}
>
{#snippet template(args)}
<SearchBar bind:value={defaultSearchValue} placeholder="Type here..." {...args} />
<SearchBar variant="filled" {...args} />
{/snippet}
</Story>

View File

@@ -1,44 +1,27 @@
<!-- Component: SearchBar -->
<script lang="ts">
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import { Input } from '$shared/ui';
import AsteriskIcon from '@lucide/svelte/icons/asterisk';
<!--
Component: SearchInput
Convenience wrapper around Input that pre-fills the leftIcon slot with
a Search icon sized to match the current `size` prop.
interface Props {
/**
* Unique identifier for the input element
*/
id?: string;
/**
* Current search value (bindable)
*/
value: string;
/**
* Additional CSS classes for the container
*/
class?: string;
/**
* Placeholder text for the input
*/
placeholder?: string;
}
The consumer can still override rightIcon, add a clear button, etc.
They cannot pass leftIcon — it's owned by this wrapper.
-->
<script lang="ts">
import { Input } from '$shared/ui/Input';
import { inputIconSize } from '$shared/ui/Input/types';
import SearchIcon from '@lucide/svelte/icons/search';
import type { ComponentProps } from 'svelte';
type Props = Exclude<ComponentProps<typeof Input>, 'leftIcon'>;
let {
id = 'search-bar',
value = $bindable(''),
class: className,
placeholder,
...rest
}: Props = $props();
</script>
<div class="relative w-full">
<div class="absolute left-4 sm:left-5 top-1/2 -translate-y-1/2 pointer-events-none z-10">
<AsteriskIcon class="size-3 sm:size-4 stroke-gray-400 stroke-[1.5]" />
</div>
<Input
{id}
class={cn('pl-11 sm:pl-14 md:pl-14 lg:pl-14', className)}
bind:value
{placeholder}
/>
</div>
<Input bind:value {...rest}>
{#snippet leftIcon(size)}
<SearchIcon size={inputIconSize[size]} />
{/snippet}
</Input>