Intentwise Primitives

Controls

Interactive filter, selector, and toggle components for dashboard toolbars and settings panels.

FilterSelect

Multi-Select Mode

Select multiple options from a dropdown list. Supports search, select all, and clear.

Selected: None

Show code
<FilterSelect
  data={{ label: 'Campaign Type', options: [...], value: [], mode: 'multi' }}
  onChange={(value) => setSelected(value)}
  searchable
/>

Single-Select Mode

Select a single option from a dropdown. Useful for status or category filters.

Selected: active

Show code
<FilterSelect
  data={{ label: 'Status', options: [...], value: 'active', mode: 'single' }}
  onChange={(value) => setStatus(value)}
/>

Staged Mode (Apply / Cancel) β€” search-scoped count

With confirm, a multi-select stages its edits behind Apply / Cancel and shows an 'N of M selected' footer. Both the count and Select all are scoped to the current search results: type 'sponsored' and the footer switches to the matching options only, so what it reports always matches what is on screen. The trigger label keeps showing the committed selection until Apply.

Applied: sp

Show code
<FilterSelect
  data={{ label: 'Campaign Type', options: [...], value: applied, mode: 'multi' }}
  onChange={setApplied}
  confirm
  searchable
/>

Loading & Disabled States

FilterSelect supports loading spinners and disabled state.

Show code
<FilterSelect data={...} onChange={...} loading />
<FilterSelect data={...} onChange={...} disabled />

FilterBar

FilterBar Layout

Responsive grid container that arranges filter controls in a consistent row. Adapts from 1 column on mobile to 4 on large screens.

Show code
<FilterBar>
  <FilterSelect data={campaignType} onChange={...} />
  <FilterSelect data={status} onChange={...} />
  <FilterSelect data={brand} onChange={...} />
</FilterBar>

SegmentedControl

Default Size

Radio-group style toggle for switching between options. Commonly used for time range, view mode, or metric selectors.

Time Range

View Mode

Show code
<SegmentedControl
  data={{ options: [{ value: '7d', label: '7D' }, ...], value: '30d' }}
  onChange={(value) => setTimeRange(value)}
/>

Size Variants

Available in sm and md (default) sizes.

sm

md

Show code
<SegmentedControl data={...} onChange={...} size="sm" />

OrgAccountSelector

Organization & Account Selector

Cascading dropdown pair for selecting organization and account. The account dropdown is disabled until an organization is selected. Changing org resets the account.

Org: org-1 | Account: acc-1

Show code
<OrgAccountSelector
  data={{ organizations: [...], accounts: [...], selectedOrgId, selectedAccountId }}
  onOrgChange={(id) => setOrgId(id)}
  onAccountChange={(id) => setAccountId(id)}
/>

Loading States

Loading spinners display while data is being fetched from the server.

Show code
<OrgAccountSelector data={...} orgsLoading accountsLoading />

Disabled State

Both dropdowns disabled when the component is in disabled state.

Show code
<OrgAccountSelector data={...} disabled />

FilterChipBar

FilterChipBar

Chips for applied filters with reset/save. Pass filters, onChange, and filterMenuItems. Returns null when filters.length === 0.

Filters :
CAMPAIGN: = Campaign AASIN: EQUAL B08X123
Show code
<FilterChipBar
  filters={filters}
  onChange={setFilters}
  filterMenuItems={[{ value: 'campaign', label: 'Campaign', filterType: 'name' }, ...]}
/>

NameFilterDialog

NameFilterDialog

Modal for name-type filters. Options support an optional secondaryLabel rendered inline as a small badge next to the name. Pass virtualizeList for large lists (500+ items) to keep only visible rows in the DOM.

Full / select-only / operator-only control which operators appear. Virtualized demo shows 500 options with inline type badges β€” only visible rows are in the DOM.

Show code
<NameFilterDialog
  open={open}
  onClose={() => setOpen(false)}
  onApply={(result) => { ...; setOpen(false); }}
  title="Campaign(s)"
  options={[{ id, label, secondaryLabel? }, ...]}
  showSelectOperator={true}
  showNonSelectOperators={true}
  virtualizeList   // opt-in for large lists
