Skip to content
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4a39c62
IS-11008 Restructure HAAPI React SDK README; fix HaapiStepper JSDoc s…
aleixsuau Jun 8, 2026
bd9de0e
IS-11008: improve docs
aleixsuau Jun 9, 2026
98cbedd
IS-11008 Refine HAAPI React SDK docs and fix JSDoc editor previews
aleixsuau Jun 9, 2026
470d5d4
IS-11008: fix type references
aleixsuau Jun 10, 2026
9316540
IS-11008: improve form tests references
aleixsuau Jun 10, 2026
d431948
IS-11008 Sharpen customization docs (interceptors vs UI composition)
aleixsuau Jun 10, 2026
feb9aba
IS-11008: form field docs and improvements
aleixsuau Jun 11, 2026
296eef3
IS-11008 Document workspace-root install in haapi-react-app README
aleixsuau Jun 11, 2026
ddb3c35
IS-11008 Rewrite SDK README and TSDoc for the docs site
aleixsuau Jun 24, 2026
bfe3556
IS-11008 Add HAAPI React SDK docs site (Docusaurus + generation)
aleixsuau Jun 24, 2026
d91ec77
IS-11008 Add docs examples and single-source step catalog
aleixsuau Jun 24, 2026
996cd53
IS-11008 Register docs workspace and StackBlitz preview
aleixsuau Jun 24, 2026
01d674f
IS-11008 Format docs sources with Prettier; add docs-workspace pretti…
aleixsuau Jun 24, 2026
5c31f96
IS-11008 Scope SDK CI steps to the SDK workspace; stop linting docs
aleixsuau Jun 24, 2026
b797445
IS-11008 Build ui-kit icons + css libs before generating docs
aleixsuau Jun 24, 2026
7a6a6e8
IS-11008 Remove StackBlitz links and config
aleixsuau Jun 24, 2026
3c3126c
Merge remote-tracking branch 'origin/dev' into feature/IS-11008/haapi…
aleixsuau Jun 24, 2026
d02d5c2
IS-11008 Land docs on the overview and link to the online docs from t…
aleixsuau Jun 25, 2026
124ed7f
IS-11008: remove haapi-react-app from the uikit npm start command
aleixsuau Jun 29, 2026
b829e83
IS-11008: curity logo, favicon and styles in docs
aleixsuau Jun 29, 2026
a84b0e2
IS-11008: add previewer to the overview page
aleixsuau Jun 29, 2026
ee05874
IS-11008: add sdk docs link in the uikit overview page
aleixsuau Jun 29, 2026
67b458a
IS-11008: prevent haapi-react-app from opening on uikit main page start
aleixsuau Jun 30, 2026
e2d7628
IS-11008: remove curity-cli command from docs
aleixsuau Jun 30, 2026
4c6bcd3
IS-11008: improve docs npm command
aleixsuau Jun 30, 2026
3442124
IS-11008: simplify folder structure and gitignore
aleixsuau Jun 30, 2026
eac93d6
IS-11008 Move SDK README to package root; brand docs links; fix entri…
aleixsuau Jun 30, 2026
1d8de84
IS-11008 Centralize docs generator paths in scripts/paths.mjs.
aleixsuau Jun 30, 2026
1db1a99
IS-11008: add typecheck, prettier and build to the ci workflow
aleixsuau Jun 30, 2026
dbc35a0
IS-11008: add previewer note to haapi-react-app readme
aleixsuau Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/lwa-github-ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ jobs:
run: npm ci

- name: SDK — Check Formatting
run: npm run prettier-check -w src/haapi-react-sdk
run: npm run prettier-check -w @curity/haapi-react-sdk

- name: SDK — Lint
run: npm run lint -w src/haapi-react-sdk
run: npm run lint -w @curity/haapi-react-sdk

- name: SDK — Typecheck
run: npm run typecheck -w src/haapi-react-sdk
run: npm run typecheck -w @curity/haapi-react-sdk

