# Time

Use `ui-time` when users need one exact time within an already known day. It works well for standups, support handoffs, call scheduling, opening hours, and other workflows where time matters but a full date-time value would be too heavy.

## Import
```ts
import { TimeComponent } from 'ui';
```

## Basic time selection
```ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ButtonComponent, TimeComponent } from 'ui';

@Component({
  selector: 'app-time-basic-demo',
  standalone: true,
  imports: [FormsModule, ButtonComponent, TimeComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem;max-width:22rem">
      <ui-time
        label="Start time"
        placeholder="HH:mm"
        [(ngModel)]="value"
        [ngModelOptions]="{ standalone: true }"
      />

      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:center;padding:0.75rem 0.875rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:0.875rem;background:var(--color-neutral-background-rest)"
      >
        <ui-button type="button" appearance="subtle" (click)="value = ''">Clear</ui-button>
        <span style="font-size:0.75rem;color:var(--color-neutral-foreground2-rest)">
          {{ value || 'No time selected.' }}
        </span>
      </div>
    </div>
  `,
})
export class TimeBasicDemoComponent {
  protected value = '09:30';
}
```

## Time step and 12h or 24h clock
```ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TimeComponent } from 'ui';

@Component({
  selector: 'app-time-step-format-demo',
  standalone: true,
  imports: [FormsModule, TimeComponent],
  template: `
    <div style="display:flex;flex-direction:column;gap:1rem">
      <div
        style="display:grid;grid-template-columns:repeat(auto-fit,minmax(17rem,1fr));gap:1rem;align-items:start"
      >
        <ui-time
          label="30 minute steps"
          placeholder="HH:mm"
          helpText="24 hour picker with half-hour increments."
          [step]="1800"
          [use24HourFormat]="true"
          [(ngModel)]="halfHourValue"
          [ngModelOptions]="{ standalone: true }"
        />

        <ui-time
          label="15 minute steps"
          placeholder="HH:mm"
          helpText="24 hour picker with denser quarter-hour increments."
          [step]="900"
          [use24HourFormat]="true"
          [(ngModel)]="quarterHourValue"
          [ngModelOptions]="{ standalone: true }"
        />

        <ui-time
          label="12 hour picker with AM/PM"
          placeholder="HH:mm"
          helpText="Open the picker to see the 12 hour time list with AM/PM."
          [step]="1800"
          [use24HourFormat]="false"
          [(ngModel)]="twelveHourValue"
          [ngModelOptions]="{ standalone: true }"
        />
      </div>

      <div
        style="display:flex;flex-wrap:wrap;gap:1rem;align-items:center;padding:0.75rem 0.875rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:0.875rem;background:var(--color-neutral-background-rest)"
      >
        <span style="font-size:0.75rem;color:var(--color-neutral-foreground2-rest)">
          24h example: <strong style="color:var(--color-neutral-foreground1-rest)">16:30</strong>
        </span>
        <span style="font-size:0.75rem;color:var(--color-neutral-foreground2-rest)">
          12h picker shows the same slot as
          <strong style="color:var(--color-neutral-foreground1-rest)">4:30 PM</strong>
        </span>
      </div>
    </div>
  `,
})
export class TimeStepFormatDemoComponent {
  protected halfHourValue = '09:30';
  protected quarterHourValue = '13:15';
  protected twelveHourValue = '16:30';
}
```

## Size and input variant
```ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TimeComponent } from 'ui';

@Component({
  selector: 'app-time-size-variant-demo',
  standalone: true,
  imports: [FormsModule, TimeComponent],
  template: `
    <div
      style="display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));gap:1rem;align-items:start"
    >
      <ui-time
        label="Small filled"
        placeholder="HH:mm"
        size="small"
        inputVariant="filled"
        [(ngModel)]="smallValue"
        [ngModelOptions]="{ standalone: true }"
      />

      <ui-time
        label="Medium filled gray"
        placeholder="HH:mm"
        size="medium"
        inputVariant="filled-gray"
        [(ngModel)]="mediumValue"
        [ngModelOptions]="{ standalone: true }"
      />

      <ui-time
        label="Large underlined"
        placeholder="HH:mm"
        size="large"
        inputVariant="underlined"
        [(ngModel)]="largeValue"
        [ngModelOptions]="{ standalone: true }"
      />
    </div>
  `,
})
export class TimeSizeVariantDemoComponent {
  protected smallValue = '08:30';
  protected mediumValue = '11:00';
  protected largeValue = '15:45';
}
```

## Readonly, disabled, and required states
```ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TimeComponent } from 'ui';

@Component({
  selector: 'app-time-states-demo',
  standalone: true,
  imports: [FormsModule, TimeComponent],
  template: `
    <div
      style="display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));gap:1rem;align-items:start"
    >
      <ui-time
        label="Readonly"
        placeholder="HH:mm"
        [readonly]="true"
        [(ngModel)]="readonlyValue"
        [ngModelOptions]="{ standalone: true }"
      />

      <ui-time
        label="Disabled"
        placeholder="HH:mm"
        [disabled]="true"
        [(ngModel)]="disabledValue"
        [ngModelOptions]="{ standalone: true }"
      />

      <ui-time
        label="Required"
        placeholder="HH:mm"
        helpText="Choose the support handoff time."
        [required]="true"
        [(ngModel)]="requiredValue"
        [ngModelOptions]="{ standalone: true }"
      />
    </div>
  `,
})
export class TimeStatesDemoComponent {
  protected readonlyValue = '10:15';
  protected disabledValue = '12:00';
  protected requiredValue = '';
}
```

## Reactive form integration
```ts
import { Component, computed } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { ButtonComponent, MessageBarComponent, TimeComponent } from 'ui';