/>

StatusFilterDialog

StatusFilterDialog

Status selector dialog with configurable single-select (radio) and multi-select (checkbox) modes.

Show code
<StatusFilterDialog
  open={open}
  onClose={() => setOpen(false)}
  onApply={(result) => { ...; setOpen(false); }}
  selectionMode="single"
  options={[{ id: 'enabled', label: 'Enabled' }]}
/>

DateFilterDialog

DateFilterDialog

Date filter dialog β€” date-specific operators (is after / is on or before / is between …) with a calendar picker, and a second picker for BETWEEN. Use instead of MetricFilterDialog for date fields: its text mode drops the range operators and its number mode coerces values numerically.

Show code
<DateFilterDialog
  open={open}
  onClose={() => setOpen(false)}
  onApply={({ operator, value }) => { ...; setOpen(false); }}
  title="Campaign Start Date"
  defaultOperator="GREATER_THAN"
  defaultValue="2026-07-16"
/>

TableColumnSelector

TableColumnSelector

Panel to show/hide and reorder table columns. open, onOpenChange, onApply(state), columns.

Show code
<TableColumnSelector
  columns={[{ id, label, visible }, ...]}
  open={open}
  onOpenChange={setOpen}
  onApply={(state) => setState(state)}
/>

FullscreenToggle

FullscreenToggle

Button that fullscreens the element at targetRef. Add FULLSCREEN_TARGET_CLASS to the target for viewport styling.

This box can be expanded to full screen.
Show code
<div ref={targetRef} className={FULLSCREEN_TARGET_CLASS}>...</div>
<FullscreenToggle targetRef={targetRef} />

DarkModeToggle

DarkModeToggle

Button that toggles light/dark mode. Requires DarkModeProvider from @primitives/context. showLabel, size: sm | md.

Show code
<DarkModeProvider><DarkModeToggle showLabel size="md" /></DarkModeProvider>

DateRangePicker β€” Non-Compare Mode

DateRangePicker β€” Non-Compare Mode

Calendar popover for selecting a single date range (no comparison). value, onChange, label.

Show code
<DateRangePicker value={range} onChange={setRange} label="Date range" />

DateRangePicker β€” Compare Mode

DateRangePicker β€” Compare Mode

With comparison enabled, the popover adds a 'Compare to' toggle plus a second calendar for the previous period. comparison, comparisonValue, onComparisonChange.

Show code
<DateRangePicker
  value={range}
  onChange={setRange}
  label="Date range"
  comparison
  comparisonValue={compare}
  onComparisonChange={setCompare}
/>

DateRangePicker β€” Custom Presets

DateRangePicker β€” Custom Presets

Override the Quick Select sidebar by passing a presets array of { label, getRange }. Useful for limiting choices (e.g. 'Recent Week' / 'Recent Date') or domain-specific shortcuts. When omitted, the standard 5 presets are shown.

Show code
const customPresets: DateRangePresetItem[] = [
  { label: 'Recent Week',  getRange: () => ({ start: subDays(new Date(), 6),  end: new Date() }) },
  { label: 'Recent Month', getRange: () => ({ start: subDays(new Date(), 29), end: new Date() }) },
  { label: 'Year to Date', getRange: () => ({ start: startOfYear(new Date()), end: new Date() }) },
];

<DateRangePicker value={range} onChange={setRange} label="Date range" presets={customPresets} />

DateRangePicker β€” Fixed Presets (hideCustom)

DateRangePicker β€” Fixed Presets (hideCustom)

Pass hideCustom to remove the 'Custom' calendar-selection button from the Quick Select sidebar. Use when only specific preset ranges are valid for a page β€” e.g. Search Term Impressions only supports Recent Week and Recent Date.

Show code
<DateRangePicker
  value={range}
  onChange={setRange}
  label="Date range"
  presets={fixedPresets}
  hideCustom
