Forms

Input contract from the legacy SAGA_INPUT mixin (DS-016): light-gray border, blue focus, clay invalid, 6px radius, italic beige placeholder, disabled is a fill.

Field, label, help, error

Shown to tutors and students.
Student ID must be at least 6 characters.
<div class="saga-field">
	<label class="saga-label is-required" for="f-title">Session Title</label>
	<input class="saga-input" id="f-title" placeholder="e.g. Out Of Window Test">
	<span class="saga-help">Shown to tutors and students.</span>
</div>
<div class="saga-field" data-invalid>
	<label class="saga-label is-required" for="f-id">Student ID</label>
	<input class="saga-input" id="f-id" value="sbx28" aria-invalid="true" aria-describedby="f-id-err">
	<span class="saga-error" id="f-id-err">Student ID must be at least 6 characters.</span>
</div>

Inline field

Applies to every pod in this period.
<div class="saga-field saga-field--inline">
	<label class="saga-label" for="f-ratio">Tutor:Student Ratio</label>
	<div class="saga-select saga-select--inline"><button type="button" class="saga-select__trigger" id="f-ratio" aria-haspopup="listbox" aria-expanded="false"><span>1:3</span></button></div>
	<span class="saga-help">Applies to every pod in this period.</span>
</div>

Inputs and states

<div class="saga-field"><label class="saga-label" for="i1">Default</label><input class="saga-input" id="i1" placeholder="Placeholder is italic"></div>
<div class="saga-field"><label class="saga-label" for="i2">Read-only</label><input class="saga-input" id="i2" value="No Period" readonly></div>
<div class="saga-field"><label class="saga-label" for="i3">Disabled</label><input class="saga-input" id="i3" value="10/12/2026" disabled></div>
<div class="saga-field"><label class="saga-label" for="i4">Invalid</label><input class="saga-input" id="i4" value="4:30 AM" aria-invalid="true"></div>
<div class="saga-field"><label class="saga-label" for="i5">Small</label><input class="saga-input saga-input--sm" id="i5" placeholder="Compact"></div>
<div class="saga-field"><label class="saga-label" for="i6">Date</label><div class="saga-datepicker"><button type="button" class="saga-datepicker__trigger" id="i6" aria-haspopup="dialog" aria-expanded="false"><span>10/12/2026</span><iconify-icon icon="material-symbols-light:calendar-today-outline-rounded"></iconify-icon></button></div></div>
<div class="saga-field"><label class="saga-label" for="t1">Notes</label><textarea class="saga-textarea" id="t1" placeholder="What happened in this session?"></textarea></div>

Select

Product UI uses the painted trigger (.saga-select > .saga-select__trigger) and the .saga-select__menu listbox, never a native <select> (DS-101, DS-117). Closed, placeholder, disabled, and the --inline --sm toolbar size:

<div class="saga-field">
	<label class="saga-label" id="s1-label">Survey</label>
	<div class="saga-select"><button type="button" class="saga-select__trigger" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="s1-label"><span>BOY - Test Survey (Oct 9 – Oct 13, 2026)</span></button></div>
</div>
<div class="saga-field">
	<label class="saga-label" id="s1b-label">Placeholder</label>
	<div class="saga-select"><button type="button" class="saga-select__trigger is-placeholder" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="s1b-label"><span>Choose a period</span></button></div>
</div>
<div class="saga-field">
	<label class="saga-label" id="s2-label">Disabled</label>
	<div class="saga-select"><button type="button" class="saga-select__trigger" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="s2-label" disabled><span>No Period</span></button></div>
</div>
<div class="saga-field" style="flex:0;min-width:0">
	<label class="saga-label" id="s2c-label">Small, inline</label>
	<div class="saga-select saga-select--inline saga-select--sm"><button type="button" class="saga-select__trigger" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="s2c-label"><span>Period 1</span></button></div>
</div>

Open listbox

The option is the <li role="option"> or a <button role="option"> inside it; data-active marks the keyboard row. Styled now, wired by JS later.

  • AI Test
  • Demo Program 08/17
  • Demo Test
  • Archived program
<div class="saga-field" style="max-width:20rem">
	<label class="saga-label" id="s3-label">Current Program</label>
	<div class="saga-select">
		<button type="button" class="saga-select__trigger" aria-haspopup="listbox" aria-expanded="true" aria-labelledby="s3-label"><span>Demo Program 08/17</span></button>
		<ul class="saga-select__menu" role="listbox" aria-labelledby="s3-label">
			<li class="saga-select__search"><div class="saga-search"><input class="saga-input saga-input--sm" placeholder="Search..." aria-label="Search programs"><span class="saga-search__icon"><iconify-icon icon="material-symbols-light:search-rounded"></iconify-icon></span></div></li>
			<li class="saga-select__option" role="option" aria-selected="false">AI Test</li>
			<li class="saga-select__option" role="option" aria-selected="true">Demo Program 08/17</li>
			<li class="saga-select__option" role="option" aria-selected="false" data-active>Demo Test</li>
			<li role="none"><button type="button" class="saga-select__option" role="option" aria-selected="false">GO Test (button option)</button></li>
			<li class="saga-select__option" role="option" aria-disabled="true">Archived program</li>
			<li class="saga-select__footer"><button class="saga-btn saga-btn--add saga-btn--sm"><span class="saga-btn__plus"><iconify-icon icon="material-symbols-light:add-rounded"></iconify-icon></span> Add New Program</button></li>
		</ul>
	</div>
</div>

Prototype-only native fallback

