---
title: "Forms: OpenVibe’s own controls · OpenVibe.Design"
canonical: "https://openvibe.design/forms"
updated: null
---

# Forms: OpenVibe’s own controls · OpenVibe.Design

HTML: [Forms: OpenVibe’s own controls · OpenVibe.Design](https://openvibe.design/forms)

Forms

# Controls that look like OpenVibe, on every site

Every select is OpenVibe’s own: a menu on a computer, a sheet from the bottom on a phone. A choice can say whether it is ready, how much is used, and how to set it up. The form underneath is the browser’s, so everything that worked still works, and a page without JavaScript keeps its plain controls.

## The select

Open it. On a phone it rises from the bottom with rows a finger tall; on a computer it opens under the button, or above it when there is more room. The keyboard works the whole way: arrows, Home and End, typing to jump, Enter, Escape.

Fallback agent

Used when Claude Code nears its weekly limit.

Chosen: **codex**

~~~~
<select id="fm-agent" name="agent" data-ov-title="Fallback agent">
  <option value="">None</option>
  <option value="codex" data-state="ok" data-badge="20% used"
          data-desc="ChatGPT plan · signed in on ada-laptop" selected>Codex</option>
  <option value="opencode" data-state="warn" data-badge="88% used"
          data-desc="5-hour window nearly full">OpenCode</option>
  <option value="minimax" disabled data-state="off" data-desc="Not signed in on this machine"
          data-href="#fm-attrs" data-href-label="Sign in">MiniMax Code</option>
</select>
~~~~

## Several, search, groups

A long list gets a search box. Groups become headings. A multiple select keeps its list open and counts what is chosen.

Model

Show on

Language

## Switches and boxes

A checkbox with `role="switch"` is a switch. Checkboxes, radios and sliders take the site’s accent. Nothing here changes a size, so a site’s own layout never moves.

  Switch back when the week frees  Tell me when it switches  Ask first  Full access Volume  A file  

## Switch rows and segmented choices

The kit builds the two rows a settings form is made of. A switch row is 56 px and the whole row is the target: an icon tile, a title, one line, and an iOS-style switch that is the native checkbox underneath, so it works without JavaScript. A segmented control puts three or four choices in one 44 px control, icons before the words.

 Burn after reading Gone once it is opened Mark as NSFW Blurred until it is opened Lock it OpenVibe can’t read what’s inside 

Visibility Public Unlisted Private

Chosen: **public**

~~~~
// The kit's builders, server or browser (openvibe-shared/kit, docs/kit.md)
kit.switchRow({
  name: 'burn_after_read', icon: 'flame',
  title: 'Burn after reading', line: 'Gone once it is opened',
})
kit.segmented({
  name: 'visibility', value: 'public', label: 'Visibility',
  items: [
    { value: 'public',   label: 'Public',   icon: 'globe' },
    { value: 'unlisted', label: 'Unlisted', icon: 'link'  },
    { value: 'private',  label: 'Private',  icon: 'lock'  },
  ],
})
~~~~

## Fields and choices

Opt in with `.ov-field` for the whole field: a label, a control 44 px tall (16 px text on a phone, so it never zooms), a hint, an error. `.ov-choice` draws a choice as a card.

API key

Sealed, never shown again.

Note

 **OpenCode Go** A month of open models, one price. Ready **Your own keys** Pay each provider by use. 

~~~~
<div class="ov-field">
  <label for="key">API key</label>
  <input id="key" name="key" autocomplete="off">
  <p class="ov-field-hint">Sealed, never shown again.</p>
</div>
~~~~

~~~~
<div class="ov-choices">
  <label class="ov-choice">
    <input type="radio" name="plan" value="go">
    <span class="ov-choice-body">
      <b class="ov-choice-title">OpenCode Go</b>
      <span class="ov-choice-desc">A month of open models</span>
    </span>
  </label>
  …
</div>
~~~~

## What it reads

Plain HTML attributes: a server that knows what a person has set up writes them, and every site draws them the same way.

| Attribute | On | What it does |
| --- | --- | --- |
| `data-desc` | option | A second line under the label. |
| `data-badge` | option | A short tag on the right: “Signed in”, “72% used”. |
| `data-state` | option | ok · warn · bad · off · new: a dot before the label, and the badge’s tone. |
| `data-icon` | option | One or two characters before the label: an emoji, a letter. |
| `data-href · data-href-label` | option | A link on the row (“Set up”), kept on a disabled choice: it says how to make it ready. |
| `data-ov-search` | select | on or off: a search box (on by itself from 9 choices). |
| `data-ov-title` | select | The phone sheet’s title; otherwise the select’s own label. |
| `data-ov-select="bare"` | select | No box of its own: for a select inside a chip or a toolbar. |
| `multiple` | select | Boxes on the rows; the list stays open; the button says “a, c” or “3 chosen”. |
| `data-ov-native` | any | Keeps the browser’s own control, on it and everything inside it. |

## Use it

On an OpenVibe site the navbar brings both files once the page settles. Anywhere else they are free (MIT). `<html data-ov-forms="off">` keeps a whole site on the browser’s own.

~~~~
<!-- On an OpenVibe site: nothing. The navbar loads both files for a page with a form control. -->
<!-- Anywhere else (MIT): -->
<link rel="stylesheet" href="https://openvibe.design/shared/ov-forms.css">
<script src="https://openvibe.design/shared/ov-forms.js" defer></script>
~~~~