/>

MetricChip

MetricChip

Compact chip for selected metrics with color dot, chart type toggles, and remove action.

SpendRevenueACoS
Show code
<MetricChip
  label="Spend"
  color="#4573D2"
  type="line"
  onTypeChange={(type) => {}}
  onRemove={() => {}}
/>

MetricsSelector

MetricsSelector

Multi-select for which metrics to show. metrics, value, onChange, max, min.

Show code
<MetricsSelector metrics={[...]} value={value} onChange={setValue} />

ExportToolbar

ExportToolbar

Dropdown with PNG and Excel export. containerRef for PNG, onExportExcel for spreadsheet.

Chart or content area for PNG export

Show code
<ExportToolbar containerRef={ref} filename="chart" onExportExcel={() => {}} />

Excel export β€” whole values (decimals: 0)

exportTableToXlsx takes a decimals option that sets the Excel number format for every numeric column (currency, number, decimal, compact). Default 2 gives $12,500.00; pass 0 for whole values ($12,500) with no trailing .00. Integer and percent columns are unaffected, and cells stay real numbers so SUM() still works.

Download the sheet twice to compare the two number formats.

Show code
exportTableToXlsx(columns, rows, 'revenue.xlsx', 'Data', {
  currencyCode: 'USD',
  decimals: 0, // $2,500,000,000 instead of $2,500,000,000.00
})

Toggle

Toggle

Switch control. checked, onChange, label, disabled.

Enable feature
On
Show code
<Toggle checked={checked} onChange={setChecked} label="Enable feature" />

TimeAggregation

TimeAggregation

Selector for Daily / Weekly / Monthly. value, onChange.

Show code
<TimeAggregation value={value} onChange={setValue} />

RollUpSelector

RollUpSelector

Grouping selector. options, value, onChange.

Show code
<RollUpSelector options={[...]} value={value} onChange={setValue} />

FrequencySelector

FrequencySelector

Frequency of tracking with Save. title, options, value, onChange, onSave.

Frequency Of Tracking

Show code
<FrequencySelector title="Frequency" options={[...]} value={value} onChange={setValue} onSave={() => {}} />

EntitySelector

EntitySelector

Campaign and Ad Group tree selector. campaigns, selectedCampaignIds, selectedAdGroupIds, onChange.

Select Campaign Types:
Show code
<EntitySelector campaigns={[...]} onChange={(c, a) => {}} />

ViewModeToggle

Chart / Table Switch

Icon toggle for switching between chart and table views. value, onChange, size.

Active: chart
Show code
<ViewModeToggle value={mode} onChange={setMode} />

Size Variants & Disabled

Available in sm and md sizes. Can be disabled.

sm
md
off
Show code
<ViewModeToggle value="chart" onChange={...} size="sm" />

LayoutSelector

Dashboard Layout Picker

Popover with grid thumbnails for choosing dashboard layout. options, value, onChange.

Selected: Single
Show code
<LayoutSelector options={layouts} value={layout} onChange={setLayout} />

DataLabelsToggle

Data Labels Toggle

Toggle button to show/hide data labels on charts. pressed, onPressedChange, size, disabled.

Data labels: hidden
Show code
<DataLabelsToggle pressed={on} onPressedChange={setOn} />

DataExportButton

Data Export Button

Downloads table data as CSV. getData (async), columns, fileName, visibleColumnIds.

Show code
<DataExportButton getData={async () => rows} columns={columns} fileName="export" />

TableToolbar

TableToolbar

Generic table toolbar composing column-selector, export, fullscreen, and chart-toggle actions. All slots are optional. Pass exportSlot for custom export buttons with toasts.

Custom actions here
Show code
<TableToolbar
  featureToolbar={<span className="text-sm text-iw-text-secondary">Custom actions here</span>}
  chartToggle={{ showChart, onToggleChart: () => setShowChart(v => !v) }}
  showColumnSelector
  onColumnSelectorOpen={() => alert('Open column selector')}
  showExport
  exportProps={{ getData: async () => rows, columns, fileName: 'export' }}
  showFullscreen
  fullscreenExpanded={fullscreenExpanded}
  onFullscreenChange={setFullscreenExpanded}
  targetRef={containerRef}
