Skip to content

Port all Livewire UI components to React - #23

Merged
ViewFromTheBox merged 60 commits into
release/1.0from
feature/react-package
Mar 29, 2026
Merged

ViewFromTheBox merged 60 commits into
release/1.0from
feature/react-package

Conversation

@ViewFromTheBox

@ViewFromTheBox ViewFromTheBox commented Mar 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Test plan

  • All Vitest test suites pass (npm run test from monorepo root)
  • Build succeeds for all packages (npm run build)
  • Lint passes (npm run lint)
  • TypeScript compilation passes with no errors
  • Component exports are correct in barrel files
  • Tokens Tailwind plugin integrates correctly

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Comprehensive design tokens (colors, typography, spacing, shadows, animations, glass) and theme system (light/dark/system).
    • Large UI library added: 50+ components across forms, navigation, layouts, data, feedback, and utilities (charting, toast, spotlight search).
  • Accessibility

    • Accessibility attributes and keyboard support added across components.
  • Chores

    • CI/build moved to Node/npm; Changesets configured for releases.
    • Linting and Prettier formatting rules added.
  • Tests

    • Extensive Vitest test suites covering components and tokens.

ViewFromTheBox and others added 30 commits March 27, 2026 17:52
Configure ESLint 9 flat config with TypeScript and React support, Prettier
for consistent formatting, Changesets for version management, and rewrite
the CI/CD workflow from PHP/Pest to Node.js with lint, type-check, test,
build, and automated npm publishing via Changesets.

Closes #1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use npm run format:check in CI instead of direct npx prettier call
- Remove redundant @typescript-eslint/eslint-plugin and @typescript-eslint/parser
  (already provided by typescript-eslint)
- Remove unused vitest from react-laravel devDependencies

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ld-tooling-ci-cd

enhancement: set up monorepo build tooling and CI/CD pipeline
Build the shared, framework-agnostic design token layer with all values
derived from the Livewire component library's DaisyUI/Tailwind configuration.

Includes:
- Color palette (DaisyUI theme colors + dark mode overrides)
- Color resolver utility (resolveColor, resolveContentColor, resolveAllColors)
- Spacing scale (0–96 with named aliases)
- Typography tokens (families, sizes, weights, line heights, letter spacing, presets)
- Border radius scale + DaisyUI component radii
- Shadow tokens (elevation, colored, glow + dark mode variants)
- Animation tokens (durations, easings, expressive easings)
- Glass helpers (base, frosted, liquid, transparent presets with style/className generators)
- CSS custom properties stylesheet (importable via @artisanpack-ui/tokens/css)
- Tailwind CSS plugin (importable via @artisanpack-ui/tokens/tailwind)
- Shared types (DaisyColor, Size, GlassProps, ColorProps, FormFieldProps)
- 69 tests across 10 test files

React package types now re-export from tokens to avoid duplication.

Closes #2

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- @changesets/cli 2.27 -> 2.30
- prettier 3.4 -> 3.8
- typescript 5.7 -> 5.9.3
- clsx 2.1.0 -> 2.1.1
- tailwind-merge 2.6 -> 3.5 (major)
- vitest 2.1 -> 4.1 (major)
- @testing-library/jest-dom 6.6 -> 6.9
- @testing-library/react 16.1 -> 16.3
- @vitejs/plugin-react 4.3 -> 6.0 (major)
- jsdom 27 -> 29 (major)
- react/react-dom 19.0 -> 19.2
- @inertiajs/react 2.0 -> 3.0 (major)
- tailwindcss peer dep updated to >=4.0.0

