Alok Srivastava

Astryx Base Typeahead

Forms 1

About

A composable Astryx combobox engine with search, keyboard navigation, custom results, and anchored dropdown positioning.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Astryx Base Typeahead to your project and fits it to your theme.

Code

How Astryx Base Typeahead is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client"

import { useRef, useState } from "react"
import BaseTypeahead, {
  createStaticSource,
  type SearchableItem,
} from "@/components/ui/astryx-base-typeahead"
import { Icon } from "@astryxdesign/core/Icon"
import { HStack, VStack } from "@astryxdesign/core/Layout"
import { Text } from "@astryxdesign/core/Text"
import {
  borderVars,
  colorVars,
  focusVars,
  radiusVars,
  spacingVars,
} from "@astryxdesign/core/theme/tokens.stylex"
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"

const frameworks: SearchableItem[] = [
  { id: "react", label: "React" },
  { id: "vue", label: "Vue" },
  { id: "angular", label: "Angular" },
  { id: "svelte", label: "Svelte" },
  { id: "solid", label: "SolidJS" },
  { id: "remix", label: "Remix" },
  { id: "next", label: "Next.js" },
  { id: "nuxt", label: "Nuxt" },
]

const source = createStaticSource(frameworks)

export default function BaseTypeaheadDemo() {
  const [value, setValue] = useState<SearchableItem | null>(null)
  const [isFocusVisible, setIsFocusVisible] = useState(false)
  const wrapperRef = useRef<HTMLDivElement>(null)

  return (
    <VStack
      data-astryx-theme="neutral"
      data-theme="light"
      gap={3}
      style={{ colorScheme: "light", width: "100%", maxWidth: 360 }}
    >
      <HStack
        ref={wrapperRef}
        gap={2}
        vAlign="center"
        onFocusCapture={(event) => setIsFocusVisible(event.target.matches(":focus-visible"))}
        onBlurCapture={() => setIsFocusVisible(false)}
        style={{
          backgroundColor: colorVars["--color-background-surface"],
          borderColor: colorVars["--color-border"],
          borderRadius: radiusVars["--radius-element"],
          borderStyle: "solid",
          borderWidth: borderVars["--border-width"],
          paddingBlock: spacingVars["--spacing-1-5"],
          paddingInline: spacingVars["--spacing-2"],
          outlineColor: isFocusVisible ? focusVars["--focus-outline-color"] : "transparent",
          outlineOffset: focusVars["--focus-outline-offset"],
          outlineStyle: "solid",
          outlineWidth: isFocusVisible ? focusVars["--focus-outline-width"] : 0,
        }}
      >
        <Icon icon={MagnifyingGlassIcon} size="sm" color="secondary" />
        <BaseTypeahead
          aria-label="Search frameworks"
          searchSource={source}
          value={value}
          onChange={setValue}
          anchorRef={wrapperRef}
          placeholder="Search frameworks…"
          hasEntriesOnFocus
          debounceMs={0}
        />
      </HStack>
      <Text type="supporting" color="secondary">
        {value != null ? `Selected: ${value.label}` : "No selection"}
      </Text>
    </VStack>
  )
}

Dependencies

More by Alok Srivastava

View all
  • Glossy Slider Call Button

    Glossy Slider Call Button

    21
  • Dot Graph Card

    Dot Graph Card

    19
  • Profile Menu Expander

    Profile Menu Expander

    2
  • Pixel Perfect Command Palette

    Pixel Perfect Command Palette

    1
  • Astryx Center

    Astryx Center

  • Astryx Alert Dialog

    Astryx Alert Dialog

  • Expandable Book Search Palette

    Expandable Book Search Palette

More in Forms

View all
  • Contact Card

    Contact Card

    1.1K
  • Premium Auth

    Premium Auth

    551
  • Login 1

    Login 1

    60
  • Form

    Form

    17
  • Form

    Form

    16
  • Book A Demo 1

    Book A Demo 1

    84
  • Card Studio

    Card Studio

    46
  • Login 2

    Login 2

    10