/>

Card

Basic Card

Generic surface container with optional header slot.

Simple card content

Card Header

Card with header slot

Show code
<Card>Content goes here</Card>
<Card header={<span>Header</span>}>With header slot</Card>

InputField

Sizes & States

InputField supports sm, md, lg sizes with error, disabled, and readOnly states.

Show code
<InputField label="Name" size="md" value={value} onChange={setValue} />
<InputField label="Error" error="Required" value="" onChange={() => {}} />
<InputField label="Disabled" disabled value="Cannot edit" onChange={() => {}} />

FileUpload

Image Upload (300Γ—180, ≀200 KB)

Image variant renders an inline thumbnail. Mirrors the Sponsored Brand logo upload constraints in Walmart Add Campaign (300Γ—180 px, max 200 KB).

Choose a file or drag & drop it here

PNG or JPG. Exactly 300Γ—180 px, up to 200 KB.

Show code
<FileUpload
  variant="image"
  accept="image/*"
  value={file}
  onChange={setFile}
  validate={validateImageDimensions({ width: 300, height: 180 })}
  maxSizeBytes={200 * 1024}
  label="Brand logo"
/>

Video Upload (1920Γ—1080 or 3840Γ—2160, 5–30s, ≀500 MB)

Video variant renders an inline player and chains dimension + duration validators. Mirrors the Sponsored Video constraints in Walmart Add Campaign.

Choose a file or drag & drop it here

MP4. 1920Γ—1080 or 3840Γ—2160 px, 5–30 seconds, up to 500 MB.

Show code
<FileUpload
  variant="video"
  accept="video/*"
  value={file}
  onChange={setFile}
  validate={[
    validateVideoDimensions([{ width: 1920, height: 1080 }, { width: 3840, height: 2160 }]),
    validateVideoDuration({ minSec: 5, maxSec: 30 }),
  ]}
  maxSizeBytes={500 * 1024 * 1024}
  label="Sponsored video"
/>

Generic File (.srt captions)

Generic variant renders just the filename + size. No additional validators β€” accept restricts the picker.

Choose a file or drag & drop it here

SubRip captions (.srt) attached to the sponsored video.

Show code
<FileUpload
  variant="generic"
  accept=".srt"
  value={file}
  onChange={setFile}
  label="Captions"
/>

Button

Primary, Secondary, Tertiary, and None Buttons

Primary and secondary buttons support optional icons. Tertiary is text-forward for low-emphasis actions. None is a neutral grey-bordered button.

Show code
<Button variant="primary" startIcon={<Plus />}>New Rule</Button>
<Button variant="secondary">View History</Button>
<Button variant="tertiary">Cancel</Button>
<Button variant="none">Filter</Button>

SelectField

Select Field

Native select with boxed and underline variants using primitives theme tokens.

Show code
<SelectField value={value} onChange={setValue} label="Target">
  <option value="line_items">Line Items</option>
  <option value="ad_groups">Ad Groups</option>
</SelectField>

CheckboxField

Checkbox Field

Checkbox states aligned to the primitive visual system. The label prop accepts a plain string or any ReactNode β€” useful for inline badges next to a name.

Show code
<CheckboxField checked={checked} onChange={setChecked} label="Enable undo schedule" />

// ReactNode label β€” name + inline badge
<CheckboxField
  checked={checked}
  onChange={setChecked}
  label={
    <span className="inline-flex items-baseline gap-1.5">
      <span>Enable undo schedule</span>
      <span className="text-[10px] font-medium uppercase tracking-wide text-iw-text-muted">beta</span>
    </span>
  }
/>

RadioField

Radio Field

Radio states aligned to primitive tokens with selected and disabled visuals.

Show code
<RadioField checked={value === 'a'} onChange={(checked) => checked && setValue('a')} />

