RichAPI design system

Forms and navigation

Field with a custom control

Field adds the label, help text and error around any control.

Credits per day.

JSX
<Field id="cap" label="Daily cap" help="Credits per day." required>
  <input id="cap" type="number" className="ra-input" defaultValue={500} aria-describedby="cap-help" />
</Field>
HTML
<div class="g-frame g-frame--sm g-frame--stack"><div class="ra-field"><label class="ra-field__label" for="cap">Daily cap<span class="ra-field__req" aria-hidden="true">*</span></label><input id="cap" type="number" class="ra-input" aria-describedby="cap-help" value="500"/><p class="ra-field__help" id="cap-help">Credits per day.</p></div></div>

Large input

size="lg" is 40px high, for the describe box.

JSX
<Input size="lg" aria-label="Describe what you need" placeholder="Describe what you need, for example: find emails for 200 founders" />
HTML
<div class="g-frame g-frame--full"><input id="_R_0_" class="ra-input ra-input--lg" aria-label="Describe what you need" placeholder="Describe what you need, for example: find emails for 200 founders"/></div>

Text input

Shown in logs and usage reports

JSX
<Input label="Key name" help="Shown in logs and usage reports" placeholder="production-backend" />
HTML
<div class="g-frame g-frame--sm g-frame--stack"><div class="ra-field"><label class="ra-field__label" for="_R_0_">Key name</label><input id="_R_0_" class="ra-input" aria-describedby="_R_0_-help" placeholder="production-backend"/><p class="ra-field__help" id="_R_0_-help">Shown in logs and usage reports</p></div></div>

Error state

A key with this name exists

JSX
<Input label="Key name" defaultValue="production" error="A key with this name exists" required />
HTML
<div class="g-frame g-frame--sm g-frame--stack"><div class="ra-field"><label class="ra-field__label" for="_R_0_">Key name<span class="ra-field__req" aria-hidden="true">*</span></label><input id="_R_0_" class="ra-input" required="" aria-describedby="_R_0_-error" aria-invalid="true" value="production"/><p class="ra-field__error" id="_R_0_-error">A key with this name exists</p></div></div>

Search with shortcut

⌘K
JSX
<Input aria-label="Search" placeholder="Search endpoints" leading={<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true">
  <circle cx="7" cy="7" r="4.5" />
  <path d="m10.5 10.5 3 3" />
</svg>} trailing={<Kbd>⌘K</Kbd>} />
HTML
<div class="g-frame g-frame--sm g-frame--stack"><div class="ra-input-wrap"><span class="ra-input-wrap__lead"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="7" cy="7" r="4.5"></circle><path d="m10.5 10.5 3 3"></path></svg></span><input id="_R_0_" class="ra-input" aria-label="Search" placeholder="Search endpoints"/><span class="ra-input-wrap__trail"><kbd class="ra-kbd">⌘K</kbd></span></div></div>

Textarea

JSX
<Textarea label="Prompt" placeholder="Describe the data you want" />
HTML
<div class="g-frame g-frame--sm g-frame--stack"><div class="ra-field"><label class="ra-field__label" for="_R_0_">Prompt</label><textarea id="_R_0_" class="ra-input ra-textarea" placeholder="Describe the data you want"></textarea></div></div>

Select

JSX
<Select label="Plan" defaultValue="Starter">
  <option>Sandbox</option>
  <option>Starter</option>
  <option>Growth</option>
</Select>
HTML
<div class="g-frame g-frame--sm g-frame--stack"><div class="ra-field"><label class="ra-field__label" for="_R_0_">Plan</label><select id="_R_0_" class="ra-input ra-select"><option>Sandbox</option><option selected="">Starter</option><option>Growth</option></select></div></div>

Checkboxes and radios