A native <select> inside .saga-select takes the same box and caret. Acceptable only in a prototype where the dropdown's behaviour is not the point; its open list is native and invisible in a tab share.

<div class="saga-field">
	<label class="saga-label" for="s4">Ratio <span class="ptag">prototype-only native fallback</span></label>
	<div class="saga-select"><select id="s4"><option>1:1</option><option selected>1:3</option><option>1:4</option></select></div>
</div>

Checkbox, radio, toggle

<label class="saga-check"><input type="checkbox" class="saga-checkbox" checked> Checked</label>
<label class="saga-check"><input type="checkbox" class="saga-checkbox"> Unchecked</label>
<label class="saga-check"><input type="checkbox" class="saga-checkbox" id="cb-ind"> Indeterminate</label>
<label class="saga-check"><input type="checkbox" class="saga-checkbox" disabled checked> Disabled</label>
<label class="saga-check"><input type="radio" name="r" class="saga-radio" checked> Same Every Week</label>
<label class="saga-check"><input type="radio" name="r" class="saga-radio"> Varies by Day Type</label>
<label class="saga-check"><input type="radio" name="r2" class="saga-radio" disabled> Disabled</label>
<label class="saga-check text-secondary"><input type="checkbox" class="saga-toggle" role="switch"> Show Entire District</label>
<label class="saga-check"><input type="checkbox" class="saga-toggle" role="switch" checked> Notifications on</label>
<label class="saga-check"><input type="checkbox" class="saga-toggle" role="switch" disabled> Disabled</label>

Date picker

Trigger shaped like an input with a trailing calendar glyph; the popover is 264px, 7 × 32px day cells, selected day filled blue with a light-blue ring, adjacent-month days muted, today bold (date_picker.png). The popover is shown statically here; in a page it is absolute under the trigger.

<div class="saga-datepicker">
	<button type="button" class="saga-datepicker__trigger" aria-haspopup="dialog" aria-expanded="true" aria-label="When: 10/12/2026"><span>10/12/2026</span><iconify-icon icon="material-symbols-light:calendar-today-outline-rounded"></iconify-icon></button>
	<div class="saga-datepicker__popover saga-datepicker__popover--static" role="dialog" aria-label="Choose a date" style="margin-top:var(--space-xs)">
		<div class="saga-datepicker__nav">
			<button type="button" class="saga-btn saga-btn--quiet saga-btn--icon saga-btn--sm" aria-label="Previous month"><iconify-icon icon="material-symbols-light:chevron-left-rounded"></iconify-icon></button>
			<span class="saga-datepicker__month">October 2026</span>
			<button type="button" class="saga-btn saga-btn--quiet saga-btn--icon saga-btn--sm" aria-label="Next month"><iconify-icon icon="material-symbols-light:chevron-right-rounded"></iconify-icon></button>
		</div>
		<div class="saga-datepicker__grid" role="grid">
			<span class="saga-datepicker__weekday">Su</span><span class="saga-datepicker__weekday">Mo</span><span class="saga-datepicker__weekday">Tu</span><span class="saga-datepicker__weekday">We</span><span class="saga-datepicker__weekday">Th</span><span class="saga-datepicker__weekday">Fr</span><span class="saga-datepicker__weekday">Sa</span>
			<button type="button" class="saga-datepicker__day saga-datepicker__day--muted">27</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">28</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">29</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">30</button> <button type="button" class="saga-datepicker__day">1</button> <button type="button" class="saga-datepicker__day">2</button> <button type="button" class="saga-datepicker__day">3</button>
			<button type="button" class="saga-datepicker__day">4</button> <button type="button" class="saga-datepicker__day">5</button> <button type="button" class="saga-datepicker__day">6</button> <button type="button" class="saga-datepicker__day">7</button> <button type="button" class="saga-datepicker__day">8</button> <button type="button" class="saga-datepicker__day">9</button> <button type="button" class="saga-datepicker__day">10</button>
			<button type="button" class="saga-datepicker__day">11</button> <button type="button" class="saga-datepicker__day" aria-selected="true">12</button> <button type="button" class="saga-datepicker__day">13</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--today">14</button> <button type="button" class="saga-datepicker__day">15</button> <button type="button" class="saga-datepicker__day">16</button> <button type="button" class="saga-datepicker__day">17</button>
			<button type="button" class="saga-datepicker__day">18</button> <button type="button" class="saga-datepicker__day">19</button> <button type="button" class="saga-datepicker__day">20</button> <button type="button" class="saga-datepicker__day">21</button> <button type="button" class="saga-datepicker__day">22</button> <button type="button" class="saga-datepicker__day">23</button> <button type="button" class="saga-datepicker__day">24</button>
			<button type="button" class="saga-datepicker__day">25</button> <button type="button" class="saga-datepicker__day">26</button> <button type="button" class="saga-datepicker__day">27</button> <button type="button" class="saga-datepicker__day">28</button> <button type="button" class="saga-datepicker__day">29</button> <button type="button" class="saga-datepicker__day">30</button> <button type="button" class="saga-datepicker__day">31</button>
			<button type="button" class="saga-datepicker__day saga-datepicker__day--muted">1</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">2</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">3</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">4</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">5</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">6</button> <button type="button" class="saga-datepicker__day saga-datepicker__day--muted">7</button>
		</div>
	</div>
</div>

Search

<div class="saga-search" style="flex:1">
	<input class="saga-input" type="search" placeholder="Search whole name, Student ID, school…" aria-label="Search students">
	<span class="saga-search__icon"><iconify-icon icon="material-symbols-light:search-rounded"></iconify-icon></span>
</div>