Skip to content
Aggarly OS
  • Getting Started
    • Introduction
  • Foundations
    • Colors
    • Spacing
    • Radius
    • Typography
    • Shadows
    • Z-Index
    • Gradients
    • Tokens
    • RTL & Direction
    • Theming
  • Layout
    • Containers
    • Grid System
    • Layout Utilities
  • Components
    • Alerts
    • Avatars
    • Buttons
    • Button Group
    • Badges
    • Inputs
    • Select
    • Checkbox
    • Counters-timers
    • Radio
    • Switch
    • Stepper
    • Select-pro
    • Cards
    • Modals
    • Dropdown
    • Popover
    • Tooltip
    • Accordion
    • Breadcrumb
    • Tabs
    • Navbar
    • List Group
    • Toasts
    • Skeleton
    • Pagination
    • Progress
    • Table
    • Icons
    • Form
    • Ribbons
    • Spinner
    • Offcanvas
    • Feedback
    • Grid
    • Data UI
  • Data UI
    • Overview
  • Platform
    • Reference DataCore
  • Widgets
    • KPI
    • Analytics
    • Behavior
  • Brand
    • Logo
    • Brand Usage
Components/Inputs

Inputs

Inputs are used to capture structured data from workspace admins, admins, supervisors, and workspace members. They are styled to be calm, readable, and appropriate for long work sessions with strong focus-visible affordances and theme-safe tokens.

Basic Input

Default input styling with label association, calm surface, and accessible focus ring.

Show code
Basic input (JSX)
import { Input } from "@/design-system/components/Input";

export function Example() {
  return (
    <Input
      id="student-name"
      label="Student name"
      placeholder="Enter full name"
      autoComplete="name"
    />
  );
}

Validation State

Error styling is token-driven and sets aria-invalid/aria-describedby via the Input component.

Goal name is required.
Show code
Validation (JSX)
import { Input } from "@/design-system/components/Input";

export function Example() {
  return (
    <Input
      id="goal-name"
      label="Goal name"
      placeholder="Enter goal name"
      error="Goal name is required."
    />
  );
}

Helper Text

Use helper text for format requirements, side effects, or system usage. Keep it short and scannable.

Used for imports, reports, and audit logs.
Show code
Helper text (JSX)
import { Input } from "@/design-system/components/Input";

export function Example() {
  return (
    <Input
      id="student-id"
      label="Student ID"
      placeholder="e.g. THR-10429"
      helper="Used for imports, reports, and audit logs."
    />
  );
}

Input Sizing

Use size variants to match surface density: tables/toolbars (sm), forms (md), primary workflows (lg).

Show code
Sizing (JSX)
import { Input } from "@/design-system/components/Input";

export function Example() {
  return (
    <div className="stack-sm">
      <Input className="input--sm" label="Small" placeholder="Small input" />
      <Input label="Default" placeholder="Default input" />
      <Input className="input--lg" label="Large" placeholder="Large input" />
    </div>
  );
}

File Input

File inputs are styled using the same token-driven surface and provide a premium file selector button.

PDF or image. Max size enforced by server validation.

Show code
File input (JSX)
export function Example() {
  return (
    <div className="stack-sm">
      <label className="input-label" htmlFor="upload">
        Upload attachment
      </label>

      <input
        id="upload"
        className="input input--file"
        type="file"
        accept=".pdf,.png,.jpg,.jpeg"
      />

      <p className="input-helper-text">
        PDF or image. Max size enforced by server validation.
      </p>
    </div>
  );
}

Input Group

Use input groups for prefixes/suffixes and structured identifiers. Uses logical borders for RTL safety.

https://.com

Use your organization slug (no spaces).

Show code
Input group (JSX)
export function Example() {
  return (
    <div className="stack-sm">
      <label className="input-label" htmlFor="website">
        Website
      </label>

      <div className="input-group" role="group" aria-label="Website">
        <span className="input-group__addon" aria-hidden="true">
          https://
        </span>

        <input
          id="website"
          className="input input-group__control"
          placeholder="aggarly"
          autoComplete="off"
        />

        <span className="input-group__addon" aria-hidden="true">
          .com
        </span>
      </div>

      <p className="input-helper-text">
        Use your organization slug (no spaces).
      </p>
    </div>
  );
}

Input Group With Buttons

Common enterprise pattern: search inputs with an icon prefix and an attached action button.

Show code
Group + button (JSX)
import { Button } from "@/design-system/components/Button";

function IconSearch() {
  return (
    <svg width="16" height="16" viewBox="0 0 20 20" fill="none" aria-hidden="true">
      <path d="M9 15a6 6 0 1 1 0-12 6 6 0 0 1 0 12Z" stroke="currentColor" strokeWidth="2" />
      <path d="M14 14l3 3" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
    </svg>
  );
}