JSX
<Checkbox label="Send receipts" description="Email a receipt after each top-up" defaultChecked />
<Checkbox label="Low-credit alerts" description="Warn at 10% credits left" />
<Radio name="cycle" label="Monthly" description="Billed on the 1st" defaultChecked />
<Radio name="cycle" label="Annual" description="Two months free" />
HTML
<div class="g-frame g-frame--sm g-frame--stack"><label class="ra-check"><input type="checkbox" class="ra-check__input" checked=""/><span class="ra-check__text">Send receipts<small>Email a receipt after each top-up</small></span></label><label class="ra-check"><input type="checkbox" class="ra-check__input"/><span class="ra-check__text">Low-credit alerts<small>Warn at 10% credits left</small></span></label><label class="ra-radio"><input type="radio" class="ra-radio__input" name="cycle" checked=""/><span class="ra-radio__text">Monthly<small>Billed on the 1st</small></span></label><label class="ra-radio"><input type="radio" class="ra-radio__input" name="cycle"/><span class="ra-radio__text">Annual<small>Two months free</small></span></label></div>

Switch

JSX
<Switch label="Auto-reload credits" defaultChecked />
HTML
<label class="ra-switch"><input type="checkbox" role="switch" class="ra-switch__input" checked=""/><span class="ra-switch__track" aria-hidden="true"></span><span class="ra-switch__label">Auto-reload credits</span></label>

Grouped endpoints

Options grouped by category. Open it: the arrow keys follow the grouped order.

Endpoint
JSX
<Combobox label="Endpoint" options={[
  {
    value: "people_search",
    label: "People Search",
    hint: "0.1 cr",
    group: "Search",
  },
  {
    value: "enrich_profile",
    label: "Enrich Profile",
    hint: "1 cr",
    group: "LinkedIn enrichment",
  },
  {
    value: "email_finder",
    label: "Email Finder",
    hint: "5 cr",
    group: "Waterfalls",
  },
  {
    value: "enrich_company",
    label: "Company Enrichment",
    hint: "1 cr",
    group: "LinkedIn enrichment",
  },
]} defaultValue="email_finder" searchPlaceholder="Search endpoints" />
HTML
<div class="g-frame g-frame--md" style="min-height:320px"><div class="ra-combo"><span class="ra-combo__label" id="_R_0_-label">Endpoint</span><button type="button" id="_R_0_-btn" class="ra-combo__btn" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="_R_0_-label _R_0_-btn"><span class="ra-combo__value">Email Finder</span><span class="ra-combo__hint">5 cr</span><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 6 4 4 4-4"></path></svg></button></div></div>

Endpoint picker

Button, search and listbox. Open it to filter by name or category.

Endpoint
JSX
<Combobox label="Endpoint" options={[
  {
    value: "people_search",
    label: "People Search",
    hint: "0.1 cr",
    keywords: ["Search"],
  },
  {
    value: "enrich_profile",
    label: "Enrich Profile",
    hint: "1 cr",
    keywords: ["LinkedIn enrichment"],
  },
  {
    value: "email_finder",
    label: "Email Finder",
    hint: "5 cr",
    keywords: ["Waterfalls"],
  },
  {
    value: "enrich_company",
    label: "Company Enrichment",
    hint: "1 cr",
    keywords: ["LinkedIn enrichment"],
  },
]} defaultValue="email_finder" searchPlaceholder="Search endpoints" />
HTML
<div class="g-frame g-frame--md" style="min-height:280px"><div class="ra-combo"><span class="ra-combo__label" id="_R_0_-label">Endpoint</span><button type="button" id="_R_0_-btn" class="ra-combo__btn" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="_R_0_-label _R_0_-btn"><span class="ra-combo__value">Email Finder</span><span class="ra-combo__hint">5 cr</span><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 6 4 4 4-4"></path></svg></button></div></div>

Segmented

