Inputs

The app has two input treatments, and the thing that distinguishes them is whether the field is required. Required fields get a gray-300 border and a font-medium label; optional ones get gray-200 and a lighter label. It is subtle and it is consistent across UserProfileForm and NdoCreateModal.

Required field

From UserProfileForm.svelte. The asterisk is a red span, and the error is xs red text below.

Nickname is required.

<label class="mb-1 block text-sm font-medium text-gray-700">
  Nickname <span class="text-red-500">*</span>
</label>
<input class="w-full rounded border border-gray-300 px-3 py-2 text-sm
  focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" />
<p class="mt-1 text-xs text-red-600">{error}</p>

Optional field

Lighter border, lighter label. The section is introduced by an uppercase grey rule rather than a heading.

Optional fields

<p class="text-xs text-gray-400 uppercase tracking-wide font-medium">Optional fields</p>
<label class="mb-1 block text-sm text-gray-600">Real name</label>
<input class="w-full rounded border border-gray-200 px-3 py-2 text-sm …" />

Select with a hint

From NdoCreateModal.svelte. Every select is followed by a one-line explanation of the chosen value, which changes as you change the selection. It is the only place in the app that teaches while you fill a form.

Shared, self-governed resource open to a defined community.

<select class="w-full rounded border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none">…</select>
<p class="mt-1 text-xs text-gray-500">{tooltips[value]}</p>

Checkbox and radio

Bare 4×4 inputs with a gap-3 label. GroupProfileModal uses checkboxes for disclosure; LifecycleTransitionModal uses radios for the target stage.

<label class="flex items-center gap-3 cursor-pointer">
  <input type="checkbox" class="h-4 w-4 rounded" />
  <span class="text-sm text-gray-700">Appear anonymously (pseudonym only)</span>
</label>

Sidebar input

Extra small, no focus ring, only a border change. Different from every other input in the app.

New group

class="mb-1.5 w-full rounded border border-gray-300 px-2 py-1 text-xs focus:border-blue-500 focus:outline-none"