# Button (React Native)

> Variants, sizes, icons and a loading state. An async onPress shows progress by itself.

GramproKit for React Native · Actions · Beta · Source: https://kit.gramproindia.com/native/docs/button

> **Beta:** React Native support is in beta. APIs may change or break between prereleases (npm tag `native`).

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/button). The example's source:

```tsx
import { useState } from "react";
import { Text } from "react-native";
import { Button } from "@/component-lib/button";
import { useKitTheme } from "@/component-lib/shared/native";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

function Glyph({ children }: { children: string }) {
  const { tokens } = useKitTheme();
  return <Text style={{ fontSize: 16, color: tokens.accentFg, fontWeight: "700" }}>{children}</Text>;
}

export function ButtonDemo() {
  const [saved, setSaved] = useState(0);
  return (
    <>
      <Section title="Button · variants">
        <Row>
          <Button>Primary</Button>
          <Button variant="secondary">Secondary</Button>
          <Button variant="outline">Outline</Button>
        </Row>
        <Row>
          <Button variant="ghost">Ghost</Button>
          <Button variant="danger">Delete</Button>
          <Button variant="link">Link</Button>
        </Row>
      </Section>

      <Section title="Button · sizes and icons">
        <Row>
          <Button size="sm">Small</Button>
          <Button size="md">Medium</Button>
          <Button size="lg">Large</Button>
        </Row>
        <Row>
          <Button leading={<Glyph>+</Glyph>}>New invoice</Button>
          <Button icon={<Glyph>✓</Glyph>} aria-label="Confirm" />
          <Button disabled>Disabled</Button>
        </Row>
      </Section>

      <Section title="Button · loading">
        <Row>
          <Button loading>Saving</Button>
          <Button variant="secondary" loading loadingText="Uploading…">
            Upload
          </Button>
        </Row>
        <Button fullWidth onPress={() => wait(1500).then(() => setSaved((n) => n + 1))}>
          {`Async press · saved ${saved}×`}
        </Button>
      </Section>
    </>
  );
}
```

## Install

```bash
npx @grampro/kit@native add Button
```

## Usage

```tsx
import { Button } from "@/component-lib/button";

<Button onPress={() => save()}>Save</Button>
<Button variant="outline" leading={<PlusIcon />}>New invoice</Button>
<Button variant="danger" loading>Deleting</Button>
```

## Props

### ButtonProps

| Prop | Type | Description |
|---|---|---|
| `variant` | `ButtonVariant` | Default `primary`. |
| `size` | `ButtonSize` | Default `md`. Every size keeps a 44dp touch target. |
| `loading` | `boolean` | Show a spinner and ignore presses, keeping the button's width. |
| `loadingText` | `ReactNode` | Text shown next to the spinner while busy, instead of keeping the label. |
| `leading` | `ReactNode` | Icon before the label. |
| `trailing` | `ReactNode` | Icon after the label. |
| `icon` | `ReactNode` | An icon-only button. Give it an `aria-label`. |
| `fullWidth` | `boolean` | Fill the width of the container. |
| `disabled` | `boolean` |   |
| `onPress` | `(event: GestureResponderEvent) => unknown` | Return a promise to show the loading state until it settles. |
| `children` | `ReactNode` |   |
| `style` | `Styleable<ViewStyle>` | Root style, or a function of the button's state. |
| `styles` | `Partial<{ root: Styleable<ViewStyle>; content: Styleable<ViewStyle>; label: Styleable<T…` |   |
| `localeText` | `Partial<ButtonLocaleText>` |   |

Also accepts the props of `Omit<PressableProps, "children" | "style" | "onPress" | "disabled">`.

## Native and web

- `onPress` instead of `onClick`. Return a promise and the button shows its spinner until it settles.
- Every size keeps a 44dp touch target (small buttons get `hitSlop`).
- No `type="submit"` or form status: React Native has no forms.
- Web version: [Button on the web](https://kit.gramproindia.com/button).
