Skip to content

Control

A control is the base interactive element used in form fields, available as a button or input.

Use a control button to trigger custom dropdowns, date pickers, or other interactive elements.

<div class="tng-control">
<button class="tng-control-button">Select an item</button>
</div>

Use an input control to allow users to enter text or data.

<div class="tng-control">
<input class="tng-control-input" type="text" />
</div>
<div class="tng-control">
<input class="tng-control-input" type="text" />
<button
class="p-absolute tng-icon-button is-ghost"
aria-label="More info"
>
<i aria-hidden="true" class="tng-icon icon-info"></i>
</button>
</div>
<div class="tng-control">
<i aria-hidden="true" class="tng-icon icon-car"></i>
<button class="tng-control-button">Select model</button>
<i aria-hidden="true" class="tng-icon icon-chevron-down"></i>
</div>

A dynamic label can be combined with an input control to provide context about the expected input. The label will shrink and move above the input field when the user focuses on the input.

<div class="tng-control">
<label class="tng-control-label">Email address</label>
<input class="tng-control-input" type="text" />
</div>
<div class="tng-control">
<label class="tng-control-label is-lg">Email address</label>
<input class="tng-control-input" type="text" />
</div>

In case of an input control you can rely on the native HTML required attribute to indicate that a form control is required. If that’s not an option, you can use the is-required class anywhere within the control to show the required state.

<div class="tng-control">
<button class="tng-control-button is-required">
Select an item
</button>
<i aria-hidden="true" class="tng-icon icon-chevron-down"></i>
</div>
<div class="tng-control">
<label class="tng-control-label">Email address</label>
<input class="tng-control-input" type="text" required />
</div>
<div class="tng-control">
<input class="tng-control-input" type="text" disabled />
</div>
<div class="tng-control">
<button class="tng-control-button" disabled>Select an item</button>
</div>
<div class="tng-control is-invalid">
<input class="tng-control-input" type="text" />
</div>
<div class="tng-control is-valid">
<input class="tng-control-input" type="text" />
</div>

Floating labels (tng-control-label) must still be associated with the input via for / id. Placeholder-only inputs are not accessible — always provide a <label>.

When using the .is-required class instead of the native required attribute, also add aria-required="true" to the control so assistive technologies announce it.

The .is-invalid and .is-valid classes provide visual feedback only. Pair them with:

  • aria-invalid="true" on the control for the error state.
  • An error message linked via aria-describedby.

The native disabled attribute removes the control from tab order and communicates the state automatically — no additional ARIA needed.