TimeField

Time Field

Time input control with the same primitive visual system as other form controls.

Show code
<TimeField value={value} onChange={setValue} label="Execution Time" />

Toast

Toast Notifications

Three design options β€” Accent, Solid, and Soft β€” across success, info, warning, failure (error), and abort intents. Pick a design below and trigger live toasts; pass it via the design option.

Accent

White surface, left colour accent + tinted icon chip.

Rule saved

Your automation rule is now live.

Execution started

We’ll let you know when it finishes.

Budget threshold

This campaign is at 90% of its daily budget.

Save failed

We couldn’t save the rule. Please try again.

Run cancelled

The bulk update was aborted before completion.

Solid

Fully filled in the intent colour, white text.

Rule saved

Your automation rule is now live.

Execution started

We’ll let you know when it finishes.

Budget threshold

This campaign is at 90% of its daily budget.

Save failed

We couldn’t save the rule. Please try again.

Run cancelled

The bulk update was aborted before completion.

Soft

Light tinted background with a matching border.

Rule saved

Your automation rule is now live.

Execution started

We’ll let you know when it finishes.

Budget threshold

This campaign is at 90% of its daily budget.

Save failed

We couldn’t save the rule. Please try again.

Run cancelled

The bulk update was aborted before completion.

Live design
Show code
const { toasts, addToast, removeToast } = useToast();

// design: 'accent' (default) | 'solid' | 'soft'
addToast('success', 'Your automation rule is now live.', { title: 'Rule saved', design: 'solid' });
addToast('error', 'We couldn’t save the rule.', { title: 'Save failed', design: 'soft' });

// or set one design for every toast on the container:
<ToastContainer toasts={toasts} onRemove={removeToast} design="accent" />

DateTimePicker

Date & Time Picker

Single date-time picker and date-only mode (time disabled), including underline variant.

Datetime: 2026-04-07T14:30:00Z

Date only: 2026-04-07

Show code
<DateTimePicker value={dateTime} onChange={setDateTime} label="Start Date" />
<DateTimePicker value={dateOnly} onChange={setDateOnly} showTime={false} variant="underline" label="Execution Date" />

CalendarRangeModal

Calendar Range Modal

Modal calendar for selecting a date range.

Show code
<CalendarRangeModal
  isOpen={open}
  onClose={() => setOpen(false)}
  initialStartDate={start}
  initialEndDate={end}
  onApply={(s, e) => { setStart(s); setEnd(e); setOpen(false); }}
/>

DateRangeSelector

Date Range Selector

Preset dropdown with optional custom range support.

Preset: last7 | Range: 2026-03-31 to 2026-04-07

Show code
<DateRangeSelector
  selectedPreset={preset}
  onPresetChange={setPreset}
  customRange={{ startDate: start, endDate: end }}
  onCustomRangeChange={(s, e) => { setStart(s); setEnd(e); }}
/>

SimpleAccordion

Single Expand

Only one item can be open at a time. Supports badges and disabled items.

Expanded: none

Show code
<SimpleAccordion items={items} expanded={expanded} onExpandedChange={setExpanded} />

Multiple Expand

Multiple items can be expanded simultaneously.

Show code
<SimpleAccordion items={items} allowMultiple />

Checkbox

Checkbox States & Sizes

Standalone checkbox with sizes, indeterminate state, and optional label.

sm

md

lg

indeterminate

disabled

Show code
<Checkbox checked={checked} onCheckedChange={setChecked} label="Enable" size="md" />

FilterConditionCell

With Conditions

Toggle to show/hide filter criteria. Designed for use inside table cells.

Show code
<FilterConditionCell conditions={[{ fieldLabel: 'Campaign', opLabel: 'is', valueStr: 'SP' }]} />

Empty State

Renders an em-dash when no conditions are present.

β€”
Show code
<FilterConditionCell conditions={[]} />

SearchInput

Search Input

Text input with search icon, optional clear button, and debounce support.

Value: (empty)

