Skip to content

v3.0.0#86

Open
smastrom wants to merge 68 commits into
mainfrom
dev
Open

v3.0.0#86
smastrom wants to merge 68 commits into
mainfrom
dev

Conversation

@smastrom

@smastrom smastrom commented May 29, 2026

Copy link
Copy Markdown
Owner

Reopens #83 on the dev integration branch (formerly v3). Package version 3.0.0.

Notivue 3 is a major release focused on a clearer public API, CSS-driven motion, and simpler keyboard navigation. Deprecated v2 names remain exported as aliases so existing imports keep working during migration.

Summary

  • notify replaces push as the primary API. notify.loading() returns a handle with .success() / .error() instead of promise .resolve() / .reject().
  • Motion moves to CSS variables. animations and transition are removed from config. Enter, leave, clearAll(), and stack reposition timing are controlled via --nv-enter-animation, --nv-leave-animation, --nv-clear-all-animation, and --nv-transform-transition (defaults in notivue/animations.css).
  • Stream layout: --nv-gap is block-end margin on <li> list items (not padding on the inner wrapper) so keyboard focus rings hug the toast. Rows are content-sized (width: max-content, maxWidth: 100%) with horizontal placement from the position config only (*-left / *-center / *-right). Removed --nv-root-x-align. Stack transforms use getListItemStackHeight (clientHeight + parsed gap margin).
  • Stream DOM data attributes (v3, unreleased names): <li data-notivue-list-item> carries the notification id; inner animation wrapper uses data-notivue-item. Replaces the v2 data-notivue-item on <li> and data-notivue-container on the wrapper. Animation nodes are tracked via elements.itemContainers Vue refs (no querySelector in store code).
  • NotivueKeyboard is self-contained. No slot props, no containersTabIndex on Notivue, no useNotivueKeyboard() wiring. Stream focus, tabindex, and aria-label live on <li>; inner wrapper is not focusable.
  • Pause-on-focus pauses timeouts when the stream receives focus and resumes when focus leaves, alongside existing pause-on-hover and pause-on-touch.
  • Monorepo tooling refresh: tsdown build, oxfmt + oxlint, pnpm 9, Vue 3.5, Nuxt 4 playground, Astro 5 playground, Cypress 15 / Vitest 3 test stack.

Breaking changes

Area v2 v3
Primary API push notify (push kept as deprecated alias)
Async notifications push.promise() / .resolve() / .reject() notify.loading() / .success() / .error()
Motion config animations, transition in createNotivue() CSS variables; import notivue/animations.css
Unlimited queue limit: Infinity limit: -1
Keyboard setup Slot props + useNotivueKeyboard() + :containersTabIndex Wrapper only; library manages focus on list items
Stream DOM hooks data-notivue-item on <li>, data-notivue-container on wrapper data-notivue-list-item on <li>, data-notivue-item on wrapper
useNotivueKeyboard() Injected tabindex map Deprecated no-op stub (returns inert defaults)

All deprecated symbols remain exported. See the alias table below.

Core API

  • Add createNotify / notify as primary entry; createPush / push are same-object aliases
  • Introduce loading, loading-success, loading-error notification types; normalize legacy promise* config at enqueue
  • Rename callbacks: onAutoClearonTimedOut, onManualClearonClear; add onDestroy for destroy actions
  • Move shared defaults into notifications.global; merge order is global → per-type → call-site
  • Pending loading notifications enforce duration: -1
  • Wrap NotivueItem, NotifyOptions, and UseNotivueReturn with Prettify<> for cleaner IDE hovers
  • Deprecate isTopAlign from useNotivue(); use config.position.value.startsWith('top')
  • destroyAll clears pending timeouts before removing items
  • Align warning ARIA defaults with error severity (assertive / alert)

Animations and transitions

  • Remove animations and transition from NotivueConfig
  • Apply motion through inline styles backed by MOTION_VARS_CSS and :root defaults in animations.css
  • Enter/leave animations target the inner data-notivue-item wrapper; stack transform stays on <li>
  • Reposition uses --nv-transform-transition with a built-in fallback when unset
  • Harden handlers: ignore bubbled animationend, skip double-firing, handle animations that resolve to none
  • Reduced motion disables transform transitions and enter/leave animations as before

Keyboard navigation

User-facing setup (v3):

<NotivueKeyboard>
  <Notivue v-slot="item">
    <MyNotification :item="item" />
  </Notivue>
</NotivueKeyboard>

Changes:

  • Drop provide/inject; manage list item tabindex directly on the DOM
  • Tab and stream focus target [data-notivue-list-item] (<li>), not the inner wrapper
  • Candidate if the list item has focusable children or isCandidate(listItem) returns true (custom hook extends, does not replace, default detection)
  • isCandidate receives the same <li> as stream focus
  • Skip ariaLiveOnly entries via store lookup (no DOM probing)
  • Exclude tabindex="-1" elements from the focusable candidates selector
  • Remove default focus outline on notification containers; style :focus-visible on the list item or a child (for example .Notification)
  • Dismissing the last candidate focuses the previous one instead of leaving the stream
  • Leave announcement: "You left the notifications stream. Press Tab or Control + N to navigate it again."
  • renderAnnouncement defaults to false (screen-reader-only unless opted in)

Accessibility

  • Pause-on-focus: stream pauses when focused, resumes when focus leaves; focusout stays bound while keyboard stream mode is active
  • aria-label and stream focus on <li>; inner animation wrapper is not in the tab order
  • Built-in close button no longer forced to tabindex="-1"

CSS and notifications UI

Astro and Nuxt

  • Astro 5 playground (playground-astro/); import from notivue/astro with dedicated CSS paths
  • Generate TypeScript declarations for Astro subpath exports
  • Nuxt module targets Nuxt 4; vue declared as a peer dependency

Tooling and infra

  • Replace Vite lib build with tsdown (tsdown.config.ts, tarball + export verification)
  • Add oxfmt + oxlint two-pass format/lint pipeline (lint-staged, format:check)
  • Rename astro-playground/playground-astro/; register docs/ in workspace (separate notivuedocs repo, gitignored locally)
  • Workflow least-privilege permissions on tests.yml and publish.yml; grant contents: read to the reusable tests job on tag publish
  • pnpm.onlyBuiltDependencies for esbuild, cypress, sharp, @parcel/watcher
  • CodeRabbit config and AGENTS.md agent workflow guidance

Playground and demos

  • Migrate demos from push to notify; notify.global.ts middleware
  • Remove all useNotivueKeyboard / containersTabIndex / elementsTabIndex wiring
  • Shared notivue-stream.css focus styles targeting [data-notivue-list-item]
  • Nuxt 4 idioms (import.meta.client, cleaner config); version badge next to logo
  • Headless demo keeps explicit push usage to verify deprecated aliases

Tests

  • Pause-on-focus E2E (focus in, intra-stream moves, dismiss while focused)
  • Keyboard tests updated for list-item focus, leave message, last-candidate focus behavior
  • isCandidate Cypress coverage (extends default qualification; receives <li>; custom-only list items)
  • List item attribute assertions; fix Cypress chains when data-notivue-list-item is "0"
  • getListItemStackHeight helper re-exported for transition/stack specs
  • Config animation tests replaced with CSS variable assertions; reduced-motion specs hardened
  • Vitest coverage for notification option precedence and legacy promise* alias normalization
  • Upgrade Cypress 15, Vitest 3, Vue 3.5, Vite 7, vue-tsc 3

Docs and README

  • Expanded quick start: headless example, Nuxt/Astro sections, key exports table
  • Astro note: import from notivue/astro; Astro 6 not supported yet
  • JSDoc links point to the new docs site structure

Deprecated aliases

All deprecated items remain type-aliased and re-exported. No runtime warnings unless noted.

Category Deprecated Use instead
Imports push, usePush(), useNotify(), createPush notify, createNotify
useNotivueKeyboard() (no longer needed)
Methods notify.promise(), notify.load(), .resolve(), .reject() notify.loading(), .success(), .error()
Callbacks onAutoClear, onManualClear onTimedOut, onClear
Config animations, transition CSS variables
Props containersTabIndex (removed)
isTopAlign config.position.value.startsWith('top')
Components NotificationSwipe NotivueSwipe
Types Push, PushOptions, NotivueSlot, promise literals, etc. Notify, NotifyOptions, NotivueItem, loading literals, etc.

Full alias list is unchanged from v2 exports; grep deprecated in packages/notivue for the complete surface.

Test plan

  • pnpm build and tarball export verification
  • pnpm test:unit
  • Cypress component suite (152 specs, CI)
  • Manual smoke on Nuxt playground and Astro playground
  • CodeRabbit review threads triaged on this PR

Summary by CodeRabbit

  • New Features

    • Unified notify API (push kept as deprecated alias); new loading notification type; automatic focus management that better pauses/resumes timeouts; notify.promise/load kept as deprecated aliases.
  • Behavior Changes

    • Loading notifications treated as non-swipeable; close button hidden for loading items; global "no limit" now uses -1; keyboard leave announcement defaults to off.
  • Documentation

    • README and Nuxt/Astro guides expanded with updated examples.
  • Chores

    • Tooling updates and package bumped to v3.0.0; test/workflow adjustments.

smastrom and others added 30 commits March 24, 2026 17:22
* Core - Refactor createStore; Nuxt module compatibility for v4
* Pkg - Build notivue with tsdown; watch keeps dist for workspace consumers
* Pkg - Refresh devDependencies and exports; remove Vite lib config
* Root - pnpm 9, oxfmt, lint-staged; remove Prettier; ignore .cursor
* Playground - Nuxt 4, luxon optimizeDeps, Vite build options
* Tests - Cypress 15; Vite 7 for component testing with Astro/Vite toolchain
* Astro - Astro 5.18, integrations v5, vite ssr.noExternal for notivue

