NovaUI
Components

Button

A versatile button component built for React Native with web support, featuring multiple variants, sizes, and states.

The Button component is a flexible and accessible button built with React Native's Pressable component. It supports multiple visual variants, sizes, border radius options, loading states, and is fully compatible with both React Native and web platforms.

Preview

Installation

The Button component is part of the novaui-components package. Make sure you have the required peer dependencies installed:

npx novaui-cli add button

Import

import { Button } from 'novaui-components'

Basic Usage

The Button component accepts label prop or children for the button text:

import { Button } from 'novaui-components'

export function MyComponent() {
  return (
    <>
      <Button label="Click me" />
      <Button>Or use children</Button>
    </>
  )
}

Variants

The Button component supports six visual variants, each designed for different use cases:

Default

The primary button variant, perfect for main actions:

<Button variant="default" label="Default Button" />

Destructive

Use for dangerous or destructive actions like delete or remove:

<Button variant="destructive" label="Delete" />

Outline

A button with an outlined border, great for secondary actions:

<Button variant="outline" label="Outline Button" />

Secondary

A secondary button variant with a subtle background:

<Button variant="secondary" label="Secondary Button" />

Ghost

A minimal button with no background, ideal for subtle actions:

<Button variant="ghost" label="Ghost Button" />

A text-only button styled like a link:

<Button variant="link" label="Link Button" />

Sizes

Control the button size with the size prop:

Default

The standard button size:

<Button size="default" label="Default Size" />

Small

Compact size for tight spaces:

<Button size="sm" label="Small Button" />

Large

Larger size for prominent actions:

<Button size="lg" label="Large Button" />

Icon

Square button perfect for icon-only buttons:

<Button size="icon" label="🚀" />

Border Radius

Customize the button's border radius with the radius prop:

<Button radius="none" label="No Radius" />
<Button radius="sm" label="Small Radius" />
<Button radius="md" label="Medium Radius" />
<Button radius="lg" label="Large Radius" />
<Button radius="xl" label="Extra Large Radius" />
<Button radius="2xl" label="2XL Radius" />
<Button radius="full" label="Full Radius" />

Loading State

Display a loading indicator while an action is in progress:

import { useState } from 'react'
import { Button } from 'novaui-components'

export function LoadingButton() {
  const [isLoading, setIsLoading] = useState(false)

  const handlePress = async () => {
    setIsLoading(true)
    // Simulate async operation
    await new Promise(resolve => setTimeout(resolve, 2000))
    setIsLoading(false)
  }

  return (
    <Button
      label="Submit"
      isLoading={isLoading}
      onPress={handlePress}
    />
  )
}

When isLoading is true, the button automatically:

  • Shows an ActivityIndicator spinner
  • Disables interaction
  • Adjusts the spinner color based on the variant

Disabled State

Disable the button to prevent user interaction:

<Button label="Disabled Button" disabled />

The button will be visually dimmed and non-interactive when disabled.

Custom Styling

Custom Class Names

Apply custom styles using the className prop:

<Button
  label="Custom Button"
  className="bg-purple-500 active:bg-purple-600"
/>

Custom Label Styling

Style the button label separately using labelClasses:

<Button
  label="Styled Label"
  labelClasses="font-bold text-lg"
/>

Advanced Examples

Button with Icon

Combine the Button with icons or other components:

import { Button } from 'novaui-components'
import { Heart } from 'lucide-react-native'

export function IconButton() {
  return (
    <Button size="icon" className="bg-red-500">
      <Heart size={20} color="white" />
    </Button>
  )
}

Full Width Button

Make a button span the full width:

<Button
  label="Full Width Button"
  className="w-full"
/>

Button Group

Create a group of buttons:

<View className="flex-row gap-2">
  <Button variant="outline" label="Cancel" />
  <Button variant="default" label="Confirm" />
</View>

Props API

ButtonProps

Extends React.ComponentPropsWithoutRef<typeof Pressable> and includes:

PropTypeDefaultDescription
variant'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link''default'The visual style variant of the button
size'default' | 'sm' | 'lg' | 'icon''default'The size of the button
radius'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full''md'The border radius of the button
labelstring-The text content of the button (alternative to children)
labelClassesstring-Additional CSS classes for the label text
isLoadingbooleanfalseShows a loading spinner and disables the button
disabledbooleanfalseDisables the button interaction
classNamestring-Additional CSS classes for the button container
childrenReact.ReactNode-Button content (alternative to label)

All standard Pressable props are also supported, including:

  • onPress - Callback when button is pressed
  • onPressIn - Callback when press starts
  • onPressOut - Callback when press ends
  • onLongPress - Callback for long press
  • accessibilityLabel - Accessibility label
  • And all other React Native Pressable props

Accessibility

The Button component includes built-in accessibility features:

  • Role: Automatically sets role="button" for screen readers
  • Hit Slop: Includes default hit slop (10px on all sides) for easier tapping on small devices
  • Disabled State: Properly handles disabled state for accessibility
  • Focus States: Web-specific focus-visible states for keyboard navigation

Platform Support

The Button component is designed to work seamlessly across platforms:

  • React Native: Full support with native touch interactions
  • Web: Enhanced with hover states, focus rings, and keyboard navigation
  • Responsive: Adapts sizing for different screen sizes (native vs web)

Best Practices

  1. Use appropriate variants: Choose variants that match the action's importance

    • default for primary actions
    • outline or secondary for secondary actions
    • destructive for dangerous actions
    • ghost or link for tertiary actions
  2. Loading states: Always use isLoading for async operations to provide user feedback

  3. Accessibility: Always provide meaningful labels and accessibility descriptions for icon-only buttons

  4. Touch targets: The component includes default hit slop, but ensure buttons are at least 44x44 points for optimal touch interaction

  5. Consistent sizing: Use consistent button sizes throughout your app for better UX

  • Consider using Button in combination with other form components
  • Use Button groups for related actions
  • Combine with icons from lucide-react-native for enhanced visual communication

On this page