# Login 02 - Split screen (`login-02`) - SignalOS page block

> Two-column sign-in: form on the left, navy brand panel with headline, subline, and testimonial slot on the right. Panel collapses below lg.

- **Version:** 0.1.4
- **Kind:** block (group: login) · **Category:** pages
- **Install:** `npx shadcn@latest add @signalos/login-02`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/label, @signalos/text-field
- **npm dependencies:** lucide-react@^1.7.0
- **Files installed:** `src/components/blocks/login-02/Login02.tsx`, `src/components/blocks/login-02/Login02.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-02
// mount the pulled page in a route, e.g. src/app/login/page.tsx
import { Login02 } from "@/components/blocks/login-02/Login02"

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

## Props

### `LoginCredentials`

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

### `Login02Testimonial`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `quote` | `string` | yes | - |  |
| `author` | `string` | yes | - |  |
| `role` | `string \| undefined` | no | - |  |

### `Login02Props`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `brand` | `ReactNode` | no | - | Brand block at the top of the form column. |
| `title` | `string \| undefined` | no | `"Welcome back"` |  |
| `subtitle` | `string \| undefined` | no | `"Sign in to continue to your workspace."` |  |
| `onSubmit` | `(credentials: LoginCredentials) => void` | yes | - |  |
| `isLoading` | `boolean \| undefined` | no | - |  |
| `error` | `string \| null \| undefined` | no | - |  |
| `onForgotPassword` | `(() => void) \| undefined` | no | - |  |
| `footer` | `ReactNode` | no | - | Footer slot under the form. |
| `panelHeadline` | `string \| undefined` | no | `"Decisions, with signal."` | Headline on the brand panel. |
| `panelSubline` | `string \| undefined` | no | - | Supporting line under the panel headline. |
| `testimonial` | `Login02Testimonial \| undefined` | no | - | Optional testimonial card on the brand panel. |
| `panelExtra` | `ReactNode` | no | - | Extra content on the brand panel (stats, logos). |
| `className` | `string \| undefined` | no | - |  |

## Changelog

# login-02

## 0.1.4

- Compose the `TextField` widget for the email and password inputs instead of
  hand-rolled `Label` + `Input` markup, matching the shared error/disabled/focus
  styling used across the registry. No prop, testid, or visual change.

## 0.1.3

- Use semantic status tokens (text-text-error, bg-bg-warning, border-border-*, bg-status-*) instead of raw palette scales so client theme overrides restyle status colors.


## 0.1.2

- Content sync fix to bring source in line with published registry payload.


## 0.1.1

- Standardize inline comment formatting (em dash → hyphen); no runtime or API change.

## 0.1.0

- Initial release: split-screen sign-in with a brand-navy right panel
  (headline/subline/testimonial/extra slots), desktop-first (panel hides below `lg`).
