Loading for Stripe Apps
Show loading indicators so people know your app is working and the interface stays responsive.
Loading states communicate that your app is retrieving data. A well-implemented loading pattern builds trust by keeping the interface responsive and preventing layout shifts when content appears.
Before you begin
Before you implement loading patterns, make sure your app meets these requirements:
- Create an app or use an existing one.
- Install @stripe/ui-extension-sdk version 9. x or later.
- Review the Spinner component reference.
Best practices
- Immediate feedback : Show a loading indicator as soon as a data fetch begins.
- Appropriate scope : Match the loading indicator to the scope of what’s loading. Use the full-page spinner for entire views, and inline spinners for sections.
- Prevent flash : Use the delay prop on the Spinner to avoid showing indicators for fast operations.
Note
Some components handle loading states internally through built-in props. For example, Button uses a pending prop instead of requiring a manual Spinner. Before you build a custom loading pattern, review the component reference to see if built-in loading behavior is available.
Show a full-page loading state
Show a centered Spinner with size="large" that fills the available space when your entire view depends on a single data fetch.
if (isLoading) {
return (
<Box css={{ stack: 'y', alignX: 'center', alignY: 'center', minHeight: 'fill', paddingTop: 'xxlarge' }}>
<Spinner size="large" />
</Box>
);
}
Show a section-level loading state
Use size="medium" when other parts of the page are already visible. If needed, load sections independently so available content appears immediately while other sections finish loading.
Use the delay prop to prevent flash
Use <Spinner size="large" delay={300} /> to prevent the spinner from appearing if data arrives within the delay window.
Recommended delay values:
- 200–300ms for most data fetches
- 0ms for known-slow operations
- 100ms for view transitions
Handle loading in tabbed layouts
Place the loading state inside each tab component, not around the Tabs container. Keep the tab bar visible and interactive.
Common mistake
Don’t wrap Tabs in a loading state. If you show a spinner instead of the tab bar, users lose their navigation context and might think the app is broken instead of loading.
Handle loading for actions
When a user triggers an action like saving or submitting, use the Button component’s built-in pending prop. This sets the button to a pending visual style and disables it, which helps prevent double submission without requiring you to manually compose a Spinner.
The pending prop handles the loading indicator and disabled state together—you don’t need to add a Spinner inside the button manually.
Choose the right spinner size
| Size | Use case |
|---|---|
large | Full-page or full-tab loading. Someone is waiting for primary content. |
medium | Section-level loading. Other parts visible. |
small | Inline indicators within table cells or compact UI elements. |
