Skip to content
Ndop UI

Angular 21 & 22 Open source MIT

Own your components. Update them anyway.

Accessible Angular components you install as source. Signals‑first, with a CLI that merges upstream fixes into the code you changed. Built for you and your agent.

Get started Browse components
npx @ndop/cli init

  • WAI-ARIA
  • SSR
  • Zoneless
  • Signals

Component showcase

Theme

Create your account

Join the Sawa Studio workspace.

At least 12 characters.

Or

This week

All pages

12,480

+18.2%

Compared with last week

Visitors by day, this week

Use the arrow keys to read each day.

Visitors by day
DayVisitors
Monday1420
Tuesday1980
Wednesday1710
Thursday2140
Friday2480
Saturday1260
Sunday1490

Team members

Four people in Product.

  • AN

    Amara Nwosu

    amara@sawa.studio

    Owner
  • KM

    Kwame Mensah

    kwame@sawa.studio

    Admin
  • SR

    Sofia Rossi

    sofia@sawa.studio

    Member
  • YT

    Yuki Tanaka

    yuki@sawa.studio

    Member

Team offsite

Kribi, with the whole studio.

October 2026
Sun Mon Tue Wed Thu Fri Sat
Selected19 Oct – 23 Oct · 5 days

Notifications

Choose what reaches your inbox.

When someone mentions you in a comment.

A summary of your projects every Monday.

New features, about once a month.

Verify your email

Enter the code we sent to fatou@sawa.studio.

Updates

Edit it. Update it anyway.

Change any file you install. ndop update merges upstream's fixes into your version, the way git merge does.

npx @ndop/cli update button

Conflicts get markers and a non-zero exit, never a silent overwrite.

How updates work
src/app/ui/button/button.tsYoursUpstream
const buttonVariants = variants({
  base: 'inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50',
  variants: {
    variant: {
      default: 'bg-primary text-primary-foreground hover:bg-primary/90',
      outline: 'border border-input bg-background hover:bg-accent',
      ghost: 'hover:bg-accent hover:text-accent-foreground',
      destructive:
        'bg-destructive text-destructive-foreground hover:bg-destructive/90',
      link: 'text-primary underline-offset-4 hover:underline',
    },
    size: {
      xs: 'h-7 px-2 text-xs',
      sm: 'h-8 px-3',
      md: 'h-9 px-4',
      lg: 'h-10 px-6',
      icon: 'size-9',
      xl: 'h-12 px-8 text-base',
    },
  },
  defaults: { variant: 'default', size: 'md' },
});

Agents

Built for agents.

Your coding agent reads the real API, installs what it needs and checks its own work, instead of guessing.

  • MCP server

    Every component, example, block and token for your agent, which can also install items and run verify.

    npx -y @ndop/mcp
  • Docs agents can read

    An index of every page, and each page as Markdown at its URL plus .md.

    /llms.txt
  • Guidance in your project

    ndop init writes the installed components, tokens, where files go and the workflow into AGENTS.md.

    AGENTS.md
  • ndop verify

    Checks usage, build, lint and accessibility, and names the file, line, rule and fix.

    npx @ndop/cli verify src/app

An eval suite of 89 prompts runs an agent with only the MCP server and scores each result with ndop verify.

Set up your agent
A sample session with the Ndop MCP server
  1. You: Add a notifications page with email and push switches.
  2. Tool call: get_project_context, returned Angular 22, zoneless; button, card, input installed
  3. Tool call: search_components "toggle setting", returned switch, toggle, checkbox
  4. Tool call: get_component switch, returned usage, parts, inputs, keyboard map
  5. Tool call: add_items ["switch", "form-field"], returned installed
  6. Writes src/app/notifications/notifications.ts
  7. Tool call: verify src/app/notifications, returned 1 problem
  8. Problem: notifications.ts:18 ndop/form-control-label: Nothing labels this control. Add an ndLabel with for set to its id, wrap it in a label, or give it aria-label.
  9. Adds a label to the push switch
  10. Tool call: verify src/app/notifications, returned passed

Accessibility

Accessible by contract.

Each primitive implements a written keyboard and ARIA contract. Here is Tabs', live: turn on Try the keyboard and press keys on the tabs.

Overview

The Kribi Foods rebrand: twelve screens, due Friday.

Focus a tab, then use the arrow keys, Home and End.

Keys the component handles.

Key Action
TabMoves focus into the tab list, to the selected tab; then to the active panel.
ArrowRightorArrowLeftIn a horizontal list, moves focus to the next or previous enabled tab, wrapping; selects it if automatic.
ArrowDownorArrowUpIn a vertical list, moves focus to the next or previous enabled tab, wrapping; selects it if automatic.
HomeMoves focus to the first enabled tab; selects it if automatic.
EndMoves focus to the last enabled tab; selects it if automatic.
EnterorSpaceSelects the focused tab.

  • WAI-ARIA patterns

    Primitives follow the Authoring Practices, with the roles, states and keys each pattern names.

  • axe on every route

    CI runs axe on every page of these docs, in every browser, and fails on any violation.

  • A spec.md per primitive

    Its keyboard map and focus rules are written down, and the tests and this table come from it.

Read Tabs' accessibility notes

Blocks

Start from a whole screen.

Logins, dashboards, settings and more, made of the same components. Add one with a single command, then make it yours.

By the numbers

Read from this build.

Counted from the registry and measured by the size report this site was built from.

Components
50
Blocks
12
Themes
5
Button, gzipped
1.3 KB
axe violations in CI
0
Angular versions
21 & 22

Add your first component.

Set Ndop up in an Angular app, then add what you need. Every file is yours from the start.

Get started
npx @ndop/cli init