Presets

Blocks

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.

Upgrade
JoinLogin
Presets
Monochrome
Overview
  • Introduction
  • Components
  • Installation
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • CalendarNEW
  • Card
  • CarouselNEW
  • Checkbox
  • Collapsible
  • Dialog
  • Dropdown Menu
  • Empty
  • Field
  • Input
  • Input Group
  • Item
  • Kbd
  • Label
  • Native Select
  • Scroll Area
  • SelectNEW
  • Separator
  • SwitchNEW
  • Table
  • Tabs
  • Textarea
  • TooltipNEW

Input Group

PreviousNext

Add addons, buttons, and helper content to inputs.

1<script lang="ts">
2  import {
3    InputGroup,
4    InputGroupAddon,

Installation

pnpm dlx sprawlify@latest add input-group
npx sprawlify@latest add input-group
yarn sprawlify@latest add input-group
bunx --bun sprawlify@latest add input-group

Install the following dependencies:

pnpm add @sprawlify/primitives @sprawlify/svelte
npm install @sprawlify/primitives @sprawlify/svelte
yarn add @sprawlify/primitives @sprawlify/svelte
bun add @sprawlify/primitives @sprawlify/svelte

Add the following files to your project:

input-group/index.ts
1export { default as InputGroup } from "./input-group.svelte";2export { default as InputGroupAddon } from "./input-group-addon.svelte";3export { default as InputGroupButton } from "./input-group-button.svelte";4export { default as InputGroupText } from "./input-group-text.svelte";5export { default as InputGroupInput } from "./input-group-input.svelte";6export { default as InputGroupTextarea } from "./input-group-textarea.svelte";7
input-group/input-group-addon.svelte
1<script module lang="ts">
2import { cva, type VariantProps } from "class-variance-authority"
3import { cn } from "@/lib/utils"
4
5export const inputGroupAddonVariants = cva(
6  "text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 flex cursor-text items-center justify-center select-none",
7  {
8    variants: {
9      align: {
10        "inline-start": "pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem] order-first",
11        "inline-end": "pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem] order-last",
12        "block-start":
13          "px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start",
14        "block-end":
15          "px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start",
16      },
17    },
18    defaultVariants: {
19      align: "inline-start",
20    },
21  }
22)
23</script>
24
25<script lang="ts">
26import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
27    import type { HTMLAttributes } from "svelte/elements";
28
29interface Props extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof inputGroupAddonVariants>, PolymorphicProps<"div"> {}
30  
31let { class: className, align = "inline-start", children, ...rest }: Props = $props()
32</script>
33
34<Sprawlify
35  as="div"
36  role="group"
37  data-scope="input-group"
38  data-part="addon"
39  data-slot="input-group-addon"
40  data-align={align}
41  class={cn(inputGroupAddonVariants({ align }), className)}
42  onclick={(e) => {
43    if ((e.target as HTMLElement).closest("button")) {
44      return
45    }
46    e.currentTarget?.parentElement?.querySelector("input")?.focus()
47  }}
48  {...rest}
49>
50  {@render children?.()}
51</Sprawlify>
input-group/input-group-button.svelte
1<script module lang="ts">
2import { cva } from "class-variance-authority"
3import { cn } from "@/lib/utils"
4
5export const inputGroupButtonVariants = cva(
6  "gap-2 text-sm shadow-none flex items-center",
7  {
8    variants: {
9      size: {
10        xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
11        sm: "",
12        "icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
13        "icon-sm": "size-8 p-0 has-[>svg]:p-0",
14      },
15    },
16    defaultVariants: {
17      size: "xs",
18    },
19  }
20)
21</script>
22
23<script lang="ts">
24import { Button } from "@/components/ui/button"
25import type { VariantProps } from "class-variance-authority"
26import type { ComponentProps } from "svelte";
27
28interface Props extends Omit<ComponentProps<typeof Button>, "size">, VariantProps<typeof inputGroupButtonVariants> {}
29  
30let { class: className, type = "button", variant = "ghost", size = "xs", ...rest }: Props = $props()
31</script>
32
33<Button
34  data-scope="input-group"
35  data-part="button"
36  type={type}
37  data-size={size}
38  variant={variant}
39  class={cn(inputGroupButtonVariants({ size }), className)}
40  {...rest}
41/>
input-group/input-group-input.svelte
1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Input } from "@/components/ui/input"
4import type { HTMLInputAttributes } from "svelte/elements"
5
6interface Props extends HTMLInputAttributes {}
7  
8let { class: className, ...rest }: Props = $props()
9</script>
10
11<Input
12  data-scope="input-group"
13  data-part="control"
14  data-slot="input-group-control"
15  class={cn("rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1", className)}
16  {...rest}
17/>
input-group/input-group-text.svelte
1<script module lang="ts">
2import { cn } from "@/lib/utils"
3</script>
4
5<script lang="ts">
6import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
7import type { HTMLAttributes } from "svelte/elements"
8
9interface Props extends HTMLAttributes<HTMLSpanElement>, PolymorphicProps<"span"> {}
10  
11let { class: className, children, ...rest }: Props = $props()
12</script>
13
14<Sprawlify
15  as="span"
16  data-scope="input-group"
17  data-part="text"
18  data-slot="input-group-text"
19  class={cn(
20    "text-muted-foreground gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none",
21    className
22  )}
23  {...rest}
24>
25  {@render children?.()}
26</Sprawlify>
input-group/input-group-textarea.svelte
1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Textarea } from "@/components/ui/textarea"
4import type { HTMLTextareaAttributes } from "svelte/elements"
5import type { PolymorphicProps } from "@sprawlify/svelte";
6
7interface Props extends HTMLTextareaAttributes, PolymorphicProps<"textarea"> {}
8  
9let { class: className, ...rest }: Props = $props()
10</script>
11
12<Textarea
13  data-scope="input-group"
14  data-part="control"
15  data-slot="input-group-control"
16  class={cn("rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1 resize-none", className)}
17  {...rest}
18/>
input-group/input-group.svelte
1<script lang="ts">
2import { cn } from "@/lib/utils"
3import { Sprawlify, type PolymorphicProps } from "@sprawlify/svelte"
4import type { HTMLAttributes } from "svelte/elements";
5
6interface Props extends HTMLAttributes<HTMLDivElement>, PolymorphicProps<"div"> {}
7  
8let { class: className, children, ...rest }: Props = $props()
9</script>
10
11<Sprawlify
12  as="div"
13  data-scope="input-group"
14  data-part="root"
15  data-slot="input-group"
16  role="group"
17  class={cn(
18    "border-input bg-input/30 dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 h-8 rounded-lg border transition-colors in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto",
19    className
20  )}
21  {...rest}
22>
23  {@render children?.()}
24</Sprawlify>

Update the import paths to match your project setup.

Usage

1import {
2  InputGroup,
3  InputGroupAddon,
4  InputGroupButton,
5  InputGroupText,
6  InputGroupInput,
7  InputGroupTextarea
8} from "@/components/ui/input-group"
1<InputGroup>
2  <InputGroupInput placeholder="Search..." />
3  <InputGroupAddon>
4    <SearchIcon />
5  </InputGroupAddon>
6</InputGroup>

Examples

Block End

Use align="block-end" to position the addon below the input.

1<script lang="ts">
2  import { FieldGroup, Field, FieldLabel, FieldDescription } from "@/components/ui/field";
3  import {
4    InputGroup,

Block Start

Use align="block-start" to position the addon above the input.

1<script lang="ts">
2  import { FieldGroup, Field, FieldLabel, FieldDescription } from "@/components/ui/field";
3  import {
4    InputGroup,

Dropdown

1<script lang="ts">
2  import {
3    InputGroup,
4    InputGroupAddon,

Icon

1<script lang="ts">
2  import {
3    InputGroup,
4    InputGroupAddon,

Inline End

Use align="inline-end" to position the addon at the end of the input.

1<script lang="ts">
2  import { Field, FieldLabel, FieldDescription } from "@/components/ui/field";
3  import {
4    InputGroup,

Inline Start

Use align="inline-start" to position the addon at the start of the input. This is the default.

1<script lang="ts">
2  import { Field, FieldLabel, FieldDescription } from "@/components/ui/field";
3  import {
4    InputGroup,

Kbd

1<script lang="ts">
2import {
3  InputGroup,
4  InputGroupAddon,

Text

1<script lang="ts">
2  import {
3    InputGroup,
4    InputGroupAddon,

Textarea

1<script lang="ts">
2  import {
3    InputGroup,
4    InputGroupAddon,

On This Page

InstallationUsageExamplesBlock EndBlock StartDropdownIconInline EndInline StartKbdTextTextarea

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.