https://github.com/mikeyil/ulam
Accessibility utilities for the modern web. Focus management, live region announcements, i18n, and UI components, each independently installable, vanilla-first, with optional React, Remix, Vue, and Angular adapters. Named for the Filipino word for dish.
https://github.com/mikeyil/ulam
a11y a11yfred accessibility angular aria focus-management i18n react ulam vue wcag
Last synced: 3 days ago
JSON representation
Accessibility utilities for the modern web. Focus management, live region announcements, i18n, and UI components, each independently installable, vanilla-first, with optional React, Remix, Vue, and Angular adapters. Named for the Filipino word for dish.
- Host: GitHub
- URL: https://github.com/mikeyil/ulam
- Owner: mikeyil
- Created: 2026-05-13T16:56:07.000Z (21 days ago)
- Default Branch: main
- Last Pushed: 2026-05-20T23:52:18.000Z (14 days ago)
- Last Synced: 2026-05-21T05:49:29.131Z (14 days ago)
- Topics: a11y, a11yfred, accessibility, angular, aria, focus-management, i18n, react, ulam, vue, wcag
- Language: JavaScript
- Homepage:
- Size: 1.23 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- fucking-awesome-angular - ulam - Accessibility utilities for the modern web. Vanilla-first, with optional React, Remix, Vue, and Angular adapters. (Development Utilities / Accessibility)
- awesome-angular - ulam - Accessibility utilities for the modern web. Vanilla-first, with optional React, Remix, Vue, and Angular adapters. (Development Utilities / Accessibility)
README
# ulam
Accessibility utilities for the modern web. Vanilla-first, with optional React, Remix, Vue, and Angular adapters.
Named for the Filipino word for dish: the thing everything else is built around.
> Accessibility utilities for the modern web. Focus management, live region announcements, i18n, and UI components, each independently installable, vanilla-first, with optional React, Remix, Vue, and Angular adapters. Named for the Filipino word for dish.
## Packages
| Package | Description |
| ------- | ----------- |
| [`@ulam/taho`](packages/taho) | ARIA live region announcer, route announcer |
| [`@ulam/sili`](packages/sili) | Focus management, overlays, routing hooks |
| [`@ulam/calamansi`](packages/calamansi) | Data-agnostic i18n, locale hooks, logic utilities |
| [`@ulam/halohalo`](packages/halohalo) | AI provider adapters, model config, agentic mode |
| [`@ulam/ube`](packages/ube) | Framework-agnostic UI components (vanilla, React, Vue, Angular, Remix), theming, design tokens |
| [`@ulam/sawsawan`](packages/sawsawan) | The sauce: integration layer wiring the above together |
## Architecture
Each package is independently installable. Dependency flow is strictly one direction:
```text
calamansi ──┐
taho ────────┤──► sawsawan
sili ────────┤
ube ─────────┘
```
None of the four core packages import from each other or from sawsawan. Sawsawan is the only package that imports from the others.
## Install
Most packages are vanilla-first with optional framework adapters. Install only what you need:
```bash
npm install @ulam/taho # vanilla announcer; React, Remix, Vue, Angular adapters optional
npm install @ulam/sili # vanilla focus management; React, Remix, Vue, Angular adapters optional
npm install @ulam/calamansi # vanilla i18n; React, Vue, Angular adapters optional
npm install @ulam/halohalo # vanilla AI adapters; React, Vue, Angular adapters optional
npm install @ulam/ube # vanilla web components; React, Remix, Vue, Angular adapters optional
```
Or with npm aliases if you prefer shorter import names:
```bash
npm install taho@npm:@ulam/taho
npm install sili@npm:@ulam/sili
npm install calamansi@npm:@ulam/calamansi
```
## Framework support
Packages with framework-specific behavior ship subpath exports:
| Subpath | Framework | Description |
| ------- | --------- | ----------- |
| `@ulam/taho` | any | Vanilla core |
| `@ulam/taho/react` | React | `useAnnounce`, `Announcer` |
| `@ulam/taho/remix` | Remix | Route announcer, React re-exports |
| `@ulam/taho/vue` | Vue 3 | `useAnnounce` composable |
| `@ulam/taho/angular` | Angular 17+ | `AnnounceService` |
| `@ulam/sili` | any | Vanilla core |
| `@ulam/sili/react` | React | Hooks, overlay components, hash router |
| `@ulam/sili/remix` | Remix | Same hooks, Remix router |
| `@ulam/sili/vue` | Vue 3 | Composables matching all React hooks |
| `@ulam/sili/angular` | Angular 17+ | Services and standalone directives |
| `@ulam/calamansi` | any | Vanilla core |
| `@ulam/calamansi/react` | React | `I18nProvider`, `useT`, `usePref` |
| `@ulam/calamansi/vue` | Vue 3 | `useT`, `usePref` composables |
| `@ulam/calamansi/angular` | Angular 17+ | `I18nService`, `PrefService` |
| `@ulam/halohalo` | any | Vanilla core |
| `@ulam/halohalo/react` | React | `useCompletion`, `useProviderConfig` |
| `@ulam/halohalo/vue` | Vue 3 | `useCompletion`, `useProviderConfig` composables |
| `@ulam/halohalo/angular` | Angular 17+ | `CompletionService`, `ProviderConfigService` |
| `@ulam/ube` | any | Vanilla web components |
| `@ulam/ube/core` | any | Web component registrations |
| `@ulam/ube/react` | React | React component adapters |
| `@ulam/ube/remix` | Remix | React re-exports (Remix is React-based) |
| `@ulam/ube/vue` | Vue 3 | Vue component adapters |
| `@ulam/ube/angular` | Angular 17+ | Angular component decorators, UbeModule |
## Quick Start by Framework
### React
```javascript
import '@ulam/ube/base-tokens.css'
import '@ulam/ube/base-typography.css'
import '@ulam/ube/ui.css'
import '@ulam/sili/base.css'
import { Router } from '@ulam/sili/react'
import { Announcer } from '@ulam/taho/react'
import { I18nProvider } from '@ulam/calamansi/react'
import { Button, Dialog } from '@ulam/ube/react'
function App() {
const [isOpen, setIsOpen] = useState(false)
return (
setIsOpen(true)}>Open
setIsOpen(false)} heading="Title">
Content
)
}
```
### Remix
For framework-agnostic focus management and vanilla utilities:
```javascript
import { mountRouteFocus, focusPageHeading } from '@ulam/sili/remix'
import { announce } from '@ulam/taho/remix'
```
For React routes in Remix, use the `/react` subexports:
```javascript
import { useRouter, useRouteMatch } from '@ulam/sili/remix/react'
import { useRouteAnnouncer } from '@ulam/taho/remix/react'
import { Button } from '@ulam/ube/react'
```
Web components work identically across all frameworks (`@ulam/ube/remix` re-exports from core).
### Vue
Use `/vue` subpaths:
```javascript
import { useFocusTrap, useDir } from '@ulam/sili/vue'
import { useT } from '@ulam/calamansi/vue'
import { useAnnounce } from '@ulam/taho/vue'
import { Button } from '@ulam/ube/vue'
```
### Angular
Use `/angular` subpaths:
```typescript
import { FocusTrapDirective } from '@ulam/sili/angular'
import { I18nService } from '@ulam/calamansi/angular'
import { AnnounceService } from '@ulam/taho/angular'
import { UbeModule } from '@ulam/ube/angular'
@NgModule({
imports: [UbeModule],
})
export class AppModule {}
```
## Core Concepts
- **Vanilla-first**: Every package has a vanilla core with zero dependencies. Framework adapters are optional add-ons.
- **Independent**: Install only what you need. Packages don't import each other.
- **Accessible by default**: All components handle focus, keyboard, ARIA, and screen reader support automatically.
- **Strictly Linted**: The codebase enforces accessibility and inclusivity through `@a11yfred/neighbor`.
- **Tree-shakeable**: Component CSS imports only what's used. Unused code doesn't bundle.
## Resources
- [@ulam/sili](packages/sili) — Focus management, overlays, routing
- [@ulam/taho](packages/taho) — Live region announcements
- [@ulam/calamansi](packages/calamansi) — i18n and utilities
- [@ulam/ube](packages/ube) — UI components and theming
- [@ulam/sawsawan](packages/sawsawan) — The sauce: integration layer
## License
MIT