JSX
<Segmented label="Theme" defaultValue="light" options={[
  {
    value: "light",
    label: "Light",
    icon: <svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true">
      <path d="M8 3v1M8 12v1M3 8h1M12 8h1M5 5l.7.7M10.3 10.3l.7.7M11 5l-.7.7M5.7 10.3 5 11" />
    </svg>,
  },
  {
    value: "dark",
    label: "Dark",
    icon: <svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true">
      <path d="M13 9.5A5.5 5.5 0 0 1 6.5 3 5.5 5.5 0 1 0 13 9.5Z" />
    </svg>,
  },
  {
    value: "system",
    label: "System",
    icon: <svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true">
      <path d="M2.5 3.5h11v7h-11zM6 13h4" />
    </svg>,
  },
]} />
HTML
<div class="ra-seg" role="group" aria-label="Theme"><button type="button" class="ra-seg__item" aria-pressed="true"><svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M8 3v1M8 12v1M3 8h1M12 8h1M5 5l.7.7M10.3 10.3l.7.7M11 5l-.7.7M5.7 10.3 5 11"></path></svg>Light</button><button type="button" class="ra-seg__item" aria-pressed="false"><svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M13 9.5A5.5 5.5 0 0 1 6.5 3 5.5 5.5 0 1 0 13 9.5Z"></path></svg>Dark</button><button type="button" class="ra-seg__item" aria-pressed="false"><svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M2.5 3.5h11v7h-11zM6 13h4"></path></svg>System</button></div>

Tabs

curl https://api.richapi.ai/v1/run -H "Authorization: Bearer $KEY"
JSX
<Tabs label="Language" items={[
  {
    value: "curl",
    label: "curl",
    content: <code style={{
      fontFamily: "var(--ra-font-mono)",
      fontSize: "var(--ra-text-sm)",
    }}>
      curl https://api.richapi.ai/v1/run -H "Authorization: Bearer $KEY"
    </code>,
  },
  {
    value: "node",
    label: "Node",
    content: <code style={{
      fontFamily: "var(--ra-font-mono)",
      fontSize: "var(--ra-text-sm)",
    }}>
      await richapi.run("linkedin.profile", 
      { url }
      )
    </code>,
  },
  {
    value: "py",
    label: "Python",
    content: <code style={{
      fontFamily: "var(--ra-font-mono)",
      fontSize: "var(--ra-text-sm)",
    }}>richapi.run("linkedin.profile", url=url)</code>,
  },
]} />
HTML
<div class="g-frame g-frame--md"><div class="ra-tabs"><div class="ra-tabs__list" role="tablist" aria-label="Language"><button type="button" role="tab" class="ra-tabs__tab" id="_R_0_-tab-0" aria-selected="true" aria-controls="_R_0_-panel" tabindex="0">curl</button><button type="button" role="tab" class="ra-tabs__tab" id="_R_0_-tab-1" aria-selected="false" aria-controls="_R_0_-panel" tabindex="-1">Node</button><button type="button" role="tab" class="ra-tabs__tab" id="_R_0_-tab-2" aria-selected="false" aria-controls="_R_0_-panel" tabindex="-1">Python</button></div><div class="ra-tabs__panel" role="tabpanel" id="_R_0_-panel" aria-labelledby="_R_0_-tab-0" tabindex="0"><code style="font-family:var(--ra-font-mono);font-size:var(--ra-text-sm)">curl https://api.richapi.ai/v1/run -H &quot;Authorization: Bearer $KEY&quot;</code></div></div></div>

Tag input

Enter or comma adds a tag. Backspace on an empty input removes the last one.

stripe.comlinear.appnotion.so

Press Enter to add.

JSX
<TagInput label="Allowed domains" help="Press Enter to add." defaultValue={["stripe.com", "linear.app", "notion.so"]} />
HTML
<div class="ra-field"><label class="ra-field__label" for="_R_0_">Allowed domains</label><div class="ra-tags"><span class="ra-tag">stripe.com<button type="button" class="ra-tag__remove" aria-label="Remove stripe.com"><svg class="ra-icon ra-icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></svg></button></span><span class="ra-tag">linear.app<button type="button" class="ra-tag__remove" aria-label="Remove linear.app"><svg class="ra-icon ra-icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></svg></button></span><span class="ra-tag">notion.so<button type="button" class="ra-tag__remove" aria-label="Remove notion.so"><svg class="ra-icon ra-icon--sm" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></svg></button></span><input id="_R_0_" class="ra-tags__input" aria-describedby="_R_0_-help" value=""/></div><p class="ra-field__help" id="_R_0_-help">Press Enter to add.</p></div>