@Component({
  selector: 'app-time-reactive-form-demo',
  standalone: true,
  imports: [ReactiveFormsModule, ButtonComponent, MessageBarComponent, TimeComponent],
  template: `
    <div
      style="display:flex;flex-direction:column;gap:1rem;max-width:24rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
    >
      <div style="display:flex;flex-direction:column;gap:0.25rem">
        <div style="font-size:0.9375rem;font-weight:600">Standup time</div>
        <div style="font-size:0.8125rem;color:var(--color-neutral-foreground2-rest)">
          Time usually matters inside a real form flow with validation and submit state.
        </div>
      </div>

      <ui-time
        label="Daily standup"
        placeholder="HH:mm"
        helpText="Choose the recurring standup time."
        [required]="true"
        [formControl]="timeControl"
      />

      @if (timeControl.invalid && timeControl.touched) {
        <ui-message-bar
          title="Time required"
          message="Choose the standup time before continuing."
          variant="warning"
          appearance="subtle"
          [dismissible]="false"
        />
      }

      <div
        style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:center;padding:0.75rem 0.875rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:0.875rem;background:var(--color-neutral-background-rest)"
      >
        <ui-button type="button" variant="primary" [disabled]="timeControl.invalid">
          Save time
        </ui-button>
        <ui-button type="button" appearance="subtle" (click)="reset()">Reset</ui-button>
        <span style="font-size:0.75rem;color:var(--color-neutral-foreground2-rest)">
          {{ summary() }}
        </span>
      </div>
    </div>
  `,
})
export class TimeReactiveFormDemoComponent {
  protected readonly timeControl = new FormControl<string | null>('09:45', {
    nonNullable: false,
    validators: [Validators.required],
  });

  protected readonly summary = computed(() => this.timeControl.value || 'No time selected.');

  protected reset(): void {
    this.timeControl.reset('09:45');
  }
}
```

## Scheduling panel composition
```ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ButtonComponent, MessageBarComponent, TagComponent, TimeComponent } from 'ui';

@Component({
  selector: 'app-time-scheduling-panel-demo',
  standalone: true,
  imports: [FormsModule, ButtonComponent, MessageBarComponent, TagComponent, TimeComponent],
  template: `
    <div
      style="display:grid;grid-template-columns:repeat(auto-fit,minmax(18rem,1fr));gap:1rem;align-items:start;max-width:48rem"
    >
      <div
        style="display:flex;flex-direction:column;gap:1rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <div style="display:flex;flex-direction:column;gap:0.25rem">
          <div style="font-size:0.9375rem;font-weight:600">Call scheduling</div>
          <div style="font-size:0.8125rem;color:var(--color-neutral-foreground2-rest)">
            Time is strongest when users need one precise slot within an already known day.
          </div>
        </div>

        <ui-time
          label="Call time"
          placeholder="HH:mm"
          [step]="1800"
          [(ngModel)]="value"
          [ngModelOptions]="{ standalone: true }"
        />

        <ui-message-bar
          title="Availability note"
          message="Confirm the chosen slot with the customer before sending the final reminder."
          variant="info"
          appearance="subtle"
          [dismissible]="false"
        />
      </div>

      <div
        style="display:flex;flex-direction:column;gap:0.875rem;padding:1rem;border:1px solid var(--color-neutral-stroke-rest);border-radius:1rem;background:var(--color-neutral-background-rest)"
      >
        <div style="display:flex;flex-wrap:wrap;gap:0.5rem">
          <ui-tag text="Support" appearance="filled" variant="secondary" />
          <ui-tag text="30 minute slot" appearance="subtle" variant="info" />
          <ui-tag text="Ready to confirm" appearance="subtle" variant="success" />
        </div>

        <div style="display:flex;flex-direction:column;gap:0.375rem">
          <div style="font-size:0.8125rem;color:var(--color-neutral-foreground2-rest)">
            Selected time
          </div>
          <div style="font-size:0.9375rem;font-weight:600">{{ value || 'Not selected' }}</div>
        </div>

        <div
          style="display:flex;flex-wrap:wrap;gap:0.75rem;align-items:center;padding:0.75rem 0.875rem;border:1px dashed var(--color-neutral-stroke-rest);border-radius:0.875rem;background:var(--color-neutral-background-rest)"
        >
          <ui-button type="button" variant="primary">Confirm slot</ui-button>
          <ui-button type="button" appearance="subtle" (click)="value = ''">Reset</ui-button>
        </div>
      </div>
    </div>
  `,
})
export class TimeSchedulingPanelDemoComponent {
  protected value = '14:30';
}
```

## Accessibility

### Input and popup behavior
`ui-time` behaves like a text field on desktop and can fall back to a native `type="time"` input on mobile when `useNativeOnMobile` is enabled.

| Mode | Behavior |
| --- | --- |
| desktop text input | exposes `aria-haspopup="dialog"` and `aria-expanded` |
| mobile native time input | relies on native platform time input semantics |
| disabled or readonly | prevents opening or changing the value |

### Keyboard
Keyboard handling follows the shared field and popup model.

| Key | Action |
| --- | --- |
| `Tab` / `Shift+Tab` | moves through the field and time picker controls |
| `Enter` / click on trigger actions | opens the time picker panel on desktop |
| picker activation | selects a time option in the overlay |

### Labels and guidance
Use a task-specific label such as standup time, call time, or handoff time so the meaning of the chosen slot is obvious. If the slot cadence matters, add helper text that explains the intended interval, such as 15 or 30 minute steps.