Co-authored-by: Cursor <cursoragent@cursor.com>
* CSS - Draw `--nv-tip-width` with a `::before` border instead of an inset box-shadow so radius and rounding stay clean (#78).

* CSS - Use full `border-radius` when a progress bar is present and `overflow: hidden` on the card so the bar and tip stay inside the rounded shape (#76).

Co-authored-by: Cursor <cursoragent@cursor.com>
* Mention Astro in the tagline; add Installation callout linking to full docs.

* Surface headless custom markup example outside a details block.

* Add Astro section with import/CSS paths and Astro 6 not supported note.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* Core - createNotify as primary API; push remains same-object alias.
* Notivue - useNotify, notifyAstro; types and store proxies use notify.
* Demo - README and playground config comments use notify for examples.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Notification - NotificationSwipe export and NotificationSwipeProps; NotivueSwipe remains deprecated alias.
* Tests, Demo, Astro playground - use NotificationSwipe in examples; Cypress CyNotificationSwipeProps.
* Pkg - exports manifest and README feature line document the alias.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Demo - Built-in/headless section titles; clearer instance, swipe, and queue copy; store messages.dynamic; button labels Dynamic, Friend request, Warning.
* Demo - Remove stray text in NavNotificationsThemes; UploadNotification uses isDynamic for the updating phase.
* Astro - Script, Vue, and React samples use Push dynamic and updated loading strings.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Headless Toast with scoped CSS, realistic copy, and notify wrapper.
* createNotivue and Nuxt module examples; installation and Astro callout formatting.
* Custom components as H3; NotificationSwipe with built-in Notification and custom Toast.
* Nuxt swipe snippet mirrors Vite.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove Polar; add PayPal hosted button and NOWPayments.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Pkg - Register playground-astro in workspace and dev:astro script.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* Playground - Rename global middleware to notify.global.ts.
* Playground - Keep explicit push and PushOptions usage in NavPushHeadless for alias checks.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ng item types

* Core - Add loading, loading-success, loading-error; normalize legacy promise* at enqueue

* Core - NotivueConfigUpdateParam; notify API with deprecated load/promise aliases

* Notifications - Themes, CSS, and icons for loading variants

* Astro, Nuxt, NotivueSwipe - Align with loading types and exports

Co-authored-by: Cursor <cursoragent@cursor.com>
* Tests - Update Notivue fixtures and push-method specs

* Tests - Extend update-config unit coverage

Co-authored-by: Cursor <cursoragent@cursor.com>
* Playground - Nav and custom notification examples

* Playground Astro - Sample components use notify

Co-authored-by: Cursor <cursoragent@cursor.com>
* Pkg - docs:dev, docs:build, docs:preview; include docs in pnpm workspace

* Pkg - oxfmt markdown tab width override

* .gitignore - Ignore docs directory

* README - Align root docs with notify API and v3

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…x isStreamPaused type

Replace isTopAlign usage with position.value.startsWith('top') across core
and playground. Add @deprecated JSDoc to useNotify, usePush, and astro
load/promise aliases. Change isStreamPaused return type to ComputedRef.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
global config was incorrectly overriding per-type defaults because it
was spread after the per-type slice. Swap the order so per-type entries
correctly take precedence over global ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…gnore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shared properties (title, message, duration, ariaLive, ariaRole) now
live in notifications.global. Per-type entries only declare what differs
from global (e.g. error → assertive/alert). This makes the
global → per-type → notify merge order work correctly: users can
update global.duration to change all types at once without per-type
defaults overriding it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keep NotivueSwipe as the primary component name matching the current
release. NotificationSwipe is retained as a deprecated alias.

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

The notification container element includes internal padding for the gap
between notifications, causing the browser's default focus outline to
render incorrectly. This moves the outline removal into the library's
base styles so users don't need to handle it manually.

Also updates keyboard navigation docs and JSDoc to clarify that Ctrl+N
can be used to both enter and leave the stream, fixes the leave message
default, and sets renderAnnouncement to false in the docs layout.

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

useFocusEvents now pauses/resumes timeouts on focusin/focusout like
useMouseEvents does for hover. It stays out of the way when
NotivueKeyboard is active (guarded by isStreamFocused).

Removes the containersTabIndex prop from Notivue — containers now
always render with tabindex="-1". NotivueKeyboard manages tabindex
directly on the DOM elements it tracks.

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

Major simplification of NotivueKeyboard:

- Removes containersTabIndex computed, candidateIds, and provide/inject
- Manages container tabindex directly on DOM elements
- Drops elementsTabIndex — inner elements are naturally focusable
- Adds isCandidate prop for custom candidate filtering
- Fixes last-candidate focus: dismissing the last notification now moves
  focus to the previous candidate instead of leaving the stream
- Deprecates useNotivueKeyboard() as a backwards-compatible no-op
- Deprecates TabIndexValue, ContainersTabIndexMap, NotivueKeyboardData

NotivueKeyboard is now a simple wrapper with no slot props. Users just
render focusable elements normally — no composable or tabindex wiring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removes containersTabIndex prop, v-slot destructuring, elementsTabIndex
bindings, and useNotivueKeyboard() usage from all consumers. Buttons
are now naturally focusable without explicit tabindex.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The focusableEls selector matched all non-disabled buttons regardless of
tabindex, causing elements intentionally excluded from keyboard navigation
(e.g. dismiss buttons with tabindex="-1") to be counted as focusable.
This made their containers qualify as candidates incorrectly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Updates leave message assertion to match new default
- Updates last-candidate action test to expect focus on previous candidate
- Adds config-pause-on-focus.cy.ts with tests for focus pause/resume,
  intra-stream focus moves, and dismiss-while-focused scenarios

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
smastrom and others added 6 commits May 29, 2026 13:29
Co-authored-by: Cursor <cursoragent@cursor.com>
* Pkg - Add oxlint with stylistic import and padding rules
* Pkg - Wire lint-staged and format scripts for oxfmt/prettier then oxlint --fix

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep v3 notification option precedence explicit while preserving legacy promise alias config during loading normalization.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Docs - Require explicit user approval before agent commits or pushes
* Docs - Remove extra custom funding links

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Warning

Ignoring CodeRabbit configuration file changes. For security, only the configuration from the base branch is applied for open source repositories.

📝 Walkthrough

<review_stack_artifact>

</review_stack_artifact>

✨ 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 dev

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/notivue/Notifications/icons/index.ts (1)

36-55: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve deprecated promise* icon keys in the default map.

This drops the alias path for custom icon overrides that still use promise, promise-resolve, or promise-reject. Notification.vue now reads canonical loading* keys at render time, so those deprecated overrides stop applying unless the map also mirrors them or gets normalized before lookup.

♻️ Minimal compatibility fix
 export const filledIcons: NotivueIcons = {
    [NType.SUCCESS]: raw(SuccessIcon),
    [NType.ERROR]: raw(ErrorIcon),
    [NType.INFO]: raw(InfoIcon),
    [NType.WARNING]: raw(ErrorIcon),
    [NType.LOADING]: raw(PromiseIcon),
    [NType.LOADING_SUCCESS]: raw(SuccessIcon),
    [NType.LOADING_ERROR]: raw(ErrorIcon),
+   [NType.PROMISE]: raw(PromiseIcon),
+   [NType.PROMISE_RESOLVE]: raw(SuccessIcon),
+   [NType.PROMISE_REJECT]: raw(ErrorIcon),
    close: raw(CloseIcon),
 }
 
 export const outlinedIcons: NotivueIcons = {
    [NType.SUCCESS]: raw(SuccessOutlineIcon),
    [NType.ERROR]: raw(ErrorOutlineIcon),
    [NType.INFO]: raw(InfoOutlineIcon),
    [NType.WARNING]: raw(ErrorOutlineIcon),
    [NType.LOADING]: raw(PromiseIcon),
    [NType.LOADING_SUCCESS]: raw(SuccessOutlineIcon),
    [NType.LOADING_ERROR]: raw(ErrorOutlineIcon),
+   [NType.PROMISE]: raw(PromiseIcon),
+   [NType.PROMISE_RESOLVE]: raw(SuccessOutlineIcon),
+   [NType.PROMISE_REJECT]: raw(ErrorOutlineIcon),
    close: raw(CloseIcon),
 }

Based on learnings: Protect public exports, types, CSS entrypoints, accessibility behavior, SSR compatibility, and backwards compatibility unless explicitly asked for a breaking change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/Notifications/icons/index.ts` around lines 36 - 55, The
filledIcons and outlinedIcons maps dropped deprecated alias keys used by
consumers; restore backward-compatible entries by adding 'promise' ->
NType.LOADING, 'promise-resolve' -> NType.LOADING_SUCCESS, and 'promise-reject'
-> NType.LOADING_ERROR mappings (using the same raw(...) values already used for
the loading* keys) in both filledIcons and outlinedIcons so existing custom icon
overrides that reference "promise*", "promise-resolve", or "promise-reject"
continue to work.
playground-astro/src/components/AstroComponent.astro (1)

53-58: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid stacking swap listeners across navigations.

In playground-astro/src/components/AstroComponent.astro the inline <script> calls document.addEventListener('astro:before-swap', removeListeners) and document.addEventListener('astro:after-swap', addListeners) (lines 57-58) on every script execution, but never unregisters them. With View Transitions, inline scripts can re-run during navigations, so these global handlers can accumulate and cause addListeners()/removeListeners() to run multiple times (and since handler functions are recreated per run, click handlers/notifications can duplicate). Guard the global listener registration (or remove existing handlers before re-adding).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@playground-astro/src/components/AstroComponent.astro` around lines 53 - 58,
The global View Transition handlers are being added on every script run causing
duplicate registrations; update the script around addListeners() and
removeListeners to avoid stacking by either keeping stable named handler
references and calling document.removeEventListener('astro:before-swap',
beforeSwapHandler) and document.removeEventListener('astro:after-swap',
afterSwapHandler) before adding them, or use a module-scoped boolean guard
(e.g., listenersRegistered) to only call
document.addEventListener('astro:before-swap', removeListeners) and
document.addEventListener('astro:after-swap', addListeners) once; ensure the
same function references (removeListeners/addListeners or stable wrappers) are
used for both addEventListener and removeEventListener so handlers can be
unregistered.
playground/components/nav/NavPushHeadless.vue (1)

6-73: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use notify/NotifyOptions in playground/components/nav/NavPushHeadless.vue

notivue exposes push and PushOptions as deprecated legacy aliases, but this playground file still imports/uses them (push.destroyAll, push.info, push.loading, push.success, and satisfies PushOptions<...>). Switch the import to notify/NotifyOptions and update the calls accordingly for API consistency with the canonical v3 surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@playground/components/nav/NavPushHeadless.vue` around lines 6 - 73, Replace
deprecated push/PushOptions usage with the v3 API: import notify and
NotifyOptions instead of push and PushOptions, then update all calls and types
that reference push (push.destroyAll, push.info, push.loading, push.success) to
use notify (notify.destroyAll, notify.info, notify.loading, notify.success) and
update the type assertion that uses "satisfies PushOptions<...>" to "satisfies
NotifyOptions<...>" while preserving the same payload types (e.g.,
FriendRequestNotificationProps, UploadNotificationProps,
SimpleNotificationProps) and other options (ariaRole, ariaLive, duration) so
behavior remains identical.
🧹 Nitpick comments (5)
packages/notivue/core/createStore.ts (1)

269-269: ⚡ Quick win

Remove leftover debug console.log statements.

console.log('Updating positions') here, plus console.log('Pausing timeouts') (Line 328) and console.log('Resuming timeouts') (Line 359), will spam every consumer's console on each reposition/pause/resume. Worth removing before the v3 release (unless the tsdown build is configured to strip console).

🧹 Proposed cleanup
-         console.log('Updating positions')
-
          const isReduced = this.isReducedMotion.value || isImmediate
         this.setStreamPause()
-
-        console.log('Pausing timeouts')
         this.setStreamPause(false)
-
-        console.log('Resuming timeouts')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/core/createStore.ts` at line 269, Remove the leftover
console.log calls that spam consumers: delete the console.log('Updating
positions'), console.log('Pausing timeouts'), and console.log('Resuming
timeouts') statements in createStore.ts; if you need persistent debug visibility
instead, replace them with a conditional debug/logging call using the project's
logger or a debug flag rather than raw console.log (search for the exact strings
"Updating positions", "Pausing timeouts", and "Resuming timeouts" to locate the
lines). Ensure no other stray console.log calls remain in the surrounding
functions.
packages/notivue/scripts/verify-tarball.sh (1)

16-17: ⚡ Quick win

Scan dist/astro.js in the tarball smoke test too.

dist/astro.js is now a shipped entrypoint, but this script still only checks dist/index.js for stripped debug output. A regression in the generated Astro bundle would slip through unchanged. Based on learnings: Protect public exports, types, CSS entrypoints, accessibility behavior, SSR compatibility, and backwards compatibility unless explicitly asked for a breaking change.

Suggested fix
-# Extract index.js for checking
-tar xzf "$tar_file" -C $temp_dir package/dist/index.js
-
-# Check if console.log exists in the extracted index.js
-if grep "console.log" $temp_dir/package/dist/index.js; then
-    echo "Error: console.log found in index.js"
-    rm -rf $temp_dir
-    exit 1
-fi
+# Extract built entrypoints for checking
+tar xzf "$tar_file" -C $temp_dir package/dist/index.js package/dist/astro.js
+
+for artifact in index.js astro.js; do
+    if grep "console.log" "$temp_dir/package/dist/$artifact"; then
+        echo "Error: console.log found in $artifact"
+        rm -rf $temp_dir
+        exit 1
+    fi
+done

Also applies to: 29-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/scripts/verify-tarball.sh` around lines 16 - 17, The tarball
verification script currently only scans "dist/index.js" for stripped debug
output; update the verify-tarball.sh check to also scan "dist/astro.js" (the new
shipped entrypoint) wherever the script builds the list of files to inspect (the
array or quoted list containing "dist/index.js"), and ensure the same scan/grep
logic used for "dist/index.js" is applied to "dist/astro.js" so regressions in
the Astro bundle are caught; apply the same addition for the secondary list of
files used later in the script (the block that includes
"dist/core/animations.css" and other dist entries).
package.json (1)

12-13: ⚡ Quick win

Keep format:check in sync with the Astro formatting path.

format still runs Prettier on Astro files, but format:check now skips that step entirely. That leaves playground-astro's .astro files outside the CI formatting check. Based on learnings: Use pnpm and the repo scripts: pnpm build, pnpm test, pnpm test:unit, pnpm format:check, pnpm dev, pnpm dev:astro.

Suggested fix
-      "format:check": "oxfmt --check . && oxlint .",
+      "format:check": "oxfmt --check . && pnpm -C playground-astro exec prettier --check \"src/**/*.astro\" && oxlint .",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 12 - 13, The format:check npm script currently
omits running Prettier on Astro files in playground-astro, causing CI to skip
those checks; update the "format:check" script (the package.json scripts named
"format" and "format:check") to run the same Prettier check used by "format" for
Astro files (use pnpm -C playground-astro exec prettier --check "src/**/*.astro"
or equivalent) so both scripts are kept in sync and Astro files are validated in
CI.
playground-astro/src/components/ReactComponent.tsx (1)

10-21: ⚡ Quick win

Prefer loading() / success() in the React example.

Line 11 and Line 17 still advertise deprecated aliases. Using the canonical loading handle here will keep the playground examples consistent across frameworks.

♻️ Proposed update
 function notifyDynamic() {
-   const notification = notify.promise({
+   const notification = notify.loading({
       title: 'Updating…',
       message: 'This dynamic notification is still updating.',
    })

    setTimeout(() => {
-      notification.resolve({
+      notification.success({
          title: 'React notification',
          message: 'Update finished — notification from React.',
       })
    }, 2000)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@playground-astro/src/components/ReactComponent.tsx` around lines 10 - 21, The
React example uses deprecated aliases notify.promise and notification.resolve;
update the notifyDynamic function to use the canonical handles instead: call
notify.loading(...) to create the in-progress notification (replacing
notify.promise) and later call notification.success(...) (replacing
notification.resolve) to mark completion; locate the notifyDynamic function and
the variable notification to make these two substitutions so the playground uses
the standard loading() and success() APIs.
playground-astro/src/components/AstroComponent.astro (1)

20-30: ⚡ Quick win

Use the canonical loading API in the Astro demo.

Line 21 and Line 27 still showcase the deprecated promise / resolve pair. Switching this example to notify.loading() and notification.success() keeps the v3 playground aligned with the public API you are introducing.

♻️ Proposed update
 function notifyDynamic() {
-   const notification = notify.promise({
+   const notification = notify.loading({
       title: 'Updating…',
       message: 'This dynamic notification is still updating.',
    })

    setTimeout(() => {
-      notification.resolve({
+      notification.success({
          title: 'Notification',
          message: 'Update finished — notification from a script tag.',
       })
    }, 2000)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@playground-astro/src/components/AstroComponent.astro` around lines 20 - 30,
The demo uses the deprecated notify.promise/notification.resolve pattern in
function notifyDynamic; update it to the canonical v3 API by calling
notify.loading(...) to create the loading notification and then call
notification.success(...) in the setTimeout callback (replace usages of
notify.promise and notification.resolve with notify.loading and
notification.success respectively), keeping the same title/message payloads and
the notification variable name so logic and messages remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/publish.yml:
- Around line 8-12: The workflow-level Permissions block currently sets an empty
permissions object which strips GITHUB_TOKEN rights and breaks reusable
workflows (the job named tests-workflow that uses
./.github/workflows/tests.yml); update the top-level permissions to grant the
minimum required token scopes (e.g., set permissions: contents: read) so actions
like actions/checkout in the reusable workflow can run, or remove the empty
permissions block entirely so the reusable workflow can use its own declared
permissions.

In @.gitignore:
- Line 17: The .gitignore currently contains an entry "docs/" which causes the
new docs package to be ignored; remove the "docs/" pattern from .gitignore (or
adjust it to only ignore specific generated artifacts) so the docs/ source tree
is tracked by Git, ensuring files under the docs package (the new docs/ package)
are not silently skipped.

In `@packages/notivue/Notivue/composables/useFocusEvents.ts`:
- Line 21: The computed currently removes root listeners as soon as
timeouts.isStreamFocused.value becomes true, which unbinds onFocusout and
prevents timeouts.resume() from being called; update the computed returned
listeners so that onFocusout remains bound even when
timeouts.isStreamFocused.value is true (e.g., return { onFocusin, onFocusout }
when not focused and { onFocusout } when focused) so onFocusout can always fire
and call timeouts.resume(); locate the computed in useFocusEvents.ts and adjust
its return shape accordingly (references: timeouts.isStreamFocused, onFocusin,
onFocusout, timeouts.resume()).

In `@packages/notivue/Notivue/composables/useNotivueStyles.ts`:
- Around line 38-43: itemContainer in useNotivueStyles.ts currently disables the
browser focus ring with outline: 'none', which removes the only guaranteed
keyboard-visible focus; restore a visible focus indicator by removing outline:
'none' or replacing it with an explicit focus-visible rule (e.g. add a focus or
:focus-visible style that applies a clear outline/box-shadow using CSS variables
like --nv-focus) so keyboard users see focus; update the itemContainer style
block (in useNotivueStyles.ts) to either omit outline or add a focus-visible
style and ensure it respects existing variables and pointerEvents.

In `@packages/notivue/NotivueKeyboard/NotivueKeyboardImpl.vue`:
- Around line 126-128: The current ternary in the isQualified computation
replaces the default qualification with props.isCandidate; change it to extend
qualification (i.e., qualification is true if there are focusable children OR
props.isCandidate(container) is true) by adjusting the logic that sets
isQualified (referencing isQualified, props.isCandidate, innerFocusableEls, and
container). After updating the logic, add a focused keyboard Cypress component
test covering the "focusable children + custom isCandidate" scenario to ensure
mixed-stream notifications remain reachable from keyboard navigation; update or
add tests in the main Cypress suite and corresponding unit tests if needed.

In `@packages/notivue/NotivueKeyboard/useNotivueKeyboard.ts`:
- Around line 5-13: The deprecated useNotivueKeyboard() stub must preserve prior
behavior by returning the injected keyboard state when present and falling back
to inert defaults only when no provider exists; update useNotivueKeyboard to
attempt to inject the existing Notivue keyboard provider (e.g., using Vue's
inject with the same injection key/symbol used by the provider such as
NotivueKeyboardSymbol or the provider name), and if the injected value exists
return its elementsTabIndex and containersTabIndex directly, otherwise return
the current defaults (elementsTabIndex: ref(-1), containersTabIndex: computed(()
=> ({}))); ensure injection is SSR-safe and that the function still exports the
NotivueKeyboardData shape.

In `@packages/notivue/package.json`:
- Line 37: The package.json for packages/notivue incorrectly sets "sideEffects":
false which can cause bundlers to tree-shake published CSS entrypoints (e.g.,
"./notifications.css", "./notification.css", "./animations.css"); change the
package metadata to mark the package as having side effects for those CSS files
by updating the "sideEffects" field to include the CSS globs or remove/set it to
true so bundlers keep the CSS imports intact—locate the sideEffects entry in
package.json of the notivue package and replace false with either true or an
array like ["*.css","./*.css"] to preserve the exported CSS entrypoints.

In `@packages/notivue/tsdown.config.ts`:
- Around line 8-13: The file uses createRequire(import.meta.url) to load
./shared/exports.js which is an ESM module and can cause ERR_REQUIRE_ESM;
replace the require call with an ESM import (e.g., top-level await
import('./shared/exports.js') or a dynamic import) and destructure the exported
symbols getFunctions, getObjects, getComponents from that module, preserving the
existing type annotations, so update the code in tsdown.config.ts to import
those functions via ESM rather than using createRequire/import.meta.url.

In `@playground/components/custom-notifications/SimpleNotification.vue`:
- Line 27: The dismiss button in SimpleNotification.vue is missing an explicit
type, causing it to act as a submit button when inside a form; update the
CloseButton <button> element that calls item.clear so it includes type="button"
to prevent accidental form submissions when the toast is embedded in a form.

In `@pnpm-workspace.yaml`:
- Around line 7-11: Replace the unsupported pnpm v10-only `allowBuilds` block
with the v9 mechanism `onlyBuiltDependencies`: locate the `allowBuilds` section
and rename it to `onlyBuiltDependencies`, keeping the same entries
(`@parcel/watcher`, `cypress`, `esbuild`, `sharp`) so pnpm 9.15.9 will whitelist
those packages' build scripts; alternatively note that upgrading pnpm to
>=10.26.0 would allow keeping `allowBuilds`/`approve-builds`.

In `@README.md`:
- Around line 228-230: The blockquote for the Astro note has an extra blank line
splitting the two lines (the line starting ":bulb: Import from
**`notivue/astro`**..." and the following "**Note:** Astro **6** is not
supported yet."), which triggers markdownlint MD028; remove the empty line so
both lines remain in one contiguous blockquote (i.e., collapse the blank line
between the two quoted lines) to satisfy MD028.

---

Outside diff comments:
In `@packages/notivue/Notifications/icons/index.ts`:
- Around line 36-55: The filledIcons and outlinedIcons maps dropped deprecated
alias keys used by consumers; restore backward-compatible entries by adding
'promise' -> NType.LOADING, 'promise-resolve' -> NType.LOADING_SUCCESS, and
'promise-reject' -> NType.LOADING_ERROR mappings (using the same raw(...) values
already used for the loading* keys) in both filledIcons and outlinedIcons so
existing custom icon overrides that reference "promise*", "promise-resolve", or
"promise-reject" continue to work.

In `@playground-astro/src/components/AstroComponent.astro`:
- Around line 53-58: The global View Transition handlers are being added on
every script run causing duplicate registrations; update the script around
addListeners() and removeListeners to avoid stacking by either keeping stable
named handler references and calling
document.removeEventListener('astro:before-swap', beforeSwapHandler) and
document.removeEventListener('astro:after-swap', afterSwapHandler) before adding
them, or use a module-scoped boolean guard (e.g., listenersRegistered) to only
call document.addEventListener('astro:before-swap', removeListeners) and
document.addEventListener('astro:after-swap', addListeners) once; ensure the
same function references (removeListeners/addListeners or stable wrappers) are
used for both addEventListener and removeEventListener so handlers can be
unregistered.

In `@playground/components/nav/NavPushHeadless.vue`:
- Around line 6-73: Replace deprecated push/PushOptions usage with the v3 API:
import notify and NotifyOptions instead of push and PushOptions, then update all
calls and types that reference push (push.destroyAll, push.info, push.loading,
push.success) to use notify (notify.destroyAll, notify.info, notify.loading,
notify.success) and update the type assertion that uses "satisfies
PushOptions<...>" to "satisfies NotifyOptions<...>" while preserving the same
payload types (e.g., FriendRequestNotificationProps, UploadNotificationProps,
SimpleNotificationProps) and other options (ariaRole, ariaLive, duration) so
behavior remains identical.

---

Nitpick comments:
In `@package.json`:
- Around line 12-13: The format:check npm script currently omits running
Prettier on Astro files in playground-astro, causing CI to skip those checks;
update the "format:check" script (the package.json scripts named "format" and
"format:check") to run the same Prettier check used by "format" for Astro files
(use pnpm -C playground-astro exec prettier --check "src/**/*.astro" or
equivalent) so both scripts are kept in sync and Astro files are validated in
CI.

In `@packages/notivue/core/createStore.ts`:
- Line 269: Remove the leftover console.log calls that spam consumers: delete
the console.log('Updating positions'), console.log('Pausing timeouts'), and
console.log('Resuming timeouts') statements in createStore.ts; if you need
persistent debug visibility instead, replace them with a conditional
debug/logging call using the project's logger or a debug flag rather than raw
console.log (search for the exact strings "Updating positions", "Pausing
timeouts", and "Resuming timeouts" to locate the lines). Ensure no other stray
console.log calls remain in the surrounding functions.

In `@packages/notivue/scripts/verify-tarball.sh`:
- Around line 16-17: The tarball verification script currently only scans
"dist/index.js" for stripped debug output; update the verify-tarball.sh check to
also scan "dist/astro.js" (the new shipped entrypoint) wherever the script
builds the list of files to inspect (the array or quoted list containing
"dist/index.js"), and ensure the same scan/grep logic used for "dist/index.js"
is applied to "dist/astro.js" so regressions in the Astro bundle are caught;
apply the same addition for the secondary list of files used later in the script
(the block that includes "dist/core/animations.css" and other dist entries).

In `@playground-astro/src/components/AstroComponent.astro`:
- Around line 20-30: The demo uses the deprecated
notify.promise/notification.resolve pattern in function notifyDynamic; update it
to the canonical v3 API by calling notify.loading(...) to create the loading
notification and then call notification.success(...) in the setTimeout callback
(replace usages of notify.promise and notification.resolve with notify.loading
and notification.success respectively), keeping the same title/message payloads
and the notification variable name so logic and messages remain unchanged.

In `@playground-astro/src/components/ReactComponent.tsx`:
- Around line 10-21: The React example uses deprecated aliases notify.promise
and notification.resolve; update the notifyDynamic function to use the canonical
handles instead: call notify.loading(...) to create the in-progress notification
(replacing notify.promise) and later call notification.success(...) (replacing
notification.resolve) to mark completion; locate the notifyDynamic function and
the variable notification to make these two substitutions so the playground uses
the standard loading() and success() APIs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b1f01f64-1c63-4ff1-a28f-3191250199ee

📥 Commits

Reviewing files that changed from the base of the PR and between 5d5b8e8 and 4e9c170.

⛔ Files ignored due to path filters (1)
  • playground-astro/public/favicon.svg is excluded by !**/*.svg
📒 Files selected for processing (136)
  • .coderabbit.yaml
  • .cursorignore
  • .github/FUNDING.yml
  • .github/workflows/publish.yml
  • .github/workflows/tests.yml
  • .gitignore
  • .oxfmtrc.json
  • .oxlintrc.json
  • AGENTS.md
  • CODE_OF_CONDUCT.md
  • README.md
  • astro-playground/package.json
  • astro-playground/src/components/ReactComponent.tsx
  • astro-playground/src/components/VueComponent.vue
  • oxlint-plugins.mjs
  • package.json
  • packages/notivue/Notifications/Notification.vue
  • packages/notivue/Notifications/constants.ts
  • packages/notivue/Notifications/icons/index.ts
  • packages/notivue/Notifications/notifications-progress.css
  • packages/notivue/Notifications/notifications.css
  • packages/notivue/Notifications/themes.ts
  • packages/notivue/Notifications/types.ts
  • packages/notivue/Notivue/AriaLive.vue
  • packages/notivue/Notivue/Notivue.vue
  • packages/notivue/Notivue/NotivueImpl.vue
  • packages/notivue/Notivue/composables/useFocusEvents.ts
  • packages/notivue/Notivue/composables/useMouseEvents.ts
  • packages/notivue/Notivue/composables/useNotivueStyles.ts
  • packages/notivue/Notivue/composables/useReducedMotion.ts
  • packages/notivue/Notivue/composables/useSizes.ts
  • packages/notivue/Notivue/types.ts
  • packages/notivue/NotivueKeyboard/NotivueKeyboard.vue
  • packages/notivue/NotivueKeyboard/NotivueKeyboardImpl.vue
  • packages/notivue/NotivueKeyboard/constants.ts
  • packages/notivue/NotivueKeyboard/types.ts
  • packages/notivue/NotivueKeyboard/useNotivueKeyboard.ts
  • packages/notivue/NotivueSwipe/NotivueSwipe.vue
  • packages/notivue/NotivueSwipe/types.ts
  • packages/notivue/astro/Notivue.vue
  • packages/notivue/astro/createNotivue.ts
  • packages/notivue/astro/push.ts
  • packages/notivue/astro/types.ts
  • packages/notivue/core/constants.ts
  • packages/notivue/core/createInstance.ts
  • packages/notivue/core/createNotify.ts
  • packages/notivue/core/createNotivue.ts
  • packages/notivue/core/createPush.ts
  • packages/notivue/core/createStore.ts
  • packages/notivue/core/createStoreWatchers.ts
  • packages/notivue/core/symbols.ts
  • packages/notivue/core/types.ts
  • packages/notivue/core/useStore.ts
  • packages/notivue/core/utils.ts
  • packages/notivue/index.ts
  • packages/notivue/nuxt/README.md
  • packages/notivue/nuxt/module.cjs
  • packages/notivue/nuxt/module.d.ts
  • packages/notivue/nuxt/module.json
  • packages/notivue/nuxt/module.mjs
  • packages/notivue/package.json
  • packages/notivue/scripts/verify-exports.js
  • packages/notivue/scripts/verify-tarball.sh
  • packages/notivue/shared/exports.js
  • packages/notivue/tsconfig.json
  • packages/notivue/tsdown.config.ts
  • packages/notivue/vite.config.ts
  • playground-astro/.gitignore
  • playground-astro/.prettierrc
  • playground-astro/astro.config.mjs
  • playground-astro/package.json
  • playground-astro/src/components/AstroComponent.astro
  • playground-astro/src/components/Notivue.vue
  • playground-astro/src/components/ReactComponent.tsx
  • playground-astro/src/components/VueComponent.vue
  • playground-astro/src/env.d.ts
  • playground-astro/src/layouts/Layout.astro
  • playground-astro/src/pages/_app.ts
  • playground-astro/src/pages/about.astro
  • playground-astro/src/pages/index.astro
  • playground-astro/src/styles/reset.css
  • playground-astro/tsconfig.json
  • playground/app.vue
  • playground/components/custom-notifications/FriendRequestNotification.vue
  • playground/components/custom-notifications/SimpleNotification.vue
  • playground/components/custom-notifications/UploadNotification.vue
  • playground/components/nav/Nav.vue
  • playground/components/nav/NavActions.vue
  • playground/components/nav/NavNotificationsCustomization.vue
  • playground/components/nav/NavNotificationsThemes.vue
  • playground/components/nav/NavNotivueConfig.vue
  • playground/components/nav/NavPushBuiltIn.vue
  • playground/components/nav/NavPushHeadless.vue
  • playground/components/shared/Background.server.vue
  • playground/components/shared/QueueCount.vue
  • playground/middleware/notify.global.ts
  • playground/nuxt.config.ts
  • playground/package.json
  • playground/utils/head.ts
  • playground/utils/misc.ts
  • playground/utils/store.ts
  • pnpm-workspace.yaml
  • tests/Notifications/elements.cy.ts
  • tests/Notifications/themes.cy.ts
  • tests/Notivue/components/Notivue.vue
  • tests/Notivue/config-enqueue.cy.ts
  • tests/Notivue/config-limit.cy.ts
  • tests/Notivue/config-pause-on-focus.cy.ts
  • tests/Notivue/config-pause-on-hover.cy.ts
  • tests/Notivue/config-pause-on-touch.cy.ts
  • tests/Notivue/push-methods.cy.ts
  • tests/Notivue/slot-custom-push-options.cy.ts
  • tests/Notivue/slot-default-options.cy.ts
  • tests/Notivue/slot-global-options.cy.ts
  • tests/Notivue/slot-internal-properties.cy.ts
  • tests/NotivueKeyboard/actions.cy.ts
  • tests/NotivueKeyboard/components/Candidate.vue
  • tests/NotivueKeyboard/components/Notivue.vue
  • tests/NotivueKeyboard/entering-stream.cy.ts
  • tests/NotivueKeyboard/leaving-stream.cy.ts
  • tests/NotivueKeyboard/props.cy.ts
  • tests/NotivueKeyboard/queue.cy.ts
  • tests/NotivueSwipe/clear.cy.ts
  • tests/NotivueSwipe/components/Notivue.vue
  • tests/NotivueSwipe/debounce.cy.ts
  • tests/config/merge-notification-options.test.ts
  • tests/config/update-config.test.ts
  • tests/cypress.config.ts
  • tests/cypress/support/commands-keyboard.ts
  • tests/cypress/support/commands-notifications.ts
  • tests/cypress/support/commands-notivue.ts
  • tests/cypress/support/commands-swipe.ts
  • tests/cypress/support/component.ts
  • tests/package.json
  • tests/tsconfig.json
  • tests/vite.config.mts
💤 Files with no reviewable changes (16)
  • astro-playground/src/components/ReactComponent.tsx
  • packages/notivue/core/createPush.ts
  • astro-playground/package.json
  • astro-playground/src/components/VueComponent.vue
  • tests/Notivue/config-pause-on-hover.cy.ts
  • packages/notivue/vite.config.ts
  • tests/NotivueKeyboard/leaving-stream.cy.ts
  • playground-astro/.prettierrc
  • playground/utils/head.ts
  • packages/notivue/Notifications/notifications-progress.css
  • tests/cypress/support/component.ts
  • .github/FUNDING.yml
  • tests/NotivueKeyboard/entering-stream.cy.ts
  • tests/NotivueKeyboard/queue.cy.ts
  • playground/components/nav/NavNotificationsThemes.vue
  • tests/Notivue/config-pause-on-touch.cy.ts

Comment thread .github/workflows/publish.yml
Comment thread .gitignore
Comment thread packages/notivue/Notivue/composables/useFocusEvents.ts Outdated
Comment thread packages/notivue/Notivue/composables/useNotivueStyles.ts
Comment thread packages/notivue/NotivueKeyboard/NotivueKeyboardImpl.vue Outdated
Comment thread packages/notivue/package.json
Comment thread packages/notivue/tsdown.config.ts
Comment thread playground/components/custom-notifications/SimpleNotification.vue Outdated
Comment thread pnpm-workspace.yaml Outdated
Comment thread README.md
* Core, Tests - Replace motion config with CSS variables

Drop animations and transition from NotivueConfig. Apply enter, leave,
clearAll, and reposition timing via MOTION_VARS_CSS inline styles and
:root defaults in animations.css.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Tests - Fix reduced-motion specs for instant dismiss

Assert no motion CSS vars are applied and notifications dismiss
immediately without waiting for ol or container nodes that reduced
motion removes on clear.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Core, Tests - Harden motion CSS variable handling

Guard animationend handlers against bubbled child animations, handle CSS-variable animations that resolve to none, and assert custom animation variables through computed styles.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Core - Rename default motion keyframes

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 29, 2026

Copy link
Copy Markdown

Deploying notivue with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4718230
Status: ✅  Deploy successful!
Preview URL: https://4ba32f91.notivue.pages.dev
Branch Preview URL: https://dev.notivue.pages.dev

View logs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/notivue/core/createStore.ts (1)

293-293: ⚡ Quick win

Remove leftover console.log debug statements from shipped library code.

updatePositions logs on every reposition (very noisy), and pause/resume log on each stream transition. These are debug artifacts that should not ship.

🧹 Remove debug logs
-      updatePositions({ isImmediate = false } = {}) {
-         console.log('Updating positions')
-
+      updatePositions({ isImmediate = false } = {}) {
         const isReduced = this.isReducedMotion.value || isImmediate
         if (items.length === 0 || this.isStreamPaused.value) return

-         console.log('Pausing timeouts')
-
         this.setStreamPause()
         if (items.length === 0 || !this.isStreamPaused.value) return

-         console.log('Resuming timeouts')
-
         this.setStreamPause(false)

Also applies to: 351-351, 382-382

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/core/createStore.ts` at line 293, Remove the leftover
console.log debug statements from the exported functions updatePositions, pause,
and resume in createStore.ts: delete the console.log calls (e.g., "Updating
positions" and any logs in pause/resume) so the library no longer emits noisy
runtime logs; if you need retainable diagnostics, replace them with a
configurable logger or a debug/trace-level logger used elsewhere in the codebase
(rather than console.log) and ensure no direct console.* calls remain in these
functions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/notivue/core/createStore.ts`:
- Line 293: Remove the leftover console.log debug statements from the exported
functions updatePositions, pause, and resume in createStore.ts: delete the
console.log calls (e.g., "Updating positions" and any logs in pause/resume) so
the library no longer emits noisy runtime logs; if you need retainable
diagnostics, replace them with a configurable logger or a debug/trace-level
logger used elsewhere in the codebase (rather than console.log) and ensure no
direct console.* calls remain in these functions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 678b7e4c-79ed-4083-8a20-18e30c369003

📥 Commits

Reviewing files that changed from the base of the PR and between 4e9c170 and fab223f.

📒 Files selected for processing (9)
  • packages/notivue/core/animations.css
  • packages/notivue/core/constants.ts
  • packages/notivue/core/createStore.ts
  • packages/notivue/core/types.ts
  • tests/Notivue/components/Notivue.vue
  • tests/Notivue/config-animations.cy.ts
  • tests/Notivue/prefers-reduced-motion.cy.ts
  • tests/config/update-config.test.ts
  • tests/cypress/support/commands-notivue.ts
💤 Files with no reviewable changes (1)
  • tests/config/update-config.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/notivue/core/types.ts

smastrom and others added 9 commits May 29, 2026 16:26
* Notivue - Keep focusout bound while keyboard stream is focused
* NotivueKeyboard - Extend isCandidate instead of replacing default qualification
* Tests - Add isCandidate Cypress coverage
* Pkg - Move build allowlist to pnpm.onlyBuiltDependencies
* CI - Grant contents read to publish tests-workflow job
* Playground - Add type=button to SimpleNotification dismiss
* Docs - Fix Astro blockquote in README

Co-authored-by: Cursor <cursoragent@cursor.com>
The Cypress wrapper accepted isCandidate but never passed it to
NotivueKeyboard, so the custom-only qualification spec could not pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
Apply --nv-gap as margin on itemContainer so focus outlines hug the
notification box. Keep margin-bottom and margin-block-end for support.

Co-authored-by: Cursor <cursoragent@cursor.com>
…cus, and stacking

* Notivue - Apply --nv-gap as block-end margin on list items; max-content rows with position-aware horizontal placement; keep --nv-root-x-align on justifyContent
* Notivue - Put tabindex and aria-label on li; item container is not focusable
* NotivueKeyboard - Tab and stream focus target data-notivue-item instead of containers
* Core - getListItemStackHeight for stack transforms including gap margin; remove debug logs
* Playground - Shared stream focus CSS; center on mobile via config.update; button focus-visible styles
* Tests - List item attributes, stack height helper, keyboard focus assertions
* Agents - Stop for user review before commit unless explicitly requested

Co-authored-by: Cursor <cursoragent@cursor.com>
* Tests - Assert aria-label on li; fix Cypress chains when data-notivue-item is "0"
* Notivue - Omit tabindex on ariaLiveOnly list items
* NotivueKeyboard - Pass container to isCandidate for backwards compatibility
* Tests - Re-export getListItemStackHeight from core utils

Co-authored-by: Cursor <cursoragent@cursor.com>
* Notivue - Remove --nv-root-x-align from list item styles; horizontal placement from position only
* Playground - Center on mobile via VueUse useMediaQuery and config.update
* Agents - Document stream layout, focus on li, and config-driven alignment

Co-authored-by: Cursor <cursoragent@cursor.com>
* Agents - Run gh pr view and refresh title/body when commits change scope or test plan

Co-authored-by: Cursor <cursoragent@cursor.com>
…ign isCandidate

* Notivue - Use data-notivue-list-item on li and data-notivue-item on the animation wrapper; drop data-notivue-container
* Core - Track animation nodes via elements.itemContainers refs instead of querySelector
* NotivueKeyboard - Pass list items to isCandidate; skip ariaLiveOnly entries via store lookup
* Tests, Playground, Agents - Update selectors, assertions, and focus CSS

Co-authored-by: Cursor <cursoragent@cursor.com>
* Playground - Drop useMediaQuery position override and nav switch
* Playground - Remove unused @vueuse/core dependency

Co-authored-by: Cursor <cursoragent@cursor.com>
@smastrom

Copy link
Copy Markdown
Owner Author

@CodeRabbit full review

Added by Cursor Agent

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

@smastrom Sure, I'll kick off a full review of PR #86.

✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/Notivue/accessibility.cy.ts (1)

18-20: ⚡ Quick win

Use the stable list-item selector in these aria-label assertions.

.get('li') is broader than the new contract and can pass against unrelated list markup. Prefer asserting on [data-notivue-list-item] so the test still proves the label lives on the stream-focus element.

♻️ Suggested update
-        .get('li')
+        .get('[data-notivue-list-item]')
          .should('have.attr', 'aria-label', 'This is a message')
-        .get('li')
+        .get('[data-notivue-list-item]')
          .should('have.attr', 'aria-label', 'This is a title: This is a message')

As per coding guidelines: Stream focus and aria-label belong on the <li>; [data-notivue-item] is not focusable.

Also applies to: 32-34

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Notivue/accessibility.cy.ts` around lines 18 - 20, Replace the broad li
selector used in the aria-label assertions with the stable list-item data
attribute: change occurrences of .get('li') that are followed by
.should('have.attr', 'aria-label', 'This is a message') to
.get('[data-notivue-list-item]') so the test asserts the aria-label on the
stream-focus list element; update both the occurrence around the
clickRandomStatic() assertion and the similar assertion at lines 32-34 to use
[data-notivue-list-item].
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/Notivue/accessibility.cy.ts`:
- Around line 18-20: Replace the broad li selector used in the aria-label
assertions with the stable list-item data attribute: change occurrences of
.get('li') that are followed by .should('have.attr', 'aria-label', 'This is a
message') to .get('[data-notivue-list-item]') so the test asserts the aria-label
on the stream-focus list element; update both the occurrence around the
clickRandomStatic() assertion and the similar assertion at lines 32-34 to use
[data-notivue-list-item].

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c984d679-3c2a-4637-a2af-6f43b0c68374

📥 Commits

Reviewing files that changed from the base of the PR and between 4718230 and d2ad176.

📒 Files selected for processing (25)
  • AGENTS.md
  • packages/notivue/Notivue/NotivueImpl.vue
  • packages/notivue/Notivue/composables/useNotivueStyles.ts
  • packages/notivue/Notivue/composables/useResizeListObserver.ts
  • packages/notivue/NotivueKeyboard/NotivueKeyboardImpl.vue
  • packages/notivue/NotivueKeyboard/types.ts
  • packages/notivue/core/createStore.ts
  • packages/notivue/core/utils.ts
  • playground/app.vue
  • playground/assets/notivue-stream.css
  • playground/components/custom-notifications/FriendRequestNotification.vue
  • playground/components/custom-notifications/SimpleNotification.vue
  • playground/components/custom-notifications/UploadNotification.vue
  • playground/components/nav/NavNotivuePosition.vue
  • playground/nuxt.config.ts
  • playground/utils/store.ts
  • tests/Notivue/accessibility.cy.ts
  • tests/Notivue/attributes.cy.ts
  • tests/Notivue/prefers-reduced-motion.cy.ts
  • tests/Notivue/transitions.cy.ts
  • tests/NotivueKeyboard/actions.cy.ts
  • tests/NotivueKeyboard/entering-stream.cy.ts
  • tests/NotivueKeyboard/props.cy.ts
  • tests/NotivueKeyboard/queue.cy.ts
  • tests/cypress/support/utils.ts
💤 Files with no reviewable changes (4)
  • playground/components/nav/NavNotivuePosition.vue
  • packages/notivue/Notivue/composables/useResizeListObserver.ts
  • playground/components/custom-notifications/FriendRequestNotification.vue
  • playground/utils/store.ts
✅ Files skipped from review due to trivial changes (1)
  • playground/assets/notivue-stream.css
🚧 Files skipped from review as they are similar to previous changes (7)
  • playground/components/custom-notifications/UploadNotification.vue
  • tests/NotivueKeyboard/props.cy.ts
  • tests/Notivue/prefers-reduced-motion.cy.ts
  • playground/app.vue
  • packages/notivue/NotivueKeyboard/types.ts
  • packages/notivue/core/utils.ts
  • packages/notivue/core/createStore.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (5)
packages/notivue/astro/createNotivue.ts (1)

3-3: ⚡ Quick win

Use a type-only import for NotivueConfig.

packages/notivue/astro/createNotivue.ts imports NotivueConfig as a value, but it’s only used in the type of pluginConfig (no runtime usage). Align with packages/notivue/core/createNotivue.ts’s existing import type pattern to avoid an unnecessary runtime import.

♻️ Proposed change
-import { NotivueConfig } from 'notivue'
+import type { NotivueConfig } from 'notivue'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/astro/createNotivue.ts` at line 3, The import of
NotivueConfig is only used as a type for pluginConfig, so change the runtime
import to a type-only import: replace the current import of NotivueConfig with
an "import type { NotivueConfig } from 'notivue'" at the top of createNotivue.ts
and keep pluginConfig's typing unchanged so there is no unnecessary runtime
import of NotivueConfig.
packages/notivue/core/types.ts (1)

197-203: ⚡ Quick win

Mark resolve / reject as @deprecated for consistency.

The doc comment states resolve / reject are aliases of success / error, and the PR replaces them, yet they are not tagged @deprecated like every other alias in this file (including load / promise in Notify). Tagging them surfaces deprecation hints in editors.

♻️ Proposed change
 export interface NotifyLoadingReturn {
    success: NotifyPromiseReturnMethod
    error: NotifyPromiseReturnMethod
+   /** `@deprecated` Use `success`. */
    resolve: NotifyPromiseReturnMethod
+   /** `@deprecated` Use `error`. */
    reject: NotifyPromiseReturnMethod
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/core/types.ts` around lines 197 - 203, The
NotifyLoadingReturn interface currently documents `resolve` and `reject` as
aliases of `success`/`error` but lacks deprecation tags; update the JSDoc for
the `NotifyLoadingReturn` interface to mark the `resolve` and `reject` members
with `@deprecated` (same pattern used for other aliases like `load`/`promise`)
so editors show deprecation warnings while keeping `success` and `error` as the
primary methods.
packages/notivue/core/createStore.ts (1)

21-28: ⚡ Quick win

Merge the duplicate ./utils imports.

Lines 21-27 and Line 28 both import from ./utils. Consolidate into a single statement to avoid a potential no-duplicate-imports lint failure under oxlint (run via format:check).

♻️ Proposed consolidation
 import {
    createConfigRefs,
    mergeDeep,
    mergeNotificationOptions as mergeOptions,
    toRawConfig,
    toCanonicalNotificationType,
+   isStatic,
+   getSlotItem,
+   isUnlimited,
+   getListItemStackHeight,
 } from './utils'
-import { isStatic, getSlotItem, isUnlimited, getListItemStackHeight } from './utils'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/core/createStore.ts` around lines 21 - 28, There are
duplicate imports from './utils' — consolidate them into a single import
statement that includes all used symbols (createConfigRefs, mergeDeep,
mergeNotificationOptions as mergeOptions, toRawConfig,
toCanonicalNotificationType, isStatic, getSlotItem, isUnlimited,
getListItemStackHeight) to satisfy the no-duplicate-imports lint rule and avoid
oxlint failures; update the import block so every referenced symbol is imported
exactly once from './utils'.
playground-astro/src/components/AstroComponent.astro (1)

20-32: 💤 Low value

Update playground sample to use notify.loading() instead of deprecated notify.promise()
notify.promise(...) and .resolve(...) still work, but they’re explicitly marked as @deprecated aliases of notify.loading(...) and .success(...) (and reject aliases .error()), so the sample should use the non-deprecated API.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@playground-astro/src/components/AstroComponent.astro` around lines 20 - 32,
The sample uses the deprecated notify.promise/resolve API inside function
notifyDynamic; update it to use notify.loading(...) instead of
notify.promise(...) and call notification.success(...) instead of
notification.resolve(...). Locate the notifyDynamic function and replace the
notify.promise call with notify.loading (preserving the same title/message
object) and replace the notification.resolve invocation in the setTimeout
callback with notification.success (if you later handle errors replace
reject().error with notification.error). Ensure behavior/timing remains
unchanged.
packages/notivue/index.ts (1)

1-2: ⚡ Quick win

Mark push/pushAstro deprecated for IDE surfacing.

Per the PR, notify/notifyAstro replace push/pushAstro as retained deprecated aliases. Unlike useNotify/usePush (Lines 12-13), these aliases carry no @deprecated JSDoc, so consumers won't see the deprecation hint. A single export statement can't deprecate only one name, so split them.

♻️ Split exports to annotate the alias
-export { notify, push } from '`@/core/createNotify`'
-export { notify as notifyAstro, push as pushAstro } from './astro/push'
+export { notify } from '`@/core/createNotify`'
+/** `@deprecated` Use `notify` instead of `push`. */
+export { push } from '`@/core/createNotify`'
+export { notify as notifyAstro } from './astro/push'
+/** `@deprecated` Use `notifyAstro` instead of `pushAstro`. */
+export { push as pushAstro } from './astro/push'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/index.ts` around lines 1 - 2, The current combined export
prevents marking the alias names as deprecated in IDEs; split the grouped
exports so you can add JSDoc `@deprecated` to the alias names. Specifically, keep
exporting notify and notifyAstro normally from createNotify and ./astro/push,
but re-export push and pushAstro in separate export statements that include a
JSDoc `@deprecated` comment for push and pushAstro (referencing the exported
symbols push, pushAstro, notify, notifyAstro) so editors surface the deprecation
hint. Ensure the original functionality/exports remain unchanged while only
annotating the alias exports as deprecated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.cursorignore:
- Around line 1-2: The two lines use negation-only patterns ('!docs/' and
'!.claude/') which do nothing without a preceding ignore; either remove the
leading '!' to actually ignore these directories (change to 'docs/' and
'.claude/') or add a preceding broad ignore that would match them (e.g., a rule
that ignores parent paths or a glob like '*' or 'docs/**') so the negation can
re-include them—update the .cursorignore accordingly to reflect the intended
behavior.

In `@packages/notivue/NotivueKeyboard/useNotivueKeyboard.ts`:
- Line 7: The deprecation comment in the useNotivueKeyboard composable uses an
em-dash; update the comment text in useNotivueKeyboard.ts to replace the em-dash
with either a hyphen or split into two sentences (e.g., "This composable is no
longer needed - remove it from your code." or "This composable is no longer
needed. Remove it from your code."), ensuring the file's top comment/JS Doc
around the useNotivueKeyboard export reflects the new punctuation.

In `@packages/notivue/nuxt/README.md`:
- Line 37: The markdown line with "NotivueSwipe (alias `NotificationSwipe`),
NotivueKeyboard, all optional and customizable" has mismatched/escaped
underscores causing broken emphasis; update the emphasis so the whole
description is wrapped in a single italic span (or remove the stray backslash)
and ensure inner identifiers stay inline code where needed—fix the line that
mentions NotivueSwipe / `NotificationSwipe` and NotivueKeyboard so the
surrounding _..._ includes the full phrase and no trailing `\_` remains.

In `@pnpm-workspace.yaml`:
- Around line 5-6: The pnpm workspace listing includes a stale entry 'docs' that
has no package.json; open pnpm-workspace.yaml and remove the 'docs' entry or
replace it with the correct workspace folder that actually contains a
package.json (e.g., update 'docs' -> '<actual-docs-folder>' if you have a
renamed docs package), leaving 'playground-astro' intact; ensure after the
change you can run pnpm -w list or pnpm -w install to verify the workspace
packages resolve correctly.

In `@README.md`:
- Line 33: Two instances in README.md (the sentence starting "Beyond this quick
start — Nuxt/Astro setup, **`notify`** / callbacks, stream config, built-in
styling, headless mode, full API — lives in the [documentation]..." and the one
at line 114) use em-dashes; replace each em-dash with the repo-preferred
punctuation (e.g., a hyphen, comma, colon, or split into separate sentences) so
the phrasing reads correctly (for example: "Beyond this quick start: Nuxt/Astro
setup, `notify` / callbacks, stream config..." or split into two sentences) and
ensure the `notify` / callbacks fragment and documentation link remain intact.

---

Nitpick comments:
In `@packages/notivue/astro/createNotivue.ts`:
- Line 3: The import of NotivueConfig is only used as a type for pluginConfig,
so change the runtime import to a type-only import: replace the current import
of NotivueConfig with an "import type { NotivueConfig } from 'notivue'" at the
top of createNotivue.ts and keep pluginConfig's typing unchanged so there is no
unnecessary runtime import of NotivueConfig.

In `@packages/notivue/core/createStore.ts`:
- Around line 21-28: There are duplicate imports from './utils' — consolidate
them into a single import statement that includes all used symbols
(createConfigRefs, mergeDeep, mergeNotificationOptions as mergeOptions,
toRawConfig, toCanonicalNotificationType, isStatic, getSlotItem, isUnlimited,
getListItemStackHeight) to satisfy the no-duplicate-imports lint rule and avoid
oxlint failures; update the import block so every referenced symbol is imported
exactly once from './utils'.

In `@packages/notivue/core/types.ts`:
- Around line 197-203: The NotifyLoadingReturn interface currently documents
`resolve` and `reject` as aliases of `success`/`error` but lacks deprecation
tags; update the JSDoc for the `NotifyLoadingReturn` interface to mark the
`resolve` and `reject` members with `@deprecated` (same pattern used for other
aliases like `load`/`promise`) so editors show deprecation warnings while
keeping `success` and `error` as the primary methods.

In `@packages/notivue/index.ts`:
- Around line 1-2: The current combined export prevents marking the alias names
as deprecated in IDEs; split the grouped exports so you can add JSDoc
`@deprecated` to the alias names. Specifically, keep exporting notify and
notifyAstro normally from createNotify and ./astro/push, but re-export push and
pushAstro in separate export statements that include a JSDoc `@deprecated` comment
for push and pushAstro (referencing the exported symbols push, pushAstro,
notify, notifyAstro) so editors surface the deprecation hint. Ensure the
original functionality/exports remain unchanged while only annotating the alias
exports as deprecated.

In `@playground-astro/src/components/AstroComponent.astro`:
- Around line 20-32: The sample uses the deprecated notify.promise/resolve API
inside function notifyDynamic; update it to use notify.loading(...) instead of
notify.promise(...) and call notification.success(...) instead of
notification.resolve(...). Locate the notifyDynamic function and replace the
notify.promise call with notify.loading (preserving the same title/message
object) and replace the notification.resolve invocation in the setTimeout
callback with notification.success (if you later handle errors replace
reject().error with notification.error). Ensure behavior/timing remains
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 60038d0b-ecf4-4a88-8842-28c2aed7dccd

📥 Commits

Reviewing files that changed from the base of the PR and between 5d5b8e8 and d2ad176.

⛔ Files ignored due to path filters (1)
  • playground-astro/public/favicon.svg is excluded by !**/*.svg
📒 Files selected for processing (146)
  • .coderabbit.yaml
  • .cursorignore
  • .github/FUNDING.yml
  • .github/workflows/publish.yml
  • .github/workflows/tests.yml
  • .gitignore
  • .oxfmtrc.json
  • .oxlintrc.json
  • AGENTS.md
  • CODE_OF_CONDUCT.md
  • README.md
  • astro-playground/package.json
  • astro-playground/src/components/ReactComponent.tsx
  • astro-playground/src/components/VueComponent.vue
  • oxlint-plugins.mjs
  • package.json
  • packages/notivue/Notifications/Notification.vue
  • packages/notivue/Notifications/constants.ts
  • packages/notivue/Notifications/icons/index.ts
  • packages/notivue/Notifications/notifications-progress.css
  • packages/notivue/Notifications/notifications.css
  • packages/notivue/Notifications/themes.ts
  • packages/notivue/Notifications/types.ts
  • packages/notivue/Notivue/AriaLive.vue
  • packages/notivue/Notivue/Notivue.vue
  • packages/notivue/Notivue/NotivueImpl.vue
  • packages/notivue/Notivue/composables/useFocusEvents.ts
  • packages/notivue/Notivue/composables/useMouseEvents.ts
  • packages/notivue/Notivue/composables/useNotivueStyles.ts
  • packages/notivue/Notivue/composables/useReducedMotion.ts
  • packages/notivue/Notivue/composables/useResizeListObserver.ts
  • packages/notivue/Notivue/composables/useSizes.ts
  • packages/notivue/Notivue/types.ts
  • packages/notivue/NotivueKeyboard/NotivueKeyboard.vue
  • packages/notivue/NotivueKeyboard/NotivueKeyboardImpl.vue
  • packages/notivue/NotivueKeyboard/constants.ts
  • packages/notivue/NotivueKeyboard/types.ts
  • packages/notivue/NotivueKeyboard/useNotivueKeyboard.ts
  • packages/notivue/NotivueSwipe/NotivueSwipe.vue
  • packages/notivue/NotivueSwipe/types.ts
  • packages/notivue/astro/Notivue.vue
  • packages/notivue/astro/createNotivue.ts
  • packages/notivue/astro/push.ts
  • packages/notivue/astro/types.ts
  • packages/notivue/core/animations.css
  • packages/notivue/core/constants.ts
  • packages/notivue/core/createInstance.ts
  • packages/notivue/core/createNotify.ts
  • packages/notivue/core/createNotivue.ts
  • packages/notivue/core/createPush.ts
  • packages/notivue/core/createStore.ts
  • packages/notivue/core/createStoreWatchers.ts
  • packages/notivue/core/symbols.ts
  • packages/notivue/core/types.ts
  • packages/notivue/core/useStore.ts
  • packages/notivue/core/utils.ts
  • packages/notivue/index.ts
  • packages/notivue/nuxt/README.md
  • packages/notivue/nuxt/module.cjs
  • packages/notivue/nuxt/module.d.ts
  • packages/notivue/nuxt/module.json
  • packages/notivue/nuxt/module.mjs
  • packages/notivue/package.json
  • packages/notivue/scripts/verify-exports.js
  • packages/notivue/scripts/verify-tarball.sh
  • packages/notivue/shared/exports.js
  • packages/notivue/tsconfig.json
  • packages/notivue/tsdown.config.ts
  • packages/notivue/vite.config.ts
  • playground-astro/.gitignore
  • playground-astro/.prettierrc
  • playground-astro/astro.config.mjs
  • playground-astro/package.json
  • playground-astro/src/components/AstroComponent.astro
  • playground-astro/src/components/Notivue.vue
  • playground-astro/src/components/ReactComponent.tsx
  • playground-astro/src/components/VueComponent.vue
  • playground-astro/src/env.d.ts
  • playground-astro/src/layouts/Layout.astro
  • playground-astro/src/pages/_app.ts
  • playground-astro/src/pages/about.astro
  • playground-astro/src/pages/index.astro
  • playground-astro/src/styles/reset.css
  • playground-astro/tsconfig.json
  • playground/app.vue
  • playground/assets/notivue-stream.css
  • playground/components/custom-notifications/FriendRequestNotification.vue
  • playground/components/custom-notifications/SimpleNotification.vue
  • playground/components/custom-notifications/UploadNotification.vue
  • playground/components/nav/Nav.vue
  • playground/components/nav/NavActions.vue
  • playground/components/nav/NavNotificationsCustomization.vue
  • playground/components/nav/NavNotificationsThemes.vue
  • playground/components/nav/NavNotivueConfig.vue
  • playground/components/nav/NavNotivuePosition.vue
  • playground/components/nav/NavPushBuiltIn.vue
  • playground/components/nav/NavPushHeadless.vue
  • playground/components/shared/Background.server.vue
  • playground/components/shared/QueueCount.vue
  • playground/middleware/notify.global.ts
  • playground/nuxt.config.ts
  • playground/package.json
  • playground/utils/head.ts
  • playground/utils/misc.ts
  • playground/utils/store.ts
  • pnpm-workspace.yaml
  • tests/Notifications/elements.cy.ts
  • tests/Notifications/themes.cy.ts
  • tests/Notivue/accessibility.cy.ts
  • tests/Notivue/attributes.cy.ts
  • tests/Notivue/components/Notivue.vue
  • tests/Notivue/config-animations.cy.ts
  • tests/Notivue/config-enqueue.cy.ts
  • tests/Notivue/config-limit.cy.ts
  • tests/Notivue/config-pause-on-focus.cy.ts
  • tests/Notivue/config-pause-on-hover.cy.ts
  • tests/Notivue/config-pause-on-touch.cy.ts
  • tests/Notivue/prefers-reduced-motion.cy.ts
  • tests/Notivue/push-methods.cy.ts
  • tests/Notivue/slot-custom-push-options.cy.ts
  • tests/Notivue/slot-default-options.cy.ts
  • tests/Notivue/slot-global-options.cy.ts
  • tests/Notivue/slot-internal-properties.cy.ts
  • tests/Notivue/transitions.cy.ts
  • tests/NotivueKeyboard/actions.cy.ts
  • tests/NotivueKeyboard/components/Candidate.vue
  • tests/NotivueKeyboard/components/Notivue.vue
  • tests/NotivueKeyboard/entering-stream.cy.ts
  • tests/NotivueKeyboard/leaving-stream.cy.ts
  • tests/NotivueKeyboard/props.cy.ts
  • tests/NotivueKeyboard/queue.cy.ts
  • tests/NotivueSwipe/clear.cy.ts
  • tests/NotivueSwipe/components/Notivue.vue
  • tests/NotivueSwipe/debounce.cy.ts
  • tests/config/merge-notification-options.test.ts
  • tests/config/update-config.test.ts
  • tests/cypress.config.ts
  • tests/cypress/support/commands-keyboard.ts
  • tests/cypress/support/commands-notifications.ts
  • tests/cypress/support/commands-notivue.ts
  • tests/cypress/support/commands-swipe.ts
  • tests/cypress/support/component.ts
  • tests/cypress/support/utils.ts
  • tests/package.json
  • tests/tsconfig.json
  • tests/vite.config.mts
💤 Files with no reviewable changes (16)
  • .github/FUNDING.yml
  • astro-playground/package.json
  • packages/notivue/Notivue/composables/useResizeListObserver.ts
  • tests/NotivueKeyboard/leaving-stream.cy.ts
  • astro-playground/src/components/ReactComponent.tsx
  • astro-playground/src/components/VueComponent.vue
  • tests/cypress/support/component.ts
  • packages/notivue/core/createPush.ts
  • tests/Notivue/config-pause-on-touch.cy.ts
  • packages/notivue/vite.config.ts
  • packages/notivue/Notifications/notifications-progress.css
  • playground-astro/.prettierrc
  • playground/components/nav/NavNotivuePosition.vue
  • playground/components/nav/NavNotificationsThemes.vue
  • tests/Notivue/config-pause-on-hover.cy.ts
  • playground/utils/head.ts

Comment thread .cursorignore
Comment on lines +1 to +2
!docs/
!.claude/ No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Negation-only patterns are likely ineffective here.

!docs/ and !.claude/ only re-include paths after an ignore match. With no preceding ignore rule, this likely does not exclude anything.

Suggested fix
-!docs/
-!.claude/
+docs/
+!.claude/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
!docs/
!.claude/
docs/
!.claude/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.cursorignore around lines 1 - 2, The two lines use negation-only patterns
('!docs/' and '!.claude/') which do nothing without a preceding ignore; either
remove the leading '!' to actually ignore these directories (change to 'docs/'
and '.claude/') or add a preceding broad ignore that would match them (e.g., a
rule that ignores parent paths or a glob like '*' or 'docs/**') so the negation
can re-include them—update the .cursorignore accordingly to reflect the intended
behavior.


/**
* @deprecated NotivueKeyboard now manages focus automatically.
* This composable is no longer needed — remove it from your code.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace the em-dash in the deprecation note.

Use a hyphen or separate sentences instead.

✏️ Proposed wording
- * This composable is no longer needed — remove it from your code.
+ * This composable is no longer needed. Remove it from your code.

Based on learnings: "Do not use em-dashes. Use a hyphen, a comma, a colon, or separate sentences instead."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* This composable is no longer needed remove it from your code.
/**
* `@deprecated` NotivueKeyboard now manages focus automatically.
* This composable is no longer needed. Remove it from your code.
*/
export function useNotivueKeyboard(): NotivueKeyboardData {
return {
elementsTabIndex: ref(-1),
containersTabIndex: computed(() => ({})),
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/NotivueKeyboard/useNotivueKeyboard.ts` at line 7, The
deprecation comment in the useNotivueKeyboard composable uses an em-dash; update
the comment text in useNotivueKeyboard.ts to replace the em-dash with either a
hyphen or split into two sentences (e.g., "This composable is no longer needed -
remove it from your code." or "This composable is no longer needed. Remove it
from your code."), ensuring the file's top comment/JS Doc around the
useNotivueKeyboard export reflects the new punctuation.


**💊 Drop-in components to enhance notifications**
_NotivueSwipe, NotivueKeyboard, all optional and customizable_
_NotivueSwipe_ (alias `NotificationSwipe`), _NotivueKeyboard_, all optional and customizable\_

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Broken markdown emphasis on this feature line.

The inner _..._ pairs around the names combined with the trailing escaped \_ break the intended single italic description and render a stray underscore. Other feature lines wrap the whole description in one italic span.

📝 Proposed fix
-_NotivueSwipe_ (alias `NotificationSwipe`), _NotivueKeyboard_, all optional and customizable\_
+_NotivueSwipe (alias `NotificationSwipe`), NotivueKeyboard, all optional and customizable_
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_NotivueSwipe_ (alias `NotificationSwipe`), _NotivueKeyboard_, all optional and customizable\_
_NotivueSwipe (alias `NotificationSwipe`), NotivueKeyboard, all optional and customizable_
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/notivue/nuxt/README.md` at line 37, The markdown line with
"NotivueSwipe (alias `NotificationSwipe`), NotivueKeyboard, all optional and
customizable" has mismatched/escaped underscores causing broken emphasis; update
the emphasis so the whole description is wrapped in a single italic span (or
remove the stray backslash) and ensure inner identifiers stay inline code where
needed—fix the line that mentions NotivueSwipe / `NotificationSwipe` and
NotivueKeyboard so the surrounding _..._ includes the full phrase and no
trailing `\_` remains.

Comment thread pnpm-workspace.yaml
Comment on lines +5 to +6
- 'playground-astro'
- 'docs'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
for d in playground-astro docs; do
  echo "== $d =="
  fd -t f 'package.json' "$d" --max-depth 1 || echo "MISSING package.json in $d"
done

Repository: smastrom/notivue

Length of output: 263


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== pnpm-workspace.yaml =="
cat pnpm-workspace.yaml | sed -n '1,120p'

echo
echo "== repo root top-level (directories named docs / playground-astro) =="
ls -la | sed -n '1,200p' | rg -n '^(d|l)'

echo
echo "== existence checks =="
for d in playground-astro docs; do
  if [ -e "$d" ]; then
    echo "$d exists (type: $(stat -c '%F' "$d"))"
  else
    echo "$d does NOT exist"
  fi
done

echo
echo "== package.json under docs (any depth) =="
if [ -d docs ]; then
  fd -t f -g package.json 'package.json' docs || true
else
  echo "docs/ is not a directory; skipping fd search under it"
fi

echo
echo "== any other 'docs' directory candidate =="
fd -t d 'docs' . --max-depth 6 || true

Repository: smastrom/notivue

Length of output: 1138


🌐 Web query:

pnpm workspace.yaml packages entry matches no packages fail install non-existent directory

💡 Result:

pnpm will fail install in workspace scenarios when your workspace patterns don’t actually include the packages pnpm expects to resolve via the workspace protocol. 1) If your pnpm-workspace.yaml “packages” patterns match no packages, pnpm treats the workspace as containing only the root package (not your intended subpackages). pnpm’s docs state that if the packages field is omitted, only the root package is included in the workspace [1]. A related issue shows behavior like “No projects found” / no workspace projects when pnpm-workspace.yaml doesn’t include the intended packages [2][3]. 2) If you have dependencies declared with the workspace protocol (workspace:, workspace:1.0.0, etc.) but the referenced package is not present in the workspace, pnpm errors during install. pnpm’s error code is ERR_PNPM_WORKSPACE_PKG_NOT_FOUND, and the docs describe it as: a project has a workspace dependency that does not exist in the workspace, so pnpm install will fail (example: bar@1.0.0 is requested as workspace but only bar@2.0.0 exists) [4]. A concrete reproduction in pnpm/pnpm issue #7678 shows this exact situation: a dependency is “@myrepo/preset@workspace:” but no package with that name is present in the workspace, causing install failure [5]. 3) If you’re seeing messages like “pnpm workspace packages entry matches no packages … fail install non-existent directory”, the “non-existent directory” part is usually one of these underlying problems: - Your include globs don’t match any workspace package directories, so pnpm doesn’t “see” them as workspace packages [1][2]. - The package directories exist, but the package name in their package.json doesn’t match what other packages request via workspace:; then pnpm still can’t resolve the workspace package and fails with ERR_PNPM_WORKSPACE_PKG_NOT_FOUND [5][6]. - You’re running pnpm from a nested folder that contains (or is affected by) a pnpm-workspace.yaml, but that workspace configuration doesn’t include the current package; pnpm will scope to the matching workspace projects rather than the local folder contents [7]. What to do - Ensure pnpm-workspace.yaml “packages” patterns actually include every intended workspace package (and don’t accidentally exclude them). Example pattern commonly used to include all packages under packages/: packages: - "packages/" (matches recursively) [1]. - If you use the workspace protocol in dependencies (workspace: / workspace:^ / workspace:1.0.0), ensure the referenced package exists in the workspace and the package.json name matches exactly; otherwise install fails with ERR_PNPM_WORKSPACE_PKG_NOT_FOUND [4][5]. - To diagnose quickly, run pnpm list across the workspace (pnpm ls -r) and verify your packages appear; issues report “No projects found” when the workspace patterns don’t match packages [2]. If you share your pnpm-workspace.yaml and the exact error text, I can tell you which of the above cases you’re hitting (no matches vs. workspace dependency name mismatch vs. nested-folder/workspace scoping).

Citations:


🌐 Web query:

pnpm "workspace entry matches no packages" fail install non-existent directory

💡 Result:

The error message "workspace entry matches no packages" (or variations such as "No projects found" or "ERR_PNPM_WORKSPACE_PKG_NOT_FOUND") in pnpm usually indicates that the workspace configuration is unable to resolve the packages defined in your pnpm-workspace.yaml or that specific local dependencies are missing from the workspace graph [1][2]. Common causes and solutions include: 1. Misconfigured or Missing pnpm-workspace.yaml If your pnpm-workspace.yaml file is missing or contains invalid glob patterns, pnpm may fail to identify your packages [1]. Ensure the file exists in the root of your workspace and correctly includes your package directories [1]. If you want to include all packages recursively, you can use: packages: - '' 2. Local Dependency Not in Workspace The ERR_PNPM_WORKSPACE_PKG_NOT_FOUND error typically occurs when a package.json file declares a dependency using the workspace: protocol (e.g., "my-pkg": "workspace:*"), but pnpm cannot find a package named "my-pkg" within the directories defined in your workspace configuration [2]. - Verify that the name field in the target package's package.json exactly matches the name you are trying to import [2]. - Ensure the directory containing the local package is covered by the glob patterns in pnpm-workspace.yaml [2]. 3. Missing package.json Pnpm requires a package.json file to identify a directory as a workspace package [1]. If you are pointing to a directory that does not contain a package.json, or if the directory path itself does not exist, pnpm will fail to match it [1]. 4. Filter Issues If you encounter this error while using the --filter flag, note that filters are case-sensitive and match against the name field in package.json rather than the directory name [3]. Use double quotes for glob patterns to ensure your shell passes them correctly to pnpm (e.g., pnpm -F "./packages/") [3]. If the issue persists, verify your workspace setup by running pnpm ls -r to see which packages pnpm is currently detecting [1]. If no packages are listed, your pnpm-workspace.yaml configuration is not correctly pointing to your source code [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== pnpm-workspace.yaml =="
cat pnpm-workspace.yaml | sed -n '1,80p'

echo
echo "== directories named docs* (any depth) =="
fd -t d -i 'docs*' . --max-depth 6 || true

echo
echo "== package.json files with 'docs' in path =="
fd -t f -g 'package.json' -i 'package.json' . --max-depth 8 | rg -i 'docs' || true

echo
echo "== package.json names that include 'docs' (grep name) =="
fd -t f -g 'package.json' . --max-depth 8 -x sh -c 'echo "---- $1"; jq -r ".name // empty" "$1" 2>/dev/null || true' sh {} || true

Repository: smastrom/notivue

Length of output: 639


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== pnpm-workspace.yaml =="
cat pnpm-workspace.yaml | sed -n '1,80p'

echo
echo "== directories named docs* (any depth) =="
fd -t d -i 'docs*' . --max-depth 6 || true

echo
echo "== package.json files with 'docs' in path =="
fd -t f -g 'package.json' . --max-depth 8 | rg -i 'docs' || true

echo
echo "== package.json name fields that include 'docs' =="
fd -t f -g 'package.json' . --max-depth 8 | while read -r f; do
  name=$(jq -r '.name // empty' "$f" 2>/dev/null || true)
  if echo "$name" | rg -i 'docs'; then
    echo "$f -> $name"
  fi
done

Repository: smastrom/notivue

Length of output: 322


🌐 Web query:

pnpm workspace.yaml packages entry matches no packages fail install unmatched include glob

💡 Result:

What pnpm does when pnpm-workspace.yaml patterns don’t match packages (and whether install fails) 1) “No matches” for packages does not necessarily fail - pnpm determines the workspace package set by matching the packages glob patterns in pnpm-workspace.yaml. - If the workspace configuration results in no projects being found, pnpm reports “No projects found …” / otherwise doesn’t operate on subpackages, but this is not always treated as a hard install failure. - Example behavior: a repo with a pnpm-workspace.yaml that effectively finds no workspace packages yields pnpm install output like “No projects found …” and pnpm ls -r also reports no projects found [1]. 2) Excluding local packages is different from “install failing” - If a folder/package exists (has a package.json) but is NOT included by the workspace packages patterns, then that folder is treated as a normal (non-workspace) package. - Running pnpm install inside such a non-included folder should behave like a single-package install (i.e., no workspace lockfile generation for that folder). This “not whitelisted in pnpm-workspace.yaml” scenario is discussed in pnpm’s issue tracker [2]. 3) When you DO reference a workspace package but it isn’t in the workspace, pnpm errors - If your root/package.json depends on a workspace package (e.g. uses workspace:*) but the package is not present in the resolved workspace set, pnpm throws an explicit error. - Example error: ERR_PNPM_WORKSPACE_PKG_NOT_FOUND … is in the dependencies but no package named … is present in the workspace [3]. 4) Glob negation (!) / invalid globs can produce specific errors - If your pnpm-workspace.yaml packages patterns include negation or constructs that pnpm can’t parse/validate as a valid glob, pnpm can fail with an invalid_glob-type error. This is tracked as a separate issue [4]. Practical guidance based on the above - If your concern is that your packages patterns “match no packages”, first confirm pnpm is actually finding workspace projects; you may see “No projects found …” rather than a full install failure [1]. - If you are relying on workspace:* links, ensure every referenced package is actually included by the packages patterns; otherwise pnpm will fail with ERR_PNPM_WORKSPACE_PKG_NOT_FOUND [3]. - If you use negated globs (e.g. !/test/) make sure they are valid in pnpm’s glob syntax; otherwise you can hit invalid_glob failures [4]. If you paste your exact pnpm-workspace.yaml (including the packages: entries) and the folder structure you expect to be matched, I can tell you which of the above cases you’re hitting (no matches vs referenced workspace:* package missing vs invalid glob syntax).

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workspace:* deps across repo =="
rg -n --glob '**/package.json' '"[^"]+"\s*:\s*"workspace:[^"]*"' . || true

echo
echo "== any deps mentioning 'docs' =="
rg -n --glob '**/package.json' '"docs[^"]*"\s*:\s*"workspace:[^"]*"' . || true
rg -n --glob '**/package.json' '"[^"]*docs[^"]*"\s*:\s*"workspace:[^"]*"' . || true

echo
echo "== list package names from package.json =="
fd -t f -g 'package.json' . | while read -r f; do
  node -e "const p=require('./$f'); console.log('$f -> '+(p.name||''))" 2>/dev/null || true
done | sed -n '1,200p'

Repository: smastrom/notivue

Length of output: 579


Fix pnpm-workspace.yaml entry for docs

  • playground-astro/ has a package.json.
  • docs/ doesn’t exist (no package.json found), so the workspace entry is stale—remove it or point it to the real docs workspace package directory (or add the missing project).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpm-workspace.yaml` around lines 5 - 6, The pnpm workspace listing includes
a stale entry 'docs' that has no package.json; open pnpm-workspace.yaml and
remove the 'docs' entry or replace it with the correct workspace folder that
actually contains a package.json (e.g., update 'docs' -> '<actual-docs-folder>'
if you have a renamed docs package), leaving 'playground-astro' intact; ensure
after the change you can run pnpm -w list or pnpm -w install to verify the
workspace packages resolve correctly.

Comment thread README.md
```

<br />
> :bulb: Beyond this quick start — Nuxt/Astro setup, **`notify`** / callbacks, stream config, built-in styling, headless mode, full API — lives in the [documentation](https://docs.notivue.smastrom.io).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace em-dashes to match repo writing style.

Lines 33 and 114 use em-dashes. Prefer a hyphen, comma, colon, or separate sentence.

✏️ Suggested edits
-> :bulb: Beyond this quick start — Nuxt/Astro setup, **`notify`** / callbacks, stream config, built-in styling, headless mode, full API — lives in the [documentation](https://docs.notivue.smastrom.io).
+> :bulb: Beyond this quick start, Nuxt/Astro setup, **`notify`** / callbacks, stream config, built-in styling, headless mode, and the full API live in the [documentation](https://docs.notivue.smastrom.io).
-### Custom components — your own markup
+### Custom components: your own markup

Based on learnings: "Do not use em-dashes. Use a hyphen, a comma, a colon, or separate sentences instead."

Also applies to: 114-114

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 33, Two instances in README.md (the sentence starting
"Beyond this quick start — Nuxt/Astro setup, **`notify`** / callbacks, stream
config, built-in styling, headless mode, full API — lives in the
[documentation]..." and the one at line 114) use em-dashes; replace each em-dash
with the repo-preferred punctuation (e.g., a hyphen, comma, colon, or split into
separate sentences) so the phrasing reads correctly (for example: "Beyond this
quick start: Nuxt/Astro setup, `notify` / callbacks, stream config..." or split
into two sentences) and ensure the `notify` / callbacks fragment and
documentation link remain intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant