Morphin
Introduction
Button
Chip
Input
Searchbar
Sidebar

Searchbar

Simple input box where users can type search queries, made on top of MnInput

Code

import { YStack } from 'tamagui'
import { Searchbar } from 'yourpath/ui'
import { useState } from 'react'

const DemoSearchbar = () => {
  const [query, setQuery] = useState('')

  return (
    <>
      <YStack minHeight={250} overflow="hidden" gap="$4" margin="$3" padding="$2">
        <Searchbar
          value={query}
          onChangeText={(text) => {
            setQuery(text)
          }}
        />
      </YStack>
    </>
  )
}

export default DemoSearchbar

Props

MnSearchbar
Prop NameTypeDescription
valuestring (required)Show value in search bar
onChangeText(text: string) => voidFunction to update value in search bar
extendsMnInputIt extends all the props the MnInput

MnSearchbar Code

import { MnInput, MnInputProps } from '../mn-input'
import { Search, X } from '@tamagui/lucide-icons'
import React, { useRef } from 'react'
import { isWeb, useComposedRefs } from 'tamagui'

type ISearchbar = Omit<MnInputProps, 'onChange'> & {
  value: string // Value must be a string for the input field
  onChangeText: (text: string) => void // Callback for text change
}

// Comment generated by ChatGPT

/**
 * Searchbar component that extends MnInput, designed for a seamless search experience.
 * Includes a left-aligned search icon and a clear button (X) on the right to reset the search text.
 *
 * - If running in a web environment, clicking the "X" icon will clear the input and refocus.
 * - In non-web environments, the "X" icon's onPress event will trigger the same behavior.
 *
 * Props:
 * - Inherits MnInputProps except for `onChange`, with required `value` and `onChangeText` props.
 *
 * @param {ISearchbar} props - The properties passed to the Searchbar, including value and optional icons.
 *
 * @returns {JSX.Element} A search input field with customizable icons and text clearing functionality.
 *
 * Note: If you provide your own iconRight for clearing search text, you must handle clearing the text like this:
 *
 * ```tsx
 * const handleClearText = () => {
 *    onChangeText(''); // Clear the input value
 *     if (isWeb) {
 *         ref.current?.focus(); // Focus input after clearing on web
 *     }
 * }
 * ```
 *
 * Usage:
 * ```tsx
 * <Searchbar value={searchText} onChangeText={setSearchText} placeholder="Search here..."/>
 * ```
 */

export const Searchbar = React.forwardRef<HTMLInputElement, ISearchbar>((props, forwardedRef) => {
  const { iconLeft = Search, iconRight, value, onChangeText, ...rest } = props
  const ref = useRef<HTMLInputElement>(null)
  const composedRef = useComposedRefs(forwardedRef, ref)

  const handleClearText = () => {
    onChangeText('') // Clear the input value
    if (isWeb) {
      ref.current?.focus() // Focus input after clearing on web
    }
  }

  const renderCancelIcon = () => {
    return (
      <X
        {...(isWeb ? { onClick: handleClearText } : { onPress: handleClearText })}
        style={{ cursor: 'pointer' }}
        aria-label="Clear search"
      />
    )
  }

  return (
    <MnInput
      roundedBorder
      iconLeft={iconLeft}
      iconRight={iconRight || renderCancelIcon()}
      value={value}
      onChangeText={onChangeText} // Ensure the value changes propagate correctly
      {...rest}
      ref={composedRef}
    />
  )
})

// Optional: Define default props
Searchbar.defaultProps = {
  iconLeft: Search,
  iconRight: null,
}