export function Example() {
  return (
    <div className="stack-sm">
      <label className="input-label" htmlFor="search">
        Search students
      </label>

      <div className="input-group" role="group" aria-label="Search students">
        <span className="input-group__addon input-group__addon--icon" aria-hidden="true">
          <IconSearch />
        </span>

        <input
          id="search"
          className="input input-group__control"
          placeholder="Name, ID, workspace member email…"
          autoComplete="off"
        />

        <Button variant="ghost" className="input-group__btn">
          Search
        </Button>
      </div>
    </div>
  );
}

Input Group Sizing

Group sizing keeps addons and attached buttons aligned. Use sm for toolbars and lg for primary workflows.

@
+1
Show code
Group sizing (JSX)
import { Button } from "@/design-system/components/Button";

export function Example() {
  return (
    <div className="stack-md">
      <div className="stack-sm">
        <label className="input-label" htmlFor="group-sm">Small group</label>
        <div className="input-group input-group--sm" role="group" aria-label="Small group">
          <span className="input-group__addon" aria-hidden="true">@</span>
          <input id="group-sm" className="input input-group__control" placeholder="username" />
          <Button size="sm" variant="ghost" className="input-group__btn">Invite</Button>
        </div>
      </div>

      <div className="stack-sm">
        <label className="input-label" htmlFor="group-lg">Large group</label>
        <div className="input-group input-group--lg" role="group" aria-label="Large group">
          <span className="input-group__addon" aria-hidden="true">+1</span>
          <input id="group-lg" className="input input-group__control" placeholder="(555) 000-0000" />
          <Button size="lg" variant="ghost" className="input-group__btn">Verify</Button>
        </div>
      </div>
    </div>
  );
}

Buttons With Dropdowns

Visual pattern for filter chips and attached dropdown actions. Connect your menu logic in product code.

This section focuses on styling + layout; dropdown behavior is implemented in your UI layer (e.g., Popover/Menu patterns).

Show code
Dropdown button pattern (JSX)
import { Button } from "@/design-system/components/Button";

function IconChevronDown() {
  return (
    <svg width="16" height="16" viewBox="0 0 20 20" fill="none" aria-hidden="true">
      <path d="M5 7.5L10 12.5L15 7.5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

export function Example() {
  return (
    <div className="stack-sm">
      <label className="input-label" htmlFor="query">
        Filter + search
      </label>

      <div className="input-group" role="group" aria-label="Filter and search">
        <Button
          variant="ghost"
          className="input-group__btn"
          trailingIcon={<IconChevronDown />}
          aria-label="Select filter"
        >
          Status
        </Button>

        <input
          id="query"
          className="input input-group__control"
          placeholder="Search…"
          autoComplete="off"
        />

        <Button variant="ghost" className="input-group__btn">
          Apply
        </Button>
      </div>

      <p className="input-helper-text">
        This shows the visual pattern. Hook up your dropdown/menu logic in product code.
      </p>
    </div>
  );
}

Input Masks Patterns

Use inputMode, autoComplete, placeholder, maxLength, and pattern for predictable enterprise data capture. Apply formatting in your UI logic when needed.

Use inputMode + maxLength; format onChange if needed.

ISO is recommended for exports and audit logs.

Show code
Mask patterns (JSX)
export function Example() {
  return (
    <div className="inputs-grid">
      <div className="stack-sm">
        <label className="input-label" htmlFor="phone">Phone (mask pattern)</label>
        <input
          id="phone"
          className="input"
          inputMode="tel"
          autoComplete="tel-national"
          placeholder="(555) 000-0000"
          maxLength={14}
        />
        <p className="input-helper-text">
          Use inputMode + maxLength; apply formatting in your onChange handler if needed.
        </p>
      </div>

      <div className="stack-sm">
        <label className="input-label" htmlFor="cc">Card number (mask pattern)</label>
        <input
          id="cc"
          className="input"
          inputMode="numeric"
          autoComplete="cc-number"
          placeholder="1234 5678 9012 3456"
          maxLength={19}
        />
      </div>

      <div className="stack-sm">
        <label className="input-label" htmlFor="dob">Date (text format)</label>
        <input
          id="dob"
          className="input"
          inputMode="numeric"
          placeholder="YYYY-MM-DD"
          autoComplete="bday"
          pattern="\d{4}-\d{2}-\d{2}"
        />
        <p className="input-helper-text">ISO format recommended for exports and audit logs.</p>
      </div>
    </div>
  );
}

Date Inputs

Native date controls provide locale-aware pickers where available. Use text ISO formats when exporting or when UI requires strict formatting.

Show code
Date inputs (JSX)
export function Example() {
  return (
    <div className="inputs-grid">
      <div className="stack-sm">
        <label className="input-label" htmlFor="date">Date</label>
        <input id="date" className="input" type="date" />
      </div>

      <div className="stack-sm">
        <label className="input-label" htmlFor="datetime">Date & time</label>
        <input id="datetime" className="input" type="datetime-local" />
      </div>

      <div className="stack-sm">
        <label className="input-label" htmlFor="month">Month</label>
        <input id="month" className="input" type="month" />
      </div>
    </div>
  );
}