# Login 04 (`login-04`) - SignalOS page block

> Card-style credential form with Microsoft SSO, structured error/warning states, and a brand slot.

- **Version:** 0.3.3
- **Kind:** block (group: login) · **Category:** pages
- **Install:** `npx shadcn@latest add @signalos/login-04`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/card, @signalos/text-field
- **npm dependencies:** lucide-react@^1.7.0
- **Files installed:** `src/components/blocks/login-04/Login04.tsx`, `src/components/blocks/login-04/Login04.types.ts`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
// after: npx shadcn@latest add @signalos/login-04
// mount the pulled page in a route, e.g. src/app/login/page.tsx
import { Login04 } from "@/components/blocks/login-04/Login04"

export default function Page() {
  return <Login04 />
}
```

## Props

### `LoginCredentials`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `email` | `string` | yes | - |  |
| `password` | `string` | yes | - |  |

### `ErrorSeverity`

```ts
export type ErrorSeverity = "error" | "warning"
```

### `LoginError`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `message` | `string` | yes | - | Human-readable message shown inside the alert. |
| `severity` | `ErrorSeverity` | yes | - | Controls the alert's color palette. |
| `icon` | `LucideIcon` | yes | - | Icon component rendered beside the message. |

### `Login04Props`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `brand` | `ReactNode` | no | - | Brand image / logo rendered above the login card. |
| `onSubmit` | `(credentials: LoginCredentials) => void` | yes | - | Called with the entered credentials when the form is submitted. |
| `isLoading` | `boolean \| undefined` | no | `false` | When true, disables all controls and shows a spinner on the submit button. |
| `isAzureLoading` | `boolean \| undefined` | no | `false` | When true, disables all controls and shows a spinner on the Azure button. |
| `loginError` | `LoginError \| null \| undefined` | no | - | Structured error or warning displayed above the form fields. Pass `null` to clear. |
| `fieldErrors` | `Partial<Record<"email" \| "password", string>> \| null \| undefined` | no | - | Per-field validation errors keyed by field name. Pass `null` or omit to clear. |
| `onFieldChange` | `((field: "email" \| "password") => void) \| undefined` | no | - | Called when a field's value changes, with the field name. Use to clear per-field errors. |
| `onAzureSignIn` | `(() => void) \| undefined` | no | - | Called when the user clicks the Microsoft sign-in button. Omit to hide the button. |
| `className` | `string \| undefined` | no | - | Extra classes merged onto the root element via `cn()`. |
| `submitLabel` | `string \| undefined` | no | `"LOGIN"` | Label for the primary submit button. |
| `azureLabel` | `string \| undefined` | no | `"Sign in with Microsoft"` | Label for the Microsoft sign-in button. |
| `data-testid` | `string \| undefined` | no | - | Test identifier rendered as `data-testid` on the root element. |

## Changelog

# login-04


## 0.3.3

- Added `fieldErrors` and `onFieldChange` props to support per-field validation messages and error clearing from the parent.
- Display validation errors for the email and password fields using the `TextField` component.

## 0.3.0

- Add `"data-testid"` prop to `Login04Props` (forwarded to root element); the root testid is now overridable instead of hardcoded.
- Fix `isAzureLoading` JSDoc (previously described the credential loading state by mistake).
- Add JSDoc to all previously undocumented props.

## 0.2.0

- Full rewrite: all state, callbacks, and error handling moved to the parent via props (`onSubmit`, `onAzureSignIn`, `isLoading`, `isAzureLoading`, `loginError`).
- Replaced native `<input>`/`<label>` with the `TextField` widget.
- Added `brand` slot and conditional Azure button (rendered only when `onAzureSignIn` is provided).
- Removed all forbidden imports (`next/*`, `next-auth`, internal schemas/services).
- Responsive layout across mobile, tablet, and desktop.

## 0.1.0

- Initial release: credential form with Microsoft SSO (tightly coupled to app internals).
