Components

Form controls

The rest of the form kit — checkboxes, radios, a custom-chevron select, textarea, range slider, input groups and field validation. Each is flat and sharp with a 1px border and no radius (only the radio dot is round), built from real form elements so they stay keyboard-accessible and form-bound.

Checkbox & radio

Both hide the native control and draw a custom indicator: a rotated-border check on ds-checkbox, an inner dot on ds-radio. The label text is part of the clickable area. Add checked on the input for the on state and disabled to lock it.

Checkbox · states
<label class="ds-checkbox">
  <input type="checkbox">
  <span class="ds-checkbox__box"></span>
  <span>Apply margin floor</span>
</label>
<label class="ds-checkbox">
  <input type="checkbox" checked>
  <span class="ds-checkbox__box"></span>
  <span>Round to nearest €10</span>
</label>
<label class="ds-checkbox">
  <input type="checkbox" checked disabled>
  <span class="ds-checkbox__box"></span>
  <span>Locked policy</span>
</label>
Radio · group
<div class="ds-radio-group">
  <label class="ds-radio">
    <input type="radio" name="rounding" checked>
    <span class="ds-radio__dot"></span>
    <span>No rounding</span>
  </label>
  <label class="ds-radio">
    <input type="radio" name="rounding">
    <span class="ds-radio__dot"></span>
    <span>Nearest €1</span>
  </label>
</div>
React
import { Checkbox } from "@diametral/design-system/react/components/Checkbox.js";
import { Radio, RadioGroup } from "@diametral/design-system/react/components/Radio.js";

<Checkbox defaultChecked onChange={(on) => console.log(on)}>
  Round to nearest €10
</Checkbox>

<RadioGroup
  name="rounding"
  defaultValue="none"
  options={[
    { value: "none", label: "No rounding" },
    { value: "one", label: "Nearest €1" },
    { value: "ten", label: "Nearest €10", disabled: true },
  ]}
  onChange={(v) => console.log(v)}
/>

Select

A native <select> wrapped in ds-select picks up the flat ds-input look and a custom chevron drawn as a background SVG. Add ds-select--block for a full-width control.

Default · full width
<div class="ds-select">
  <select>
    <option>LBC_FR</option>
    <option>LBC_US</option>
    <option>LBC_UK</option>
  </select>
</div>

<div class="ds-select ds-select--block">
  <select>
    <option>Standard rate card</option>
    <option>Strategic accounts</option>
    <option>Pilot pricing</option>
  </select>
</div>
React
import { Select } from "@diametral/design-system/react/components/Select.js";

<Select
  block
  defaultValue="fr"
  options={[
    { value: "fr", label: "LBC_FR" },
    { value: "us", label: "LBC_US" },
    { value: "uk", label: "LBC_UK" },
  ]}
  onChange={(e) => console.log(e.target.value)}
/>

Textarea

A ds-textarea shares the input border and padding, sets a comfortable min-height and resizes vertically only.

Textarea
<div class="ds-field">
  <label>Pricing note</label>
  <textarea class="ds-textarea" placeholder="Explain the override…"></textarea>
</div>
React
import { Textarea } from "@diametral/design-system/react/components/Textarea.js";

<Textarea rows={4} placeholder="Explain the override…" />

Range

A styled input[type=range] with a 4px flat track and a 14px square ink thumb, in WebKit and Firefox.

Range slider
<div class="ds-field">
  <label>Discount ceiling</label>
  <input class="ds-range" type="range" min="0" max="100" value="35">
</div>
React
import { Range } from "@diametral/design-system/react/components/Range.js";

<Range min={0} max={100} defaultValue={35}
  onChange={(v) => console.log(v)} />

Input group

An ds-input-group glues addons to a control so they share borders and read as one unit. Put an ds-input-group__addon before and/or after the input.

Prefix · suffix
.csv
<div class="ds-input-group">
  <span class="ds-input-group__addon">€</span>
  <input class="ds-input ds-input--number" type="number" value="900">
</div>

<div class="ds-input-group">
  <input class="ds-input" type="text" value="rate-card">
  <span class="ds-input-group__addon">.csv</span>
</div>
React
import { InputGroup } from "@diametral/design-system/react/components/InputGroup.js";
import { Input } from "@diametral/design-system";

<InputGroup before="€">
  <Input number defaultValue={900} />
</InputGroup>

Validation

Add ds-field--error or ds-field--success to a field to color its control's border, and a ds-field__hint below it for helper text — use ds-field__hint--error / ds-field__hint--success for the matching tone.

Error · success · neutral hint
Day rate must be greater than zero.
Above the 30% floor.
Maximum discount a sales rep can apply unaided.
<div class="ds-field ds-field--error">
  <label>Day rate</label>
  <input class="ds-input ds-input--number" type="number" value="0">
  <span class="ds-field__hint ds-field__hint--error">Day rate must be greater than zero.</span>
</div>

<div class="ds-field ds-field--success">
  <label>Margin</label>
  <input class="ds-input ds-input--number" type="number" value="32">
  <span class="ds-field__hint ds-field__hint--success">Above the 30% floor.</span>
</div>

<div class="ds-field">
  <label>Discount ceiling</label>
  <input class="ds-input ds-input--number" type="number" value="15">
  <span class="ds-field__hint">Maximum discount a sales rep can apply unaided.</span>
</div>
React
import { Field, Input } from "@diametral/design-system";
import { FieldHint } from "@diametral/design-system/react/components/FieldHint.js";

<div class="ds-field ds-field--error">
  <Field label="Day rate">
    <Input number defaultValue={0} />
  </Field>
  <FieldHint status="error">Day rate must be greater than zero.</FieldHint>
</div>