- name: SDK — Run Tests
run: npm run test -w src/haapi-react-sdk -- run
run: npm run test -w @curity/haapi-react-sdk -- run

- name: App — Check Formatting
run: npm run prettier-check -w src/haapi-react-app
Expand Down
4 changes: 4 additions & 0 deletions .stackblitzrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"installDependencies": false,
"startCommand": "npm install --engine-strict=false --no-audit --no-fund && cd src/haapi-react-sdk/docs && npm run docs -- --host 0.0.0.0 --no-open"
}
35,258 changes: 24,023 additions & 11,235 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"src/identity-server",
"src/self-service-portal/app",
"src/haapi-react-sdk",
"src/haapi-react-sdk/docs",
"src/haapi-react-app"
],
"scripts": {
Expand Down
34 changes: 30 additions & 4 deletions src/haapi-react-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

## Project & tools

Install packages with `npm install`.
Install all workspaces from the repo root:

```shell
curity-cli t && npm i --prefix "$(git rev-parse --show-toplevel)"
Comment thread
aleixsuau marked this conversation as resolved.
Outdated
```

- React
- Built with Vite
Expand All @@ -13,14 +17,27 @@ Install packages with `npm install`.
- IDEs usually have Prettier integrated with the "format code" commands.
- IntelliJ has a [plugin](https://plugins.jetbrains.com/plugin/10456-prettier). Additional settings in `Languages & Frameworks | JavaScript | Prettier`.

## SDK documentation

This app is built on the [HAAPI React SDK](../haapi-react-sdk/haapi-stepper/README.md). Browse its
interactive documentation — run it locally from the repo root:

```shell
cd src/haapi-react-sdk/docs && npm run docs
Comment thread
aleixsuau marked this conversation as resolved.
Outdated
```

or open it in the browser with no setup, and the code editor hidden, on
[StackBlitz](https://stackblitz.com/~/github.com/curityio/ui-kit/tree/feature/IS-11008/haapi-react-sdk-docs?view=preview).

Comment thread
aleixsuau marked this conversation as resolved.
Outdated
## Development setup

The Vite development server is used both to serve the application and as a proxy for specific Identity Server endpoints.
This allows running the application as a type-0 client (which is the realistic scenario) and still get all the Vite/React development facilities.

Follow these steps to get started:

1. Start Identity Server locally.
- The server should have a minimum setup to allow running OAuth authorization flows with user interaction.
- The server should have a minimum setup to allow running OAuth authorization flows with user interaction.
2. In this directory, run `IDSVR_HOME=<idsvr_home> ./configure-idsvr-dev.sh`.
- `IDSVR_HOME` should contain the path to the home directory of the running Identity Server instance.
3. Run `npm run dev`.
Expand All @@ -37,9 +54,11 @@ To test the updates, enable the API-driven UI in the Identity Server instance an
## Error Handling

### ErrorBoundary

**Purpose**: Global error boundary that catches unhandled React errors and displays fallback UI.

**Example Usage**:

```tsx
<ErrorBoundary>
<HaapiStepper>
Expand All @@ -49,47 +68,53 @@ To test the updates, enable the API-driven UI in the Identity Server instance an
```

**Features:**

- Catches JavaScript errors anywhere in the component tree
- Displays user-friendly error messages with retry functionality
- Prevents entire application crashes
- Includes error reporting for debugging


## Folder Structure

Inspired by the Domain-Driven Design approach, this project's folder structure is organized by 2 dimensions/levels:

### **Dimension 1: Subdomain/Feature**

- **First level folders** represent different **subdomains or features** the app implements
- Each subdomain encapsulates related functionality

#### **Shared Code Organization**

- **`shared/` folder**: Contains libraries used by multiple subdomains/features

### **Dimension 2: Technical Layer Types**

Within each subdomain, code is organized by these technical layer types:

#### **`feature/`**

- **Purpose**: Smart UI components with data access
- **Contains**: Business logic components that connect to data sources. "Smart" components that manage state and side effects
- **Examples**: Components that handle authentication flows, form submissions, API calls

#### **`ui/`**

- **Purpose**: Presentational components only
- **Contains**: "Dumb" components focused on rendering. No business logic, just UI rendering based on props
- **Examples**: Buttons, input fields, layout components, styled elements

#### **`data-access/`**

- **Purpose**: Backend interaction and state management
- **Contains**: API clients, state management code, data transformation. Handles all external data operations
- **Examples**: HTTP service functions, Redux stores

#### **`util/`**

- **Purpose**: Low-level shared utilities
- **Contains**: Helper functions, constants, type definitions. Reusable across multiple components/features
- **Examples**: Date formatters, validation functions, common types


### **Example Schema**

```
Expand All @@ -106,6 +131,7 @@ src/
```

This structure promotes:

- **Discoverability**: Clear separation makes code easy to find
- **Maintainability**: Similar responsibilities are grouped together
- **Reusability**: Shared components can be easily identified and reused
Expand Down
3 changes: 3 additions & 0 deletions src/haapi-react-sdk/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.prettierrc
tsconfig.*
README.md

# The docs are their own workspace with its own prettier-check (run via `-w src/haapi-react-sdk`).
docs
19 changes: 19 additions & 0 deletions src/haapi-react-sdk/docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Dependencies
/node_modules

# Docusaurus build output
/build
/.docusaurus

# Generated by scripts/build-sandpack-sdk.mjs (npm run docs:gen)
/src/generated/
/docs/_overview.mdx

# Generated by scripts/split-docs.mjs (npm run docs:split): one short page per `##` section
/docs/overview/

# Generated by scripts/emit-api-reference.mjs (npm run docs:apiref) from api-reference.entries.mjs
/docs/api-reference/

# Generated by scripts/emit-examples.mjs (npm run docs:examples) from examples.entries.mjs
/docs/examples/
Comment thread
aleixsuau marked this conversation as resolved.
Outdated
16 changes: 16 additions & 0 deletions src/haapi-react-sdk/docs/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Tooling / config
.prettierrc
tsconfig.*
README.md

# Dependencies & build output
node_modules
build
.docusaurus

# Generated by the docs:gen / docs:split / docs:apiref / docs:examples scripts (see .gitignore)
src/generated
docs/_overview.mdx
docs/overview
docs/api-reference
docs/examples
Comment thread
aleixsuau marked this conversation as resolved.
59 changes: 59 additions & 0 deletions src/haapi-react-sdk/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# HAAPI React SDK docs

Docusaurus site for the HAAPI React SDK. Most content is **generated** from the SDK source, so you rarely
edit pages by hand — you edit the SDK (README + TSDoc) and the example files, and the build assembles the site.

## Run it

```bash
npm run docs # dev server on http://localhost:3220
npm run docs:build # production build (fails on broken links)
```

Both run the generators first (`predocs`): `docs:gen → docs:split → docs:apiref → docs:examples`.

## Where content comes from

| Sidebar section | Source | How |
|---|---|---|
| **Overview** | SDK `README.md` | `docs:gen` → `_overview.mdx`, `docs:split` → one page per `##` |
| **API Reference** | component **TSDoc** | `docs:apiref` extracts the TSDoc (`scripts/extract-tsdoc.mjs`) and emits a Markdown page per entry in `api-reference.entries.mjs` |
| **Examples** | `examples/*.tsx` | `docs:examples` emits a playground page per entry in `examples.entries.mjs` |

Generated folders (`docs/_overview.mdx`, `docs/overview/`, `docs/api-reference/`, `docs/examples/`) are
**gitignored** — don't edit them; change the source instead.
Comment thread
aleixsuau marked this conversation as resolved.
Outdated

## Examples = live playgrounds

An example is a self-contained `examples/<Name>.tsx` (default `App`, wrapped in `<ExamplePreviewer>`).
`docs:gen` bundles every example into `examples.json` (keyed by basename). You reference it by **name**
(its filename, no `.tsx`) in one of two ways — both get rewritten, at generation time, into the same
`<DocExample id="<Name>" />` runtime tag, which looks the source up in `examples.json` by that `id`:

- **A markdown link to the file** — `[label](…/examples/<Name>.tsx)`, in the SDK `README.md` (→ Overview).
It stays a clickable link on GitHub; the build derives `<Name>` from the link and converts it to a
playground (`build-sandpack-sdk.mjs`).
- **A `{@see_example docs/examples/<Name>.tsx Label}` marker** — inside a component's TSDoc, so the
playground renders inline on its API Reference page (`emit-api-reference.mjs`).

(The Examples section pages are emitted from `examples.entries.mjs`. You don't hand-write `<DocExample>` —
it's the generated tag underlying all of these.) Each mounts the example in Sandpack against the **mocked**
HAAPI driver (no backend) using the shared closure in `src/sandpack/closure.ts`.

```
examples/<Name>.tsx ──(docs:gen)──▶ examples.json[<Name>]
├─ [label](…/examples/<Name>.tsx) (README markdown) ─┐
├─ {@see_example …<Name>.tsx Label} (component TSDoc) ─┤─(generate)─▶ <DocExample id="<Name>"/>
└─ entry in examples.entries.mjs (Examples section) ─┘ │
▼ ▼
examples.json[<Name>] ──▶ SandpackPlayer( SDK + mocked driver + <Name>.tsx ) ──▶ live playground
```

## Add an example

1. Create `examples/MyExample.tsx` — a default `App`, wrapped in `<ExamplePreviewer>`.
2. Surface it by **name**: a markdown link `[label](…/examples/MyExample.tsx)` in the README, **or** an
entry in `examples.entries.mjs` (Examples section), **or** a `{@see_example …MyExample.tsx Label}`
marker in a component's TSDoc.
3. `npm run docs` — it's picked up automatically; no registry edit needed for `examples.json`.
142 changes: 142 additions & 0 deletions src/haapi-react-sdk/docs/api-reference.entries.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright (C) 2026 Curity AB. All rights reserved.
*
* The contents of this file are the property of Curity AB.
* You may not copy or use this file, in either source code
* or executable form, except in compliance with terms
* set by Curity AB.
*
* For further information, please contact Curity AB.
*/

/*
* Single source of truth for the API Reference docs layout. Each leaf entry maps an SDK export
* (`{ id, file, export }`) to a sidebar label; the grouping describes the nested sidebar tree.
*
* `scripts/emit-api-reference.mjs` walks the tree to generate `docs/api-reference/**`: it extracts each
* export's TSDoc (via `scripts/extract-tsdoc.mjs`) into a Markdown page, plus a `_category_.json` per
* (sub)category, ordered by declaration order here.
*
* Add or reorder API Reference pages here only — the generator follows automatically.
*/

/**
* The API Reference structure: an ordered list of top-level items, where an item is either a leaf
* entry (`{ id, file, export, label }`) or a group (`{ group, label, items }`) that nests further.
* @typedef {{ id: string, file: string, export: string, label: string }} ApiReferenceEntry
* @typedef {{ group: string, label: string, items: ApiReferenceItem[] }} ApiReferenceGroup
* @typedef {ApiReferenceEntry | ApiReferenceGroup} ApiReferenceItem
* @type {ApiReferenceItem[]}
*/
export const apiReferenceStructure = [
{
id: 'stepper',
file: 'haapi-stepper/feature/stepper/HaapiStepper.tsx',
export: 'HaapiStepper',
label: 'HaapiStepper',
},
{
id: 'use-haapi-stepper',
file: 'haapi-stepper/feature/stepper/HaapiStepperHook.ts',
export: 'useHaapiStepper',
label: 'useHaapiStepper',
},
{
id: 'step-ui',
file: 'haapi-stepper/feature/steps/HaapiStepperStepUI.tsx',
export: 'HaapiStepperStepUI',
label: 'HaapiStepperStepUI',
},
{
group: 'ui-components',
label: 'UI Components',
items: [
{
id: 'ui-components-overview',
file: 'haapi-stepper/ui/index.ts',
export: 'HaapiStepperUiComponents',
label: 'Overview',
},
{
// A documented component that also nests its parts: the form-field components are children of
// HaapiStepperFormUI (its `index.mdx`).
group: 'form-ui',
label: 'HaapiStepperFormUI',
id: 'form-ui',
file: 'haapi-stepper/feature/actions/form/HaapiStepperFormUI.tsx',
export: 'HaapiStepperFormUI',
items: [
{
id: 'form-field-ui',
file: 'haapi-stepper/feature/actions/form/fields/HaapiStepperFormFieldUI.tsx',
export: 'HaapiStepperFormFieldUI',
label: 'HaapiStepperFormFieldUI',
},
{
id: 'text-form-field-ui',
file: 'haapi-stepper/feature/actions/form/fields/HaapiStepperTextFormFieldUI.tsx',
export: 'HaapiStepperTextFormFieldUI',
label: 'HaapiStepperTextFormFieldUI',
},
{
id: 'password-form-field-ui',
file: 'haapi-stepper/feature/actions/form/fields/HaapiStepperPasswordFormFieldUI.tsx',
export: 'HaapiStepperPasswordFormFieldUI',
label: 'HaapiStepperPasswordFormFieldUI',
},
{
id: 'select-form-field-ui',
file: 'haapi-stepper/feature/actions/form/fields/HaapiStepperSelectFormFieldUI.tsx',
export: 'HaapiStepperSelectFormFieldUI',
label: 'HaapiStepperSelectFormFieldUI',
},
{
id: 'checkbox-form-field-ui',
file: 'haapi-stepper/feature/actions/form/fields/HaapiStepperCheckboxFormFieldUI.tsx',
export: 'HaapiStepperCheckboxFormFieldUI',
label: 'HaapiStepperCheckboxFormFieldUI',
},
],
},
{
id: 'selector-ui',
file: 'haapi-stepper/feature/actions/selector/HaapiStepperSelectorUI.tsx',
export: 'HaapiStepperSelectorUI',
label: 'HaapiStepperSelectorUI',
},
{
id: 'client-operation-ui',
file: 'haapi-stepper/feature/actions/client-operation/HaapiStepperClientOperationUI.tsx',
export: 'HaapiStepperClientOperationUI',
label: 'HaapiStepperClientOperationUI',
},
{
id: 'links-ui',
file: 'haapi-stepper/ui/links/HaapiStepperLinksUI.tsx',
export: 'HaapiStepperLinksUI',
label: 'HaapiStepperLinksUI',
},
{
id: 'messages-ui',
file: 'haapi-stepper/ui/messages/HaapiStepperMessagesUI.tsx',
export: 'HaapiStepperMessagesUI',
label: 'HaapiStepperMessagesUI',
},
{
id: 'error-notifier-ui',
file: 'haapi-stepper/feature/stepper/HaapiStepperErrorNotifier.tsx',
export: 'HaapiStepperErrorNotifier',
label: 'HaapiStepperErrorNotifier',
},
{
id: 'validation-error-wrapper-ui',
file: 'haapi-stepper/feature/actions/form/HaapiStepperFormValidationErrorInputWrapper.tsx',
export: 'HaapiStepperFormValidationErrorInputWrapper',
label: 'HaapiStepperFormValidationErrorInputWrapper',
},
],
},
];

/** Whether an item is a group (has nested `items`) rather than a leaf entry. */
export const isApiReferenceGroup = item => Array.isArray(item?.items);
Loading
Loading