Show code
<SearchInput value={value} onChange={setValue} onSearch={handleSearch} debounceMs={300} />

SelectableTable

Interactive Selection

Table with checkbox column, header select-all, and sortable columns.

CampaignStatusSpendROAS
Brand Defence – SPActive$1,240.504.2x
Category Conquest – SBActive$890.303.1x
Retargeting – SDPaused$320.002.8x
New Launch – SPActive$2,100.755.6x
Competitor ASIN – SPEnded$450.201.9x

0 of 5 selected

Show code
<SelectableTable columns={cols} rows={rows} rowIdField="id"
  selectedIds={selectedIds} onSelectionChange={setSelectedIds} />

Radio (single-select)

selectionMode='radio' replaces checkboxes with radio buttons β€” selecting a row deselects all others. Useful for picking one item from a list.

CampaignStatusSpendROAS
Brand Defence – SPActive$1,240.504.2x
Category Conquest – SBActive$890.303.1x
Retargeting – SDPaused$320.002.8x
New Launch – SPActive$2,100.755.6x
Competitor ASIN – SPEnded$450.201.9x

Selected: none

Show code
<SelectableTable
  selectionMode="radio"
  columns={cols} rows={rows} rowIdField="id"
  selectedIds={selectedIds} onSelectionChange={setSelectedIds} />

Loading State

Shows loading overlay while data is being fetched.

CampaignStatusSpendROAS
Loading...
Show code
<SelectableTable loading columns={cols} rows={[]} ... />

Row Height Constraints

rowMinHeight and rowMaxHeight set a floor/ceiling on each row. Useful when cells contain variable-height content like tags or wrapped text.

CampaignStatusSpendROAS
Brand Defence – SPActive$1,240.504.2x
Category Conquest – SBActive$890.303.1x
Retargeting – SDPaused$320.002.8x
New Launch – SPActive$2,100.755.6x
Competitor ASIN – SPEnded$450.201.9x
Show code
<SelectableTable
  rowMinHeight="48px"
  rowMaxHeight="72px"
  columns={cols} rows={rows} rowIdField="id"
  selectedIds={selectedIds} onSelectionChange={setSelectedIds} />

TransparentCard

Transparent vs Regular Card

TransparentCard removes border, background, and shadow from the base Card component.

Regular Card

Has border, background, and shadow.

Transparent Card

No border, no background, no shadow.

Show code
<Card header="Regular">content</Card>
<TransparentCard header="Transparent">content</TransparentCard>

TreeSelect

Basic Tree

Two-level checkbox tree with parent indeterminate states and selection counts.

Sponsored Products0/3
Sponsored Brands0/2
Sponsored Display0/2

Selected: none

Show code
<TreeSelect items={items} selectedIds={selectedIds} onSelectionChange={setSelectedIds} />

With Search

Searchable mode filters both parent and child labels.

Sponsored Products0/3
Sponsored Brands0/2
Sponsored Display0/2
Show code
<TreeSelect items={items} selectedIds={selectedIds} onSelectionChange={setSelectedIds} searchable />

RadioGroup

Horizontal Orientation

Inline radio group for simple binary or small-set choices (e.g. Include/Exclude targeting).

Selected: include

Show code
<RadioGroup
  options={[{ value: 'include', label: 'Include' }, { value: 'exclude', label: 'Exclude' }]}
  value={value}
  onChange={setValue}
  orientation="horizontal"
/>

Vertical Orientation

Stacked radio group for longer option lists (e.g. bid edit type selector).

Selected: new-bid

Show code
<RadioGroup
  options={[{ value: 'new-bid', label: 'Set New Bid' }, ...]}
  value={value}
  onChange={setValue}
  orientation="vertical"
/>

Disabled States

Individual options or the entire group can be disabled.

Single option disabled

Entire group disabled

Show code
<RadioGroup options={[...]} value="active" disabled />

Custom Option Label Class

optionLabelClassName applies extra Tailwind classes to every option label span β€” useful for muted, italic, or otherwise styled labels.

