Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
kinetix-accessibility
kinetix-accessibility
happones/kinetix
claude-code
accessibility
vue
inertia
dark-mode
screen-readers
kinetix
a11y-preferences

Per-user accessibility preferences (reduced motion, high contrast, text size, underline links, enhanced focus) persisted server-side + applied flash-free, plus screen-reader primitives (skip link, live-region announcer). Activates when wiring a11y settings, the panel, or SR support.

Install
php artisan boost:add-skill happones/kinetix

Save this content to: .claude/skills/kinetix-accessibility/SKILL.md

# Kinetix Accessibility Development

## When to Apply

Activate this skill when:
- Mounting `<KinetixAccessibilityPanel>` or wiring per-user a11y preferences.
- Adding the compact `<KinetixAccessibilityMenu>` (popover) to the header, login
  page or setup wizard (guest-safe — server persist is best-effort).
- Adding the `<KinetixModeToggle>` dark-mode button (Light/Dark/System), backed by
  `useKinetixAppearance` which shares the starter kit's `appearance` storage.
- Installing the `KinetixAccessibility` Vue plugin.
- Adding a `<KinetixSkipLink>` or announcing async updates to screen readers.

## Documentation

For full details, reference `docs/accessibility.md` (published at https://happones.github.io/kinetix/accessibility).

## Configuration

```bash
php artisan vendor:publish --tag=kinetix-accessibility-migrations && php artisan migrate
```

```php
'accessibility' => [
    'enabled'  => env('KINETIX_ACCESSIBILITY_ENABLED', false),
    'defaults' => ['reducedMotion' => false, 'highContrast' => false, 'textSize' => 'normal', 'underlineLinks' => false, 'enhancedFocus' => false],
],
```

## How it works

- **Per-user, self-service**: `GET/POST {prefix}/accessibility` (`AccessibilityController`),
  one `kinetix_accessibility` row per user (`AccessibilityManager::for/update`,
  merged over config defaults; `AccessibilityData` DTO normalizes values + textSize enum).
- **Shared + applied flash-free**: the prefs ship on every Inertia response as
  `kinetix_accessibility`. Install the **`KinetixAccessibility` plugin**
  (`app.use(...)`) — it injects the a11y CSS and applies classes to `<html>`
  before mount, reading the initial `data-page` prop + a localStorage mirror.
- **Classes on `<html>`**: `kx-reduce-motion`, `kx-high-contrast`,
  `kx-text-large`/`kx-text-x-large`, `kx-underline-links`, `kx-enhanced-focus`
  (CSS is injected by the plugin — theme-agnostic, `currentColor` outlines).

## Frontend

```vue
<KinetixAccessibilityPanel />   <!-- text-size segmented control + 4 toggles -->
```

- `useKinetixAccessibility()` → `{ prefs, set(key, value) }` (optimistic apply +
  persist + localStorage). `applyKinetixAccessibility(prefs)` is the standalone
  class-applier (used by the plugin).
- `<KinetixSkipLink target="#main" />` — visually hidden until focused.
- `useKinetixAnnounce()` → `announce(message, assertive?)` via a shared ARIA
  live region for SR-only announcements (toasts, counts, removed rows).
- `useKinetixReducedMotion()` → reactive `boolean` for motion CSS can't stop
  (timers, `<Transition>` durations): OS `prefers-reduced-motion` OR the
  `kx-reduce-motion` class OR `kinetix.motion = 'reduced'` (config, shared as
  `kinetix_config.motion`). One shared media listener + class observer,
  released with the last consumer. `useKinetixTransition(preset)` builds on it
  (`fade` · `slide-down` · `slide-up` · `scale` · `collapse` · `none`).
- `focusableNear(el)` (from `useKinetixFocusTrap`) → where focus goes when a
  focused element leaves the page (next tab stop, else previous).

i18n `a11y_*` / `skip_to_content` (en/es/fr/pt). Tests: `AccessibilityTest`,
`useKinetixAccessibility.spec.ts`.

## UUID / ULID Host Models

This feature's migration builds `user_id` with
`Happones\Kinetix\Support\HostKeys`, which types each column after YOUR model
at migrate time from its primary key (`HasUlids` -> ulid, `HasUuids` -> uuid, string `$keyType` ->
string, else bigint). Pin `kinetix.key_types.user|team` when detection cannot
see the setup; morph ids follow `kinetix.key_types.morph` (default bigint) —
set it when the referenced models use UUIDs/ULIDs. Apps migrated on an older
Kinetix have bigint columns on disk and need their own ALTER migration. Full
recipe: the `kinetix-boost` skill, section "UUID / ULID Host Models".

Kinetix Accessibility Development

When to Apply

Activate this skill when:

  • Mounting <KinetixAccessibilityPanel> or wiring per-user a11y preferences.
  • Adding the compact <KinetixAccessibilityMenu> (popover) to the header, login page or setup wizard (guest-safe — server persist is best-effort).
  • Adding the <KinetixModeToggle> dark-mode button (Light/Dark/System), backed by useKinetixAppearance which shares the starter kit's appearance storage.
  • Installing the KinetixAccessibility Vue plugin.
  • Adding a <KinetixSkipLink> or announcing async updates to screen readers.

Documentation

For full details, reference docs/accessibility.md (published at https://happones.github.io/kinetix/accessibility).

Configuration

php artisan vendor:publish --tag=kinetix-accessibility-migrations && php artisan migrate
'accessibility' => [
    'enabled'  => env('KINETIX_ACCESSIBILITY_ENABLED', false),
    'defaults' => ['reducedMotion' => false, 'highContrast' => false, 'textSize' => 'normal', 'underlineLinks' => false, 'enhancedFocus' => false],
],

How it works

  • Per-user, self-service: GET/POST {prefix}/accessibility (AccessibilityController), one kinetix_accessibility row per user (AccessibilityManager::for/update, merged over config defaults; AccessibilityData DTO normalizes values + textSize enum).
  • Shared + applied flash-free: the prefs ship on every Inertia response as kinetix_accessibility. Install the KinetixAccessibility plugin (app.use(...)) — it injects the a11y CSS and applies classes to <html> before mount, reading the initial data-page prop + a localStorage mirror.
  • Classes on <html>: kx-reduce-motion, kx-high-contrast, kx-text-large/kx-text-x-large, kx-underline-links, kx-enhanced-focus (CSS is injected by the plugin — theme-agnostic, currentColor outlines).

Frontend

<KinetixAccessibilityPanel />   <!-- text-size segmented control + 4 toggles -->
  • useKinetixAccessibility() → { prefs, set(key, value) } (optimistic apply + persist + localStorage). applyKinetixAccessibility(prefs) is the standalone class-applier (used by the plugin).
  • <KinetixSkipLink target="#main" /> — visually hidden until focused.
  • useKinetixAnnounce() → announce(message, assertive?) via a shared ARIA live region for SR-only announcements (toasts, counts, removed rows).
  • useKinetixReducedMotion() → reactive boolean for motion CSS can't stop (timers, <Transition> durations): OS prefers-reduced-motion OR the kx-reduce-motion class OR kinetix.motion = 'reduced' (config, shared as kinetix_config.motion). One shared media listener + class observer, released with the last consumer. useKinetixTransition(preset) builds on it (fade · slide-down · slide-up · scale · collapse · none).
  • focusableNear(el) (from useKinetixFocusTrap) → where focus goes when a focused element leaves the page (next tab stop, else previous).

i18n a11y_* / skip_to_content (en/es/fr/pt). Tests: AccessibilityTest, useKinetixAccessibility.spec.ts.

UUID / ULID Host Models

This feature's migration builds user_id with Happones\Kinetix\Support\HostKeys, which types each column after YOUR model at migrate time from its primary key (HasUlids -> ulid, HasUuids -> uuid, string $keyType -> string, else bigint). Pin kinetix.key_types.user|team when detection cannot see the setup; morph ids follow kinetix.key_types.morph (default bigint) — set it when the referenced models use UUIDs/ULIDs. Apps migrated on an older Kinetix have bigint columns on disk and need their own ALTER migration. Full recipe: the kinetix-boost skill, section "UUID / ULID Host Models".

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console