Tools

Tool frame

One order for every tool page: head, input, answer, family, folds, related.

openvibe-shared/kitJSON

Build it

kit.tool({ head: kit.toolHead({ icon: 'search', hue: 200, title: 'DNS lookup', task: 'Every record for a domain.', facts: ['Free'], level: 2 }), input: kit.toolInput({ name: 'd', label: 'A domain', placeholder: 'openvibe.live', button: 'Look up' }), answer: kit.answer({ title: '4 records', rows: [['A', '104.21.32.1'], ['AAAA', '2606:4700::6810:2001']] }), family: kit.family({ title: 'More network tools', items: [{ href: '/tools/ping', label: 'Ping', icon: 'wave' }] }) })

Props

id
any?
head
string?
folds
list?
input
string?
answer
string?
family
string?
related
string?

Anatomy

  • toolOne order for every tool page: head, input, answer, family, folds, related.

Behaviour and access

Keyboard
Keeps the focused control in view
Outside tap
Leaves it open
Scroll
The page still scrolls
Reduced motion
Remove movement; keep the state change.
Name
Tool frame
Target
At least 44 × 44 px on touch
Focus
Visible keyboard focus; follow reading order

States

  • default

Tokens

  • color.bg.raised
  • color.text.primary

Android · Jetpack Compose

Material 3 Tool frame

Use Tool frame in Jetpack Compose with the shared tokens.

iOS · SwiftUI

Use Tool frame in SwiftUI with the shared tokens.

Markup

Default

<div class="ovk-tool"><header class="ovk-tool-head ovk-tool-head--solo" style="--ovk-tint-h:200"><span class="ovk-tool-tile" aria-hidden="true"><svg class="ovk-i" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="6.5"/><path d="m20 20-4.2-4.2"/></svg></span><h2 class="ovk-tool-title">DNS lookup</h2><p class="ovk-tool-task">Every record for a domain.</p><ul class="ovk-tool-facts"><li>Free</li></ul></header><div class="ovk-tool-card"><form class="ovk-tool-form" method="get" action="?"><label class="ovk-tool-label" for="ovk-tool-d">A domain</label><div class="ovk-tool-row"><span class="ovk-tool-field"><input id="ovk-tool-d" name="d" type="text" value="" placeholder="openvibe.live" autocomplete="off" spellcheck="false" autocapitalize="off" required><button type="button" class="ovk-tool-clear" data-ovk-clear="#ovk-tool-d" aria-label="Clear" title="Clear" hidden><svg class="ovk-i" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5.4 5.4l13.2 13.2M18.6 5.4 5.4 18.6"/></svg></button></span><button type="submit" class="ovk-btn ovk-btn--primary ovk-tool-go"><svg class="ovk-i" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="6.5"/><path d="m20 20-4.2-4.2"/></svg><span>Look up</span></button></div></form></div><div class="ovk-tool-out"><section class="ovk-answer" aria-live="polite"><div class="ovk-answer-head"><h2>4 records</h2></div><dl class="ovk-answer-rows"><div><dt>A</dt><dd>104.21.32.1</dd></div><div><dt>AAAA</dt><dd>2606:4700::6810:2001</dd></div></dl></section></div><nav class="ovk-family" aria-label="More network tools"><div class="ovk-family-head"><h2>More network tools</h2></div><div class="ovk-family-items"><a href="/tools/ping">Ping</a></div></nav></div>