Show code
<RadioGroup
  options={[{ value: 'set', label: 'Set new bid' }, ...]}
  value={value}
  onChange={setValue}
  orientation="vertical"
  optionLabelClassName="italic text-iw-text-muted"
/>

IWDialog

Default Dialog

Modal dialog with header (auto close button), scrollable body, and footer with action buttons.

Show code
<IWDialog isOpen={open} onClose={() => setOpen(false)}>
  <IWDialogHeader title="Edit Line Item" />
  <IWDialogBody>...</IWDialogBody>
  <IWDialogFooter>
    <Button variant="secondary" onClick={onClose}>Cancel</Button>
    <Button variant="primary" onClick={onSave}>Save</Button>
  </IWDialogFooter>
</IWDialog>

Branded Header

Use variant='branded' for a primary-colored header (e.g. bulk edit confirmation).

Show code
<IWDialogHeader title="Bulk Update" variant="branded" />

Size Variants

Sizes: sm (400px), md (560px), lg (760px), xl (960px), full (95vw).

Show code
<IWDialog isOpen={open} onClose={onClose} size="xl">...</IWDialog>

IWDrawer

Right Drawer (default)

Slide-in panel from the right edge. Supports header, scrollable body, and footer.

Show code
<IWDrawer isOpen={open} onClose={() => setOpen(false)}>
  <IWDrawerHeader title="Settings" />
  <IWDrawerBody>...</IWDrawerBody>
  <IWDrawerFooter>
    <Button variant="primary" onClick={onClose}>Apply</Button>
  </IWDrawerFooter>
</IWDrawer>

Left Drawer

Slides in from the left edge. Useful for navigation or filter panels.

Show code
<IWDrawer isOpen={open} onClose={onClose} position="left" width="20rem">...</IWDrawer>

MetricFilterDialog

Number Filter

Filter by numeric metrics with operators: equal, less than, greater than, between, etc.

Show code
<MetricFilterDialog
  open={open}
  onClose={() => setOpen(false)}
  title="Filter by Impressions"
  filterType="number"
  onApply={(result) => console.log(result)}
/>

Text Filter

Filter by text with operators: equals, contains, does not contain, not equals.

Show code
<MetricFilterDialog
  open={open}
  onClose={() => setOpen(false)}
  title="Filter by Campaign Name"
  filterType="text"
  onApply={(result) => console.log(result)}
/>

CopyButton

Default (always visible)

Standalone copy button. Click to copy the text; the icon briefly becomes a checkmark.

Campaign name test99673
Show code
<CopyButton text="Campaign name test99673" />

With onCopy callback

Fires onCopy after a successful write β€” use this to trigger a page-level toast.

some-api-key-123
Show code
<CopyButton
  text="some-api-key-123"
  label="Copy API key"
  onCopy={(text) => console.log('Copied:', text)}
/>

Hover-reveal (table cell usage)

Add opacity-0 group-hover:opacity-100 via className β€” the parent must have the 'group' class. This is how EntityNameCell uses it.

Campaign name test99673

Hover the box above to reveal the icon.

Show code
<div className="group flex items-center gap-1 w-48 border rounded p-2">
  <span className="flex-1 truncate text-sm">Campaign name test99673</span>
  <CopyButton
    text="Campaign name test99673"
    className="opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
  />
</div>

Input + Label (bare)

Bare Input + Label

Unopinionated Input and Label primitives for composing custom form fields (distinct from InputField).

Show code
<div className="space-y-2">
  <Label htmlFor="campaign">Campaign name</Label>
  <Input id="campaign" placeholder="Summer Sale" />
</div>

Select (bare Radix)

Bare Select

Radix Select composition β€” SelectTrigger / SelectValue / SelectContent / SelectItem.

Show code
<Select value={value} onValueChange={setValue}>
  <SelectTrigger className="w-[220px]">
    <SelectValue placeholder="Ad type" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="sp">Sponsored Products</SelectItem>
    <SelectItem value="sb">Sponsored Brands</SelectItem>
  </SelectContent>
