# Success check

> A success or error moment: the circle springs in, the check draws itself while a ring pulses out and the title rises in; the error variant draws a cross and shakes once. Inline or fullscreen, optionally with confetti.

- Type: Component (feedback)
- Access: Free, open source (MIT)
- Page: https://goodui.dev/native/components/success-check
- Markdown: https://goodui.dev/native/components/success-check.md
- Registry item: https://goodui.dev/native/r/success-check.json
- Dependencies: react-native-reanimated, react-native-svg
- Keywords: react native success animation, animated checkmark, payment success screen, order confirmed, done screen, error cross animation, expo success check

## When to use

- The end of a flow: payment sent, booking confirmed, account created, workout saved.
- A result that replaces a form or a sheet's content once it is submitted.
- A failed final step that needs a clear, calm error moment before offering a retry.

## When not to use

- A single button's result: Button and IconButton already show success and error themselves.
- Background events: use toast.
- A problem that leaves the screen usable: use banner.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add https://goodui.dev/native/r/success-check.json
npx expo install --fix
```

The component lands in `components/goodui-native/success-check/` and imports the foundation from `components/goodui-native/foundation/` with relative paths; it also installs confetti, locale.

Built-in strings follow `<GooduiLocaleProvider>` (one [language pack](https://goodui.dev/native/r/locale-tr.json) translates the whole kit); the `labels` prop overrides them for one instance.

## Usage

```tsx
import { useState } from "react";
import { Button } from "@/components/goodui-native/button/button";
import { SuccessCheck } from "@/components/goodui-native/success-check/success-check";

export function SendMoney({ send }: { send: () => Promise<void> }) {
  const [done, setDone] = useState(false);
  return (
    <>
      <Button onPress={async () => { await send(); setDone(true); }}>Send $1,250.00</Button>
      <SuccessCheck
        variant="fullscreen"
        visible={done}
        onDismiss={() => setDone(false)}
        title="Money sent"
        subtitle="$1,250.00 to Maya Chen"
        confetti
      />
    </>
  );
}
```

## Examples

### Inline, replacing a sheet's form

```tsx
{submitted ? (
  <SuccessCheck title="Booked" subtitle="Thu 14 Nov, 10:30 with Dr. Patel">
    <Button variant="secondary" onPress={close}>Done</Button>
  </SuccessCheck>
) : form}
```

### Error, then retry

```tsx
<SuccessCheck status="error" size="sm" title="Card declined" subtitle="Try another card" playKey={attempt} />
```

## API reference

### SuccessCheck

`import { SuccessCheck } from "@/components/goodui-native/success-check/success-check";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `status` | `"success" \| "error"` | `"success"` | `success` draws a check and pulses a ring; `error` draws a cross and shakes. |
| `variant` | `"inline" \| "fullscreen"` | `"inline"` | `inline` sits in your layout; `fullscreen` covers the screen through the portal and closes itself. |
| `visible` | `boolean` | `true` | Plays the moment each time it turns `true`. Fullscreen closes with a fade when it turns `false`. Default `true`. |
| `title` | `string` | – | One short line: "Payment sent", "Booked". Rises in under the mark. |
| `subtitle` | `string` | – | Detail under the title: an amount, a time, a reference. |
| `size` | `"sm" \| "md" \| "lg"` | – | Circle of 48, 72 or 96 pt. Default `md` inline, `lg` fullscreen. |
| `playKey` | `string \| number` | – | Change it to play the moment again without hiding it. |
| `duration` | `number` | `2200` | Fullscreen: milliseconds before `onDismiss` runs on its own. `Infinity` waits for a tap. Default 2200. |
| `onDismiss` | `() => void` | – | Fullscreen: called after `duration`, on a tap, on Escape or the Android back button. Set `visible` to false here. |
| `confetti` | `boolean` | `false` | Burst confetti out of the circle on success. Default `false`. |
| `haptic` | `boolean` | `true` | Success or error haptic as the mark lands. Default `true`. |
| `children` | `ReactNode` | – | Extra content that rises in last, for example a Done button (inline) or a receipt line. |
| `labels` | `Partial<SuccessCheckLabels>` | – | Overrides for the built-in strings; a GooduiLocaleProvider pack sets them app-wide. |
| `style` | `StyleProp<ViewStyle>` | – | Style for the outer container. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

## Accessibility

- Each time it plays it announces the title and subtitle (or 'Done' / 'Something went wrong').
- Fullscreen is modal (accessibilityViewIsModal): a single button that closes it on tap, with the hint 'Closes this message'; Escape on the web and the Android back button close it too.
- Colors come from success and danger with their on-colors; the mark is never the only signal when a title is set.

## Motion

- Success: the circle scales in on the bouncy spring, the check draws itself in (260 ms, from 170 ms), a ring pulses out to 1.75× and fades over 700 ms, then title, subtitle and children rise 12 pt on the smooth spring, staggered.
- Error: the circle scales in on the snappy spring, the two strokes of the cross draw one after another, then the mark shakes once.
- It plays again each time visible turns true, the status changes or playKey changes.
- Fullscreen fades its background in and out over the app.
- Reduced motion: circle and text fade in, the check appears complete, no ring, no shake, no confetti physics (Confetti shows its static sparkle).

## Haptics

- success (celebrate with confetti) or error when the mark lands (about 400 ms in), once per play. haptic={false} turns it off.

## Performance

- A handful of Reanimated values on the UI thread. Confetti mounts only when the burst fires and unmounts when it ends.

## Notes for AI

- Inline: render it where the result belongs; visible={false} removes it. Fullscreen: control visible and set it false in onDismiss.
- Fullscreen closes after duration ms (default 2200); pass duration={Infinity} to wait for a tap.
- Use playKey to replay without hiding, for example the attempt number for repeated errors.
- children rise in last; inline that is the place for a Done button. In fullscreen the whole screen is already the close button, so pass text, not buttons.

## Related

- [Confetti](https://goodui.dev/native/components/confetti.md): A celebration burst: paper pieces launch from a point or rain from the top on closed-form physics (air drag, gravity, sway), spinning and turning over as they fall; one burst per trigger, a static sparkle under reduced motion.
- [Button](https://goodui.dev/native/components/button.md): A press-responsive button with haptics that runs async actions on its own: it gathers into a spinner, then opens into a success or error state.
- [Toast](https://goodui.dev/native/components/toast.md): Background confirmations that stack at the top, fan out on tap, swipe away up or sideways, and pause their timers while touched.
- [Banner](https://goodui.dev/native/components/banner.md): An inline status banner that slides down from under the edge above and pushes the content down, flings away sideways with the finger, and can collapse on its own behind a draining hairline; includes an offline preset.

## Guidance for AI tools

Success check: A success or error moment: the circle springs in, the check draws itself while a ring pulses out and the title rises in; the error variant draws a cross and shakes once. Inline or fullscreen, optionally with confetti. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
