AniUI

Input Group

Add addons, buttons, and helper content to inputs.

$
Web preview — components render natively on iOS & Android
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group";

export function MyScreen() {
  return (
    <InputGroup>
      <InputGroupAddon>
        <InputGroupText>$</InputGroupText>
      </InputGroupAddon>
      <InputGroupInput placeholder="0.00" keyboardType="numeric" />
    </InputGroup>
  );
}

Installation#

npx @aniui/cli add input-group

Usage#

app/index.tsx
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group";

export function MyScreen() {
  return (
    <InputGroup>
      <InputGroupAddon>
        <InputGroupText>$</InputGroupText>
      </InputGroupAddon>
      <InputGroupInput placeholder="0.00" keyboardType="numeric" />
    </InputGroup>
  );
}

Suffix Addon#

.com
Web preview — components render natively on iOS & Android
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group";

export function MyScreen() {
  return (
    <InputGroup>
      <InputGroupInput placeholder="you@example.com" keyboardType="email-address" />
      <InputGroupAddon align="end">
        <InputGroupText>@gmail.com</InputGroupText>
      </InputGroupAddon>
    </InputGroup>
  );
}

Button Addon#

Web preview — components render natively on iOS & Android
import {
  InputGroup,
  InputGroupButton,
  InputGroupInput,
} from "@/components/ui/input-group";
import { Text } from "react-native";

export function MyScreen() {
  return (
    <InputGroup>
      <InputGroupInput placeholder="Search..." />
      <InputGroupButton onPress={() => console.log("search")}>
        <Text className="text-sm font-medium text-primary">Go</Text>
      </InputGroupButton>
    </InputGroup>
  );
}

Components#

InputGroup is a compound component made up of several parts:

ComponentDescription
InputGroup

Root container that provides the bordered row layout.

InputGroupAddon

Non-interactive addon area. Supports start and end alignment.

InputGroupInput

The text input element. Expands to fill available space.

InputGroupButton

Pressable button placed inside the input group.

InputGroupText

Styled text for use inside addons.

Props#

InputGroup#

PropTypeDefault
className
string
-
children
React.ReactNode
-

Also accepts all View props from React Native.

InputGroupAddon#

PropTypeDefault
align
"start" | "end"
"start"
className
string
-
children
React.ReactNode
-

Also accepts all View props from React Native.

InputGroupInput#

PropTypeDefault
className
string
-

Also accepts all TextInput props from React Native.

InputGroupButton#

PropTypeDefault
className
string
-
children
React.ReactNode
-

Also accepts all Pressable props from React Native.

InputGroupText#

PropTypeDefault
className
string
-

Also accepts all Text props from React Native.

Accessibility#

  • InputGroupButton uses accessibilityRole="button" and accessible={true}.
  • Minimum touch target of 48dp on interactive elements.
  • Use accessibilityLabel on addons that contain icons instead of text.

Source#

components/ui/input-group.tsx
import React from "react";
import { View, Text, TextInput, Pressable } from "react-native";
import { cn } from "@/lib/utils";

export interface InputGroupProps extends React.ComponentPropsWithoutRef<typeof View> {
  className?: string;
  children?: React.ReactNode;
}

export function InputGroup({ className, children, ...props }: InputGroupProps) {
  return (
    <View
      className={cn("flex-row items-center rounded-md border border-input bg-background", className)}
      {...props}
    >
      {children}
    </View>
  );
}

export interface InputGroupAddonProps extends React.ComponentPropsWithoutRef<typeof View> {
  className?: string;
  align?: "start" | "end";
  children?: React.ReactNode;
}

export function InputGroupAddon({ className, align = "start", children, ...props }: InputGroupAddonProps) {
  return (
    <View
      className={cn(
        "items-center justify-center px-3 self-stretch",
        align === "start" ? "border-e border-input" : "border-s border-input",
        className
      )}
      {...props}
    >
      {children}
    </View>
  );
}

export interface InputGroupInputProps extends React.ComponentPropsWithoutRef<typeof TextInput> {
  className?: string;
}

export function InputGroupInput({ className, ...props }: InputGroupInputProps) {
  return (
    <TextInput
      className={cn("flex-1 min-h-12 px-3 text-base text-foreground", className)}
      placeholderTextColor="#71717a"
      {...props}
    />
  );
}

export interface InputGroupButtonProps extends React.ComponentPropsWithoutRef<typeof Pressable> {
  className?: string;
  children?: React.ReactNode;
}

export function InputGroupButton({ className, children, ...props }: InputGroupButtonProps) {
  return (
    <Pressable
      className={cn(
        "items-center justify-center px-3 min-h-12 active:opacity-70",
        className
      )}
      accessible={true}
      accessibilityRole="button"
      {...props}
    >
      {children}
    </Pressable>
  );
}

export interface InputGroupTextProps extends React.ComponentPropsWithoutRef<typeof Text> {
  className?: string;
}

export function InputGroupText({ className, ...props }: InputGroupTextProps) {
  return (
    <Text className={cn("text-sm text-muted-foreground", className)} {...props} />
  );
}