</Select>

Accordion (Radix compound)

Radix Accordion

Compound Accordion / AccordionItem / AccordionTrigger / AccordionContent (distinct from SimpleAccordion above).

Spend, revenue, and ROAS for the selected period.

Show code
<Accordion type="single" collapsible>
  <AccordionItem value="a">
    <AccordionTrigger>Performance</AccordionTrigger>
    <AccordionContent>Spend, revenue, and ROAS.</AccordionContent>
  </AccordionItem>
</Accordion>

ActionMenu

Action Menu

Simple trigger + item list menu for row/bulk actions.

Show code
<ActionMenu
  trigger={<Button size="sm">Actions</Button>}
  items={[
    { label: 'Edit', onClick: () => {} },
    { label: 'Duplicate', onClick: () => {} },
    { label: 'Delete', onClick: () => {}, disabled: true },
  ]}
/>

Command

Command

cmdk-based command list (distinct from CommandPalette composition).

Show code
<Command className="rounded-iw-md border">
  <CommandInput placeholder="Search metrics…" />
  <CommandList>
    <CommandEmpty>No results.</CommandEmpty>
    <CommandGroup heading="Metrics">
      <CommandItem>Spend</CommandItem>
      <CommandItem>Revenue</CommandItem>
    </CommandGroup>
  </CommandList>
</Command>

ContextMenu

Context Menu

Right-click the target to open a Radix context menu.

Right-click this area
Show code
<ContextMenu>
  <ContextMenuTrigger>Right click me</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Open</ContextMenuItem>
    <ContextMenuItem>Rename</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>

Dialog (Radix)

Radix Dialog

Compound Dialog primitives (distinct from IWDialog branded modal).

Show code
<Dialog>
  <DialogTrigger asChild><Button>Open</Button></DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Confirm</DialogTitle>
      <DialogDescription>Apply changes to this campaign?</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <Button>Confirm</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Popover

Popover

Radix Popover for lightweight floating content.

Show code
<Popover>
  <PopoverTrigger asChild><Button>Filters</Button></PopoverTrigger>
  <PopoverContent>Filter panel content</PopoverContent>
</Popover>

Tooltip (Radix)

Radix Tooltip

TooltipProvider + TooltipTrigger + TooltipContent (distinct from IWTooltip).

Show code
<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild><Button>Hover me</Button></TooltipTrigger>
    <TooltipContent>Helpful hint</TooltipContent>
  </Tooltip>
</TooltipProvider>

Tabs

Tabs

Content tabs with TabsList / TabsTrigger / TabsContent.

High-level campaign metrics for the selected period.
Show code
<Tabs defaultValue="overview">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="details">Details</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">Overview panel</TabsContent>
</Tabs>

Skeleton

Skeleton

Loading placeholders sized via className.

Show code
<Skeleton className="h-4 w-48" />
<Skeleton className="h-24 w-full rounded-iw-md" />

Separator

Separator

Horizontal or vertical decorative rule.

Above

Left
Right
Show code
<Separator />
<Separator orientation="vertical" />

ScrollArea

Scroll Area

Thin-scrollbar overflow container for long lists.

  • Campaign row 1
  • Campaign row 2
  • Campaign row 3
  • Campaign row 4
  • Campaign row 5
  • Campaign row 6
  • Campaign row 7
  • Campaign row 8
  • Campaign row 9
  • Campaign row 10
  • Campaign row 11
  • Campaign row 12
  • Campaign row 13
  • Campaign row 14
  • Campaign row 15
  • Campaign row 16
  • Campaign row 17
  • Campaign row 18
  • Campaign row 19
  • Campaign row 20
Show code
<ScrollArea className="h-40 w-64 rounded border">…</ScrollArea>

Toaster (Sonner)

Sonner Toaster

Imperative toast() API with a mounted Toaster (distinct from shared Toast / useToast).

Show code
<Toaster />
<Button onClick={() => toast.success('Saved')}>Notify</Button>