Primitives

View on GitHub

React wrappers for Shopify Polaris Web Components.

These are thin React adapters around Polaris Web Components. They normalize boolean props, handle custom events, and provide typed slots — making Polaris ergonomic in React without replacing the underlying components.

Primitives are open source and available on GitHub.

What you get

Component files

TypeScript source you own and can modify

Storybook stories

Interactive examples for every component and variant

Type definitions

Full TypeScript types for props and events

Enhanced10

Add event handlers, slots, or sub-components beyond the base web component.

Adapted4

Normalizes boolean props and typed slots for React. No new API surface.

1:135

TypeScript types, clean imports, and ref forwarding. React-ready with zero overhead.

Live Examples

ButtonAdapted

Live Preview

PrimarySecondaryTertiaryCriticalDisabled

Component Source Code

import { forwardRef, createElement, type ReactNode } from 'react';

type SButtonProps = JSX.IntrinsicElements['s-button'];

export type ButtonProps = Omit<SButtonProps, 'disabled' | 'loading'> & {
    /** Prevents clicking or receiving focus */
    disabled?: boolean;
    /** Shows loading indicator and disables button */
    loading?: boolean;
    /** Content of the button */
    children?: ReactNode;
};

/**
 * Button component - triggers actions or events.
 *
 * @see https://shopify.dev/docs/api/app-home/polaris-web-components/actions/button
 *
 * @example
 * <Button variant="primary">Save</Button>
 * <Button variant="secondary" tone="critical">Delete</Button>
 */
export const Button = forwardRef<HTMLElement, ButtonProps>(
    ({ children, disabled, loading, ...props }, ref) => {
        return createElement(
            's-button',
            {
                ref,
                ...props,
                disabled: disabled || undefined,
                loading: loading || undefined,
            },
            children
        );
    }
);

Button.displayName = 'Button';

What we add: Boolean prop normalization (disabled, loading) — converts React booleans to proper HTML attributes for the underlying s-button web component.

Chip1:1

Live Preview

DefaultTagLabelCategory

Component Source Code

import { forwardRef, createElement } from 'react';

type Props = JSX.IntrinsicElements['s-chip'];

export const Chip = forwardRef<HTMLElement, Props>((props, ref) => createElement('s-chip', { ref, ...props }));

Chip.displayName = 'Chip';

What we add: React wrapper with full TypeScript support. Provides type-safe props, ref forwarding, and clean imports — just import and use like any React component.

BannerEnhanced
This is an informational message.Please review before continuing.

Event handlers, secondaryActions slot

TextFieldAdapted

Boolean props, accessory slot

Badge1:1
DefaultInfoSuccessWarningCritical

Typed props, clean imports, ref forwarding

CheckboxAdapted

Boolean props, details slot

All Primitives

Actions

ComponentTypeWhat we add
ButtonAdaptedBoolean prop normalization (disabled, loading)
ButtonGroupEnhancedAuto-slotting (last → primary, others → secondary)
Clickable1:1Typed props, clean imports, ref forwarding
ClickableChipEnhancedBoolean props, onRemove event, graphic slot
Link1:1Typed props, clean imports, ref forwarding
MenuEnhancedAuto-wired trigger prop, useId integration

Forms

ComponentTypeWhat we add
TextFieldAdaptedBoolean props, accessory slot
EmailField1:1Use PolarisField for form library integration
PasswordField1:1Use PolarisField for form library integration
UrlField1:1Use PolarisField for form library integration
NumberField1:1Use PolarisField for form library integration
MoneyField1:1Use PolarisField for form library integration
SearchField1:1Use PolarisField for form library integration
TextArea1:1Typed props, clean imports, ref forwarding
DateFieldEnhancedDate object API, min/max, react-hook-form compatible
DatePickerEnhancedDate object API, min/max, single + range modes
ColorField1:1Typed props, clean imports, ref forwarding
ColorPicker1:1Typed props, clean imports, ref forwarding
SelectEnhancedValue-first onChange(string), onBlur for form libs
CheckboxAdaptedBoolean props, details slot
ChoiceListEnhancedValue-first onChange(string[]), JSON serialize values[], Choice sub-component
Switch1:1Typed props, clean imports, ref forwarding
DropZone1:1Typed props, clean imports, ref forwarding

Feedback

ComponentTypeWhat we add
Badge1:1Typed props, clean imports, ref forwarding
BannerEnhancedEvent handlers (onDismiss, onAfterHide), secondaryActions slot
Spinner1:1Typed props, clean imports, ref forwarding
Chip1:1Typed props, clean imports, ref forwarding

Overlays

ComponentTypeWhat we add
ModalEnhancedEvent handlers, primaryAction/secondaryActions slots
PopoverEnhancedAuto-wired trigger prop, 6 lifecycle event handlers
TooltipAdaptedSimplified props interface

Layout

ComponentTypeWhat we add
Box1:1Typed props, clean imports, ref forwarding
Stack1:1Typed props, clean imports, ref forwarding
Grid1:1Typed props, clean imports, ref forwarding
GridItem1:1Typed props, clean imports, ref forwarding
Page1:1Typed props, clean imports, ref forwarding
Section1:1Typed props, clean imports, ref forwarding
Divider1:1Typed props, clean imports, ref forwarding
QueryContainer1:1Typed props, clean imports, ref forwarding

Typography

ComponentTypeWhat we add
Text1:1Typed props, clean imports, ref forwarding
Heading1:1Typed props, clean imports, ref forwarding
Paragraph1:1Typed props, clean imports, ref forwarding
OrderedList1:1Typed props, clean imports, ref forwarding
UnorderedList1:1Typed props, clean imports, ref forwarding
ListItem1:1Typed props, clean imports, ref forwarding

Media

ComponentTypeWhat we add
Icon1:1Typed props, clean imports, ref forwarding
Thumbnail1:1Typed props, clean imports, ref forwarding
Avatar1:1Typed props, clean imports, ref forwarding
Image1:1Typed props, clean imports, ref forwarding

Table

ComponentTypeWhat we add
Table1:1Thin wrappers for s-table-* elements
What this is not
  • Not a full component library
  • Not a Polaris Web Components replacement
  • Not meant to be used standalone

Primitives exist to support compositions and recipes. The real value is in the composed patterns.