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.raisedcolor.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>