ESLint stays at 9.x (eslint-plugin-react doesn't support 10 yet).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add missing test assertion for shadows.base in shadow tests
- Create GlassInlineStyleOptions type to prevent passing tint/tintOpacity
  to glassStyles() (tints require CSS pseudo-elements, use glassClassName)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add browser-path tests for color resolver (mock getComputedStyle)
- Expand shadowsDark test to cover all elevation levels, not just sm
- Add none key to shadowsDark for key parity with shadows
- Fix tailwind plugin to match real plugin(handler, config?) API shape
- Add TailwindPluginFn and TailwindPluginAPI types for typed contract
- Replace Object.values loop with explicit pairwise font size comparisons
- Separate glass option types: GlassClassOptions (tint, no dark) vs
  GlassInlineStyleOptions (dark, no tint) to prevent silent no-ops
- Use import.meta.url in tsup config for reliable path resolution

Skipped (verified not needed):
- react-laravel peerDep: intentional scaffold for future adapter
- CSS font-family quoting: values match Tailwind defaults exactly
- types.ts GlassPreset import: IS used by GlassProps interface

73 tests pass (up from 69).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Skip glass-tint-opacity class when tintOpacity is 0 (was clamping to 10)
- Fix JSDoc referencing non-existent artisanPackPlugin export name
- Skipped: fontSizes has no 'md' key so test coverage is already complete

74 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @plugin directive requires a default export which this module doesn't
provide. Replaced with a complete tailwind.config.ts usage example.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use a generic R parameter on TailwindPluginFn so createArtisanPackPlugin
returns the concrete type from the plugin factory instead of unknown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ckage

feat: implement @artisanpack-ui/tokens design token package
Add feedback component category directory with barrel export, tsup entry
point, and package.json sub-path export. Create ThemeProvider context and
useTheme hook for color scheme management (light/dark/system with media
query listener). Export ColorScheme and ThemeContextValue types. Fix
test-setup.ts hoisting issue with @testing-library/jest-dom. Add 8 tests
covering all ThemeProvider behavior.

Closes #3
…ackage-scaffolding

Enhancement: Complete base package scaffolding
Port all form components to React with TypeScript and DaisyUI/Tailwind CSS
styling: Button, Input, Textarea, Select, Checkbox, Radio, Toggle, Range,
ColorPicker, DatePicker, File, Password, Pin (OTP), Editor, RichTextEditor.

Each component supports ref forwarding, full TypeScript prop types, DaisyUI
color variants, accessibility (ARIA attributes, keyboard navigation), and
unit tests. Includes 75 new component tests.

Closes #4
- Remove duplicate 'neutral' from Button color prop type
- Add 'neutral' to Checkbox, Radio, Pin colorMaps
- Fix hintId computation in Checkbox and Toggle (hint && !error)
- Add aria-hidden to Input prefix/suffix spans
- ColorPicker: notify onChange on random/clear, reset state on clear
- File: call onChange in handleDrop for consumer notification
- Radio: conditional aria-labelledby when label is present
- Pin: add aria-describedby for error, stricter onComplete test assertion
- Button: tooltip now wraps both link and button branches
- Checkbox: pass required to input, prevent rest from overriding ARIA
- ColorPicker: make action buttons keyboard accessible, notify onChange on clear
- File: omit value/defaultValue from props type
- Radio: add required to first radio input for native validation
- Toggle: add neutral to colorMap
- File: forward required prop to native file input elements
- Radio: apply required to first enabled option instead of index 0
- Radio: card variant respects color prop instead of hard-coding primary
- Add aria-invalid to radiogroup fieldset when error exists
- Attach forwarded ref to first enabled option instead of index 0
…ents

feat: port 15 form components to React
Port the complete layout component category to React with TypeScript
and DaisyUI/Tailwind CSS: Card, Modal, Tabs, Accordion, Collapse,
Drawer, Dropdown, Divider, Stack, Grid, and Popover.

Each component supports ref forwarding, full TypeScript prop types,
controlled/uncontrolled state, DaisyUI color and size variants, and
accessibility (ARIA attributes, keyboard navigation, focus management).

Tabs supports vertical/vertical-right orientation with color and
custom class props. Modal uses native <dialog> with focus restoration.
Dropdown and Popover use DaisyUI CSS-based show/hide for reliability.

Includes 131 unit tests across 11 test files (280 total passing).

Closes #5
- Card: discriminated union props (CardDivProps | CardLinkProps) for
  correct ref/attribute types when link prop is present
- Collapse: move aria-expanded from title div to the input elements
  where assistive tech expects it
- Divider: type colorMap as Record<DaisyColor, string>, guard
  positionMap on label/children presence
- Drawer: add focus trap (Tab/Shift+Tab cycling), focus first element
  on open, restore focus on close, forward aria-label/aria-labelledby
  to the dialog element
- Dropdown: use cloneElement to attach aria/click/keyboard props
  directly to custom triggers (avoids nested focusable elements),
  properly type DropdownItem onClick as MouseEventHandler<HTMLButtonElement>
- Modal: add aria-labelledby pointing to title heading, always
  preventDefault on cancel event to prevent DOM/React state desync
- Popover: add onFocus/onBlur handlers for hover mode keyboard access,
  global Escape listener when open, type positionMap with Position type
- Stack/Grid: replace dynamic template-string classes with static maps
  to prevent Tailwind CSS purging
- Tabs: remove redundant !tab.disabled guard (button disabled prop
  already prevents clicks)
- Accordion: displayName-based type guard for wrapped Collapse variants
- Grid tests: add gapX-only and gapY-only fallback branch coverage
- Collapse test: verify aria-expanded on input element
- Accordion: remove radio name prop to preserve checkbox semantics so
  clicking an open panel in single mode fires onChange and closes it
- Collapse: add aria-labelledby on inputs pointing to title element ID
  so assistive tech announces the control name
- Dropdown: target inner <button> in getMenuItemButtons() instead of
  <li> so keyboard focus lands on the interactive element; compose
  original trigger handlers with dropdown handlers via cloneElement
- Popover: check relatedTarget in mouseLeave to avoid closing when
  moving between trigger and content; use showDelay for focus handler;
  remove redundant handlers on content div
- Tabs: validate defaultTab/activeTab against selectable tabs with
  fallback to first enabled tab; use index-based IDs and data
  attributes for querySelector and aria references
- Drawer: filter getFocusableElements for tabIndex >= 0, exclude
  hidden inputs and aria-hidden/invisible elements; forward
  aria-describedby to dialog element
- Accordion: use Collapse-relative indices (skip non-Collapse children);
  isCollapseElement is now a type predicate eliminating casts
- Drawer: cancel requestAnimationFrame on cleanup to prevent stale
  focus; Tab trap reclaims focus when activeElement escapes panel
- Dropdown: Escape restores focus to trigger via triggerRef; composed
  handlers respect defaultPrevented; default trigger is native <button>;
  role="menuitem" + aria-disabled moved from <li> to inner <button>,
  <li> gets role="none"; getMenuItemButtons selects button[role=menuitem]
- Popover: add persistent prop to skip outside-click/Escape dismiss;
  extract and compose external onMouseEnter/Leave/Focus/Blur handlers
  from rest props; cloneElement trigger directly instead of wrapping
  in synthetic div[role=button]; remove dropdown-hover class to prevent
  DaisyUI :focus-within/:hover from overriding React state
- Tabs: map enabledTabs index back to full tabs array index for
  querySelector focus targeting
- Popover: add Escape and outside-click dismissal tests; fix z-1 → z-[1]
  for valid Tailwind z-index utility
- Accordion: compose consumer onOpenChange with handleToggle instead
  of overwriting it
- Dropdown: early return in handleMenuKeyDown when items empty; capture
  triggerRef via event.currentTarget instead of injecting ref; narrow
  trigger prop to ReactElement | null; fix z-1 → z-[1]
- Tabs: type variantMap as Record<Variant, string> and colorMap as
  Record<DaisyColor, string> for exhaustive compile-time checks;
  normalize uncontrolled internalTab when tabs change; guard
  handleSelect to only accept selectable tab names
- Drawer: fix forward-Tab trap when activeElement is the panel
  container itself (activeIndex === -1)
- Accordion: normalize/dedupe currentOpen before state computation,
  filter out-of-range indices against Collapse child count
- Drawer: remove unused useCallback import; add contenteditable and
  inert support to getFocusableElements; add aria-hidden={!open} on
  drawer-side so AT ignores closed panel
- Dropdown: guard setOpen to skip when state unchanged (prevents
  duplicate onOpenChange); add JS hover handlers (mouseEnter/Leave)
  so hover prop drives React state + ARIA; add Tab key handler in
  menu to close without preventing default
- Popover: guard setOpen against duplicate calls; add inline
  visibility override on content to prevent DaisyUI :focus-within
  from revealing closed content; make hover-mode non-element fallback
  focusable (span with tabIndex/role)
- Tabs: add useEffect to sync internalTab when tabs prop changes
  and current selection becomes invalid
- Popover: add persistent-blocks-Escape test; stopPropagation on
  Escape to prevent parent dismissals; remove role="button" from
  hover-mode fallback span (focus-driven, not activation-driven)
- Accordion: enforce single-open invariant — cleanOpen.slice(0,1)
  when multiple is false
- Dropdown: extract and compose consumer onMouseEnter/onMouseLeave
  with internal hover handlers; gate dropdown-hover CSS class on
  uncontrolled mode only so controlled state isn't bypassed
- Tabs: add JSDoc stability note on tabs prop recommending useMemo
- Popover: add Enter/Space keyboard activation tests for click mode;
  import MutableRefObject to avoid React namespace reference;
  stopPropagation on Escape to prevent parent dismissals
- Accordion: hoist cleanOpen derivation above handleToggle for
  clearer reading order
- Dropdown: import MutableRefObject; Tab key just closes without
  refocusing trigger (natural focus flow); Escape stopPropagation on
  both trigger and menu handlers; sync focusedIndex from
  document.activeElement when -1; closeFocusTrigger falls back to
  containerRef querySelector for hover/controlled scenarios
- Accordion: add role="group" on wrapper for screen-reader context
- Popover: generate stable contentId via useId and wire
  aria-controls on all trigger paths pointing to the content div id;
  detect non-focusable intrinsic elements (div, span, etc.) and
  inject tabIndex=0 when cloning to ensure keyboard reachability
- Popover: restore focus to trigger on Escape dismiss via
  containerRef querySelector; replace denylist with allowlist of
  natively focusable intrinsics (FOCUSABLE_INTRINSICS); detect and
  wrap React.Fragment triggers in a focusable container; extract
  wrapInFocusable helper for consistent fallback rendering
ViewFromTheBox and others added 18 commits March 29, 2026 10:33
- Calendar: fix nested button-in-button by splitting day cell into a
  container div with separate day button and event dot buttons as siblings.
  Use Record<DaisyColor, string> for type-safe color maps. Add tests for
  minDate/maxDate constraints, event overflow indicator, and keyboard
  activation on event dots.
- Carousel: clamp current index to valid range when slides shrink. Call
  consumer onKeyDown/onTouchStart/onTouchEnd first and respect
  defaultPrevented. Skip keyboard navigation when target is an interactive
  element (input, button, etc.).
- Table: safely render non-primitive cell values via JSON.stringify instead
  of casting to ReactNode which produces [object Object].
- Badge: add falsy value edge case test (value={0}), strengthen ref
  assertion to verify HTMLSpanElement instance.
- Calendar: increase event dot touch target (w-4 h-4 wrapper around
  w-1.5 h-1.5 visual dot), use event.id as stable React key, add Space
  key assertion to keyboard test.
- Carousel: clamp current via useEffect when slides.length changes,
  compute safeIndex once and use throughout (next/prev/render/indicators),
  guard window.matchMedia for jsdom compatibility, add anchor tags to
  isInteractiveTarget, call consumer handlers first with defaultPrevented
  check, pass safeIndex to renderSlide callback.
- Table: preserve non-visible selections in toggleSelectAll/toggleSelect
  by operating on a copy of selectedKeys. Make sortable headers keyboard-
  accessible by rendering a native <button> inside <th> instead of making
  the <th> itself clickable.
- Calendar: sync viewDate when controlled value prop changes via
  useEffect. Remove redundant custom onKeyDown from event dot buttons
  (native <button> already fires onClick on Enter/Space, preventing
  double-firing). Simplify handleEventDotInteraction signature.
- Carousel: clear touchStartRef on defaultPrevented early-return to
  prevent stale coordinates causing ghost swipes. Add onTouchCancel
  handler. Add anchor tags ('A') to isInteractiveTarget check.
- Table: derive canExpand from expandable && !!renderExpansion so
  expansion UI only renders when both props are provided. Gate sort
  button rendering on onSort presence to avoid dead controls in tab
  order. Wrap JSON.stringify in try/catch (safeStringify) to handle
  circular references gracefully.
- Calendar: expand multi-day events (endDate) across all dates in
  eventsByDate map. Render event dots as non-interactive <span> when
  onEventClick is not provided (removes dead buttons from tab order).
  Replace duplicate onEventClick test with controlled value → viewDate
  sync test.
- Carousel: extract onTouchCancel from props to merge with internal
  handler instead of allowing ...rest to override it.
- Table: render boolean cell values as "true"/"false" strings instead
  of silently swallowing them (React doesn't render booleans).
- Calendar: add role="img" and aria-label to non-interactive event dots
  so screen readers announce event names. Add tests for multi-day event
  expansion (endDate) and non-interactive dot rendering when onEventClick
  is absent.
- Table: disable selection checkboxes (both header and per-row) when
  onSelectionChange is not provided, removing dead controls from the
  tab order.
…splay-components

enhancement: Port Data Display components to React
Add 6 feedback components: Alert (dismissible, controlled/uncontrolled,
severity-based aria-live), Loading (6 variants, color/size), Skeleton
(text/card/image placeholders), EmptyState (icon, title, description,
action, configurable heading tag), ErrorDisplay (retry action, custom
icon/label), and Toast (context provider, useToast hook, auto-dismiss
with configurable duration, 0 for persistent, max stacking, eviction
timer cleanup).

Includes 61 unit tests covering all components.

Closes #8
- Remove unused createElement import from EmptyState
- Fix Skeleton circle to normalize both dimensions from whichever is
  provided (width-only circle was previously broken)
- Make Toast state updater pure by computing evictions before setToasts
- Add aria-label="Notifications" to Toast container
- Make ToastMessage role conditional: role="alert" for warning/error,
  role="status" for info/success
- Add tests for new behaviors (circle width-only, toast roles, container
  aria-label)
- Rename EmptyState title/titleAs props to heading/headingAs to avoid
  collision with native HTML title attribute; omit title from base type
  so it can still be passed via ...rest for tooltips
- Fix Toast show() race condition: use functional setToasts updater with
  evictedIdsRef instead of reading stale toastsRef.current outside the
  updater
- Add test verifying default 5000ms auto-dismiss duration
- Update dev app demo to use new heading prop

Closes #8
Verify that headingAs renders the correct semantic element by asserting
role='heading' at the expected level.

Closes #8
…k-components-to-react

Enhancement: Port feedback components to React
Add 5 utility components: Icon, ThemeToggle, Tooltip, Clipboard, and
Markdown. Each component includes full TypeScript types, accessibility
support (ARIA attributes, keyboard interaction), DaisyUI variant props,
and comprehensive unit tests.

- Icon: SVG wrapper with size/color/viewBox props and decorative vs labeled modes
- ThemeToggle: Cycles light/dark/system using existing useTheme hook
- Tooltip: DaisyUI tooltip with aria-describedby on hover/focus
- Clipboard: Copy-to-clipboard with success feedback and onCopy callback
- Markdown: Built-in lightweight parser with XSS protection and custom render support

Closes #9

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix Tooltip bug: tooltip-open class now uses isOpen (computed state)
  instead of open (prop only), so it toggles on hover/focus
- Fix Clipboard: extract onClick from rest props and merge with
  handleCopy so consumer onClick is not silently overridden
- Fix ThemeToggle: extract onClick from rest props and compose with
  handleToggle to prevent override via spread
- Fix Markdown XSS: decode HTML entities (numeric, hex, named) before
  URL safety check to prevent scheme obfuscation like java&#115;cript:
- Add tests for tooltip-open hover/focus toggling
- Add test for HTML-entity-encoded javascript: URL rejection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tooltip:
- Fix accessibility: add sr-only span with role="tooltip" containing
  real DOM text for screen readers instead of relying on data-tip CSS
- Merge aria-describedby with existing values instead of overwriting
- Use separate tipId for aria-describedby to avoid id collision
- Extract consumer id prop to prevent ...rest from overwriting it

Clipboard:
- Respect e.defaultPrevented after calling userOnClick so consumers
  can cancel the copy operation

ThemeToggle:
- Respect e.defaultPrevented after calling onClickProp
- Import MouseEvent type explicitly from react
- Map md size to 'btn-md' for consistency with Button component

Markdown:
- Fix decodeEntities ordering: decode &amp; before numeric entities
  so &amp;#x3a; sequences are fully resolved for URL safety checks
- Add security JSDoc warning on renderMarkdown about
  dangerouslySetInnerHTML trust boundary

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clipboard:
- Map md size to 'btn-md' for consistency with Button/ThemeToggle

Markdown:
- Strip ASCII C0 control characters in isSafeUrl before scheme checks
  to prevent bypass via embedded newlines/tabs in URLs
- Narrow MarkdownProps to Omit<..., 'children' | 'dangerouslySetInnerHTML'>
  to prevent consumer override of internal HTML injection
- Spread ...rest before component-controlled props so internal
  dangerouslySetInnerHTML always takes precedence

ThemeToggle:
- Change aria-label from current-state ("Light mode") to action-oriented
  ("Switch to dark mode") computed dynamically from the modes array
- Lift nextIndex/nextMode computation out of handler for label access

Tooltip:
- Handle Fragment children by wrapping in a focusable span so event
  handlers and ARIA attributes can be attached
- Accept plain ReactNode children (not just ReactElement)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ThemeToggle:
- Show non-actionable label when nextMode equals current colorScheme
  (e.g., modes={['dark']} shows "dark mode (current)" not "Switch to")
- Add regression test for single-mode list

Tooltip:
- Move {...rest} spread before data-tip and id so consumer props
  cannot override the component-controlled tip text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ggle

Prevents consumer props from overriding aria-label, onClick, and type
on the ThemeToggle button element.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-components

enhancement: Port Utility components to React
@coderabbitai

coderabbitai Bot commented Mar 29, 2026 •

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds a full React UI library and tokens package: 40+ components (data, form, layout, navigation, feedback, utility), comprehensive Vitest test suites, a design-tokens system (CSS vars, Tailwind plugin, color resolver, glass helpers), TypeScript typing reorganization, and developer tooling/CI updates (ESLint, Prettier, Changesets, Node-based CI).

Changes

Cohort / File(s) Summary
Tooling & Repo Config
.coderabbit.yaml, .changeset/README.md, .changeset/config.json, .github/workflows/ci.yml, .prettierrc, .prettierignore, eslint.config.js, package.json, tsconfig.json, tsup/workflow tweaks
Add/replace repo configs: Changesets config and README, CodeRabbit settings, Prettier & ESLint flats, switch CI from PHP/Composer to Node/npm jobs, add ESM "type": "module" and new scripts.
Monorepo Build & Packaging
packages/react/tsup.config.ts, packages/react/package.json, packages/tokens/package.json, packages/tokens/tsup.config.ts
Add ESM entrypoints (chart, feedback, tailwind-plugin), mark apexcharts externals, export tokens CSS/tailwind plugin, update peer/dev dependencies, and copy CSS into dist post-build.
Type/Barrel Re-exports
packages/react/src/types/*, packages/react/src/index.ts, packages/react/src/components/*/index.ts, packages/tokens/src/index.ts
Move many common types into @artisanpack-ui/tokens, add/adjust barrels to export new components/types and re-export theme hook/types.
Theme & Hooks
packages/react/src/hooks/use-theme.tsx, packages/react/src/__tests__/use-theme.test.tsx, packages/react/src/test-setup.ts
Introduce ThemeProvider/useTheme (light/dark/system) with matchMedia syncing and tests; update Vitest setup to explicitly extend jest-dom matchers.
Tokens core
packages/tokens/src/{colors,color-resolver,animation,borders,shadows,spacing,typography,glass,tailwind-plugin}.ts, packages/tokens/src/css/tokens.css
Add comprehensive design tokens: colors (+dark), color resolver utilities, animation/easing tokens, border radii, shadow scales (colored/glow), spacing scale, typography presets, glass tokens + helpers, Tailwind plugin and a tokens CSS file with glass utility classes and tint modifiers.
Tokens tests & utils
packages/tokens/src/__tests__/*, packages/tokens/src/utils/*
Add Vitest suites validating tokens, cn utility and color resolution, plus tests for tailwind plugin integration and glass helpers.
React components — Data & Visualization
packages/react/src/components/data/... and packages/react/src/components/data/index.ts
Implement Avatar, Badge, Calendar (events), Carousel (touch/keyboard/autoplay), Chart (Apex wrapper + deepMerge), Code, Diff (LCS-based), Progress, Sparkline, Stat (+sparkline), Table (sorting/selection/expansion), Timeline — all with typed props, forwardRef, and exports.
React components — Form
packages/react/src/components/form/... and packages/react/src/components/form/index.ts
Implement Button, Checkbox, ColorPicker, DatePicker, Editor, File (drag/drop), Input, Password, Pin (OTP), Radio, Range, RichTextEditor, Select, Textarea, Toggle — accessibility wiring, error/hint handling, ref forwarding, and exports.
React components — Layout
packages/react/src/components/layout/... and packages/react/src/components/layout/index.ts
Implement Accordion, Card, Collapse, Divider, Drawer (focus trap/escape handling), Dropdown (menu + keyboard nav + DropdownItem), Grid, Modal (dialog showModal/close), Popover (hover/click modes), Stack, Tabs — full ARIA/keyboard behaviors and exports.
React components — Navigation
packages/react/src/components/navigation/... and packages/react/src/components/navigation/index.ts
Implement Breadcrumbs (collapsing), Menu (nested, active state, keyboard nav), Navbar, Pagination (ellipsis/siblings), Sidebar (drawer-based), SpotlightSearch (combobox/filter/grouping/keyboard), Steps — all typed and exported.
React components — Feedback & Utility
packages/react/src/components/feedback/..., packages/react/src/components/utility/..., and their indexes
Implement Alert, EmptyState, ErrorDisplay, Loading, Skeleton, Toast (provider + useToast hook), plus utility components: Clipboard, Icon, Markdown, ThemeToggle, Tooltip — with tests and barrel exports.
Tests — React
packages/react/src/__tests__/**/* (many files)
Add extensive Vitest + Testing Library coverage for nearly all new components (rendering, interactions, accessibility, refs, edge cases).
Small edits / module markers
packages/react-laravel/src/index.ts, packages/react/src/components/display/index.ts
Added empty export {} markers and small package.json script adjustments to ensure ESM/tooling compatibility.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Poem

🐰 Hops through code with tiny paws so spry,

Components bloom beneath my sky;
Tokens gleam and themes take flight,
Tests applaud each passing night.
A rabbit cheers — the UI’s right!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/react-package

Fix 17 potential issues: Button anchor forwarding, synthetic event
dispatch in ColorPicker/File, Pin controlled sync, RichTextEditor
cursor preservation, Toggle a11y, Carousel autoplay stability,
Sparkline empty-array guard, Stat zero-change neutrality, Avatar
dead code, Divider falsy-children check, Breadcrumbs aria-current,
Pagination bounds validation, Sidebar callback stability,
SpotlightSearch listener consolidation, use-theme SSR safety.

Address ~30 nitpicks: test isolation with vi.stubGlobal, DaisyUI v4
menu-compact→menu-sm, exported consumer types, nested menu a11y
roles, hex color casing, Tailwind v4 plugin docs, redundant code
removal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ViewFromTheBox
ViewFromTheBox merged commit e55cd2d into release/1.0 Mar 29, 2026
1 check was pending
@github-project-automation github-project-automation Bot moved this from In Review to Done in ArtisanPack UI Overview Mar 29, 2026
@ViewFromTheBox
ViewFromTheBox deleted the feature/react-package branch March 29, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant