Active Foundation · Example
Icons, prefix and suffix, a button and a footer
Icons, prefix and suffix, a button and a footerClient
0 characters
Full source examples/ui/input-group.tsx
// apps/docs/examples/ui/input-group.tsx'use client';
import {useEffect, useRef, useState} from 'react';import {CheckIcon, CopyIcon, SearchIcon} from 'lucide-react';
import { Field, FieldLabel,} from '@workspace/active-ui/components/primitives/field';import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea,} from '@workspace/active-ui/components/primitives/input-group';import {Kbd} from '@workspace/active-ui/components/primitives/kbd';
const LINK = 'https://example.com/schemes/ps-2026';
/** * An input with something attached: an icon and a shortcut, a fixed prefix * and suffix, a button that acts on the value, and a textarea with a footer. * Clicking an addon that is not a button focuses the input. The shortcut * shown in the search field works: `/` focuses it, unless you are typing * in another field. */export default function InputGroupExample() { const [copied, setCopied] = useState(false); const [message, setMessage] = useState(''); const search = useRef<HTMLInputElement>(null); useEffect(() => { const onKey = (event: KeyboardEvent) => { const target = event.target as HTMLElement; if (event.key !== '/' || target.closest('input, textarea, select')) { return; } event.preventDefault(); search.current?.focus(); }; document.addEventListener('keydown', onKey); return () => document.removeEventListener('keydown', onKey); }, []); const copy = async () => { await navigator.clipboard?.writeText(LINK).catch(() => undefined); setCopied(true); window.setTimeout(() => setCopied(false), 1500); }; return ( <div className="grid w-full max-w-md gap-6"> <InputGroup> <InputGroupInput ref={search} placeholder="Search schemes" aria-label="Search schemes" aria-keyshortcuts="/" /> <InputGroupAddon> <SearchIcon aria-hidden /> </InputGroupAddon> <InputGroupAddon align="inline-end"> <Kbd>/</Kbd> </InputGroupAddon> </InputGroup>
<Field> <FieldLabel htmlFor="group-site">Website</FieldLabel> <InputGroup> <InputGroupAddon> <InputGroupText>https://</InputGroupText> </InputGroupAddon> <InputGroupInput id="group-site" placeholder="example.com" /> <InputGroupAddon align="inline-end"> <InputGroupText>/schemes</InputGroupText> </InputGroupAddon> </InputGroup> </Field>
<Field> <FieldLabel htmlFor="group-link">Share link</FieldLabel> <InputGroup> <InputGroupInput id="group-link" value={LINK} readOnly /> <InputGroupAddon align="inline-end"> <InputGroupButton size="icon-xs" aria-label={copied ? 'Copied' : 'Copy link'} onClick={copy} > {copied ? <CheckIcon aria-hidden /> : <CopyIcon aria-hidden />} </InputGroupButton> </InputGroupAddon> </InputGroup> </Field>
<Field> <FieldLabel htmlFor="group-message">Message</FieldLabel> <InputGroup> <InputGroupTextarea id="group-message" value={message} onChange={(event) => setMessage(event.target.value)} placeholder="Write a message" /> <InputGroupAddon align="block-end" className="border-t"> <InputGroupText>{message.length} characters</InputGroupText> <InputGroupButton variant="default" size="sm" className="ml-auto" disabled={message.trim() === ''} onClick={() => setMessage('')} > Send </InputGroupButton> </InputGroupAddon> </InputGroup> </Field> </div> );}