Skip to content

feat: nimbus toast indefinite duration#335

Open
joacotornello wants to merge 2 commits intomasterfrom
cursor/analyze-nimbus-toast-indefinite-duration-522c
Open

feat: nimbus toast indefinite duration#335
joacotornello wants to merge 2 commits intomasterfrom
cursor/analyze-nimbus-toast-indefinite-duration-522c

Conversation

@joacotornello
Copy link
Copy Markdown
Contributor

@joacotornello joacotornello commented Aug 21, 2025

Type

  • Bugfix 🐛
  • New feature 🌈
  • Change request 🤓
  • Documentation 📚
  • Tech debt 👩‍💻

Changes proposed ✔️

  • Add support for indefinite duration toasts via duration: null to enable manual control for async operations (e.g., file uploads), addressing [REQUEST] Toast Component: Need indefinite duration option for async operations #254.
  • Introduce a more intuitive API for indefinite toasts while maintaining backward compatibility with autoClose: false.
  • Enhance TypeScript types for duration to accept null, automatically setting autoClose to false when duration is null.
  • Provide comprehensive Storybook examples and update README to document the recommended pattern for async operations.
  • Include new tests to ensure correct behavior for duration: null.

Open in Cursor Open in Web

Summary by CodeRabbit

  • New Features
    • Support indefinite toasts by setting duration to null; they persist until manually closed and ignore auto-close. Backward-compatible with autoClose: false.
  • Documentation
    • Expanded README and changelogs with guidance and examples for async workflows and indefinite toasts. Storybook playground and async demo added.
  • Tests
    • Added tests confirming no auto-close for null duration and manual closure behavior.
  • Chores
    • Bumped package version to 2.5.0 and updated changelogs.

Co-authored-by: joaquin.tornello <joaquin.tornello@tiendanube.com>
@cursor
Copy link
Copy Markdown

cursor Bot commented Aug 21, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 21, 2025

📝 Walkthrough

Walkthrough

Implements indefinite-duration toasts by allowing duration: null, updating Toast runtime logic, types, tests, stories, and documentation, and bumps the Toast package to v2.5.0 (also recording the change in the repo changelog).

Changes

Cohort / File(s) Summary
Version bump
packages/react/src/atomic/Toast/package.json
Bump package version 2.4.0 → 2.5.0.
Repo changelog
packages/react/CHANGELOG.md
Add v5.18.0 entry noting Toast supports indefinite duration via duration: null.
Types and API shape
packages/react/src/atomic/Toast/src/toast.types.ts
ToastProperties.duration now allows null (4000
Component logic
packages/react/src/atomic/Toast/src/Toast.tsx
Add derived values shouldAutoClose and effectiveDuration; prevent auto-close when duration is null; use effectiveDuration for animation/timers.
Tests
packages/react/src/atomic/Toast/src/toast.spec.tsx
Add tests asserting no auto-close when duration: null (including when autoClose: true) and that manual/explicit close remains possible.
Storybook
.../Toast/src/components/ToastProvider/toastProvider.stories.tsx
Add playground and asyncOperations stories demonstrating duration: null and legacy autoClose: false, with example async upload flow and manual toast management.
Documentation
packages/react/src/atomic/Toast/README.md
Add "Indefinite duration (async operations)" section with TSX example using duration: null and legacy note about autoClose: false.
Changelog (package)
packages/react/src/atomic/Toast/CHANGELOG.md
Add 2.5.0 entry documenting nullable duration and related docs/story updates.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant App as App Component
  participant TP as Toast.Provider
  participant Toast as Toast Item

  User->>App: Trigger async action
  App->>TP: addToast({ type: "progress", duration: null })
  TP->>Toast: Render with duration: null
  Note right of Toast #DDEBF7: shouldAutoClose = false\neffectiveDuration = 4000 (animation only)
  Toast-->>Toast: No auto-close timer scheduled

  App->>TP: onSuccess → closeToast(progressId)
  TP->>Toast: Unmount progress toast
  App->>TP: addToast({ type: "success", duration: 4000 })
  TP->>Toast: Render success toast
  Toast-->>Toast: Auto-close after 4000ms
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

enhancement, documentation

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/analyze-nimbus-toast-indefinite-duration-522c

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @autosummary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @autotitle anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Aug 21, 2025

Getting started

Please make sure you read our documentation on how to write code for components, stories and styles.

  • Provide a list of changes
  • Include images to help better visualize your work
  • If your PR closes an issue, please link it
  • Add reviewers
  • Add a label to help better understand what your changes are related to

@joacotornello joacotornello marked this pull request as ready for review August 21, 2025 18:10
@joacotornello joacotornello requested a review from a team August 21, 2025 18:10
@joacotornello joacotornello changed the title Analyze nimbus toast indefinite duration feat: nimbus toast indefinite duration Aug 21, 2025
@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Aug 21, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 18

Caution

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

⚠️ Outside diff range comments (4)
packages/react/src/atomic/Toast/package.json (1)

6-9: Publish CHANGELOG.md as part of the package files.

Guidelines require including CHANGELOG.md in the "files" whitelist so consumers get release notes along with the package.

Apply:

   "files": [
     "dist",
-    "README.md"
+    "README.md",
+    "CHANGELOG.md"
   ],
packages/react/src/atomic/Toast/src/toast.types.ts (2)

9-16: Add JSDoc for all exported types.

Coding standards require JSDoc on exported types. Please document Types, TypesColors, and IconColor (purpose, constraints).

Example:

+/** Visual variants available for the Toast component. */
 export type Types = "primary" | "success" | "danger" | "progress";
-export type TypesColors = Exclude<Types, "progress"> | "neutral";
+/** Color tokens for Toast variants excluding progress; progress uses neutral. */
+export type TypesColors = Exclude<Types, "progress"> | "neutral";
 
+/** Icon color tokens mapped to design-system surfaces. */
 export type IconColor =
   | "primary-surface"
   | "success-surface"
   | "danger-surface"
   | "neutral-surface";

41-49: Optional: encode the duration=null ⇒ autoClose=false invariant at type level.

If you want TS to help callers, consider a discriminated shape. This is optional and non-breaking if added as an alternative type.

type IndefiniteToast = Omit<ToastProperties, "duration" | "autoClose"> & {
  duration: null;
  autoClose?: false;
};

type TimedToast = Omit<ToastProperties, "duration"> & {
  duration?: ToastDurationMs;
};

export type StrictToastProperties = IndefiniteToast | TimedToast;

Keep ToastProperties as-is for backward compatibility; export StrictToastProperties for power users and docs.

packages/react/src/atomic/Toast/src/Toast.tsx (1)

101-110: Inline style violates DS guideline; prefer class + CSS variable for transform.

packages/react/src/**/*.tsx should avoid inline styles. Suggest moving the translateY to CSS, controlled via a custom property set on the element or container class.

Example (outside current hunk):

// JSX
<div
  id={id}
  className={toast.classnames.appearance[type]}
  style={{ ['--toast-offset' as any]: `${position * -HEIGHT_TOAST}%` }}
  data-testid="toast-element"
  {...rest}
/>

// CSS (styles package)
.transform {
  transform: translateY(var(--toast-offset, 300%));
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5b92939 and 4b4ccf6.

⛔ Files ignored due to path filters (1)
  • packages/react/src/atomic/Toast/src/toast.docs.json is excluded by !**/*.docs.json
📒 Files selected for processing (7)
  • packages/react/src/atomic/Toast/CHANGELOG.md (1 hunks)
  • packages/react/src/atomic/Toast/README.md (1 hunks)
  • packages/react/src/atomic/Toast/package.json (1 hunks)
  • packages/react/src/atomic/Toast/src/Toast.tsx (2 hunks)
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx (2 hunks)
  • packages/react/src/atomic/Toast/src/toast.spec.tsx (1 hunks)
  • packages/react/src/atomic/Toast/src/toast.types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/CHANGELOG.md

📄 CodeRabbit inference engine (.cursor/rules/changelogs.mdc)

**/CHANGELOG.md: Each package must have its own CHANGELOG.md file in its root directory
The main repository must have a root CHANGELOG.md file
Changes must be documented in both the package-specific and root changelogs
Each changelog entry must have a date and version header in the format '## YYYY-MM-DD version', using semantic versioning, with the version enclosed in backticks and the date in YYYY-MM-DD format
Use the following categories with their respective emojis as section headers: '#### 🛠 Breaking changes', '#### 🎉 New features', '#### 🐛 Bug fixes', '#### 📚 3rd party library updates', '#### 💡 Others'
Each changelog entry must follow the format: Description of the change. (#PR by @contributor)
Major version (x.0.0) for breaking changes, minor version (0.x.0) for new features, and patch version (0.0.x) for bug fixes and minor changes
Every change must reference a PR number, using the full GitHub URL and the format '#PR'
Every change must credit the contributor, using GitHub usernames with @ prefix and linking to the contributor's GitHub profile
Changelog entries must be concise but descriptive, use present tense, focus on what changed (not how), group related changes together, and list changes in chronological order within each category
Use proper Markdown syntax, maintain consistent spacing, use proper emoji codes, and keep entries in chronological order (newest first)

Files:

  • packages/react/src/atomic/Toast/CHANGELOG.md

⚙️ CodeRabbit configuration file

**/CHANGELOG.md: Ensure CHANGELOG.md updates follow the established format: YYYY-MM-DD version with categorized entries (Breaking changes, New features, Bug fixes, Others).
Each entry must include PR reference and author, and changes must be properly versioned (major/minor/patch). Changes MUST be documented in their respective package's CHANGELOG.md.
CRITICAL: Clearly highlight and document the package bumps in the summary (or a comment, if unable), following exactly this structure: '@nimbus-ds/@|: .' For example: '@nimbus-ds/styles@9.18.0|minor: Added scroll-pane new composite component...'. It is crucial to respect the requested structure.

Files:

  • packages/react/src/atomic/Toast/CHANGELOG.md
!packages/icons/src/assets/*.svg

📄 CodeRabbit inference engine (.cursor/rules/icon-creation.mdc)

Do not place icon files outside of packages/icons/src/assets.

Files:

  • packages/react/src/atomic/Toast/CHANGELOG.md
  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/toast.types.ts
  • packages/react/src/atomic/Toast/package.json
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/README.md
  • packages/react/src/atomic/Toast/src/Toast.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/code.mdc)

**/*.{ts,tsx}: Enforce type safety—never use any or unsafe casts, and always declare explicit types. When a dynamic type is truly unavoidable, use unknown and narrow it explicitly. Never use any for props or state.
Replace magic numbers with named constants.
Always use strict equality operators (===, !==) instead of loose ones.
Ensure functions have consistent return types.
Avoid using deprecated APIs.
Ban the use of eval() entirely.
Handle exceptions properly; never swallow errors silently.
Omit unnecessary else branches after a return.
Refactor functions that exceed the acceptable cyclomatic complexity threshold >10.
Export only intended symbols; keep internals private.
Prefer RegExp.exec() over String.match().
Always provide default cases in switch statements.
Prefer for…of (or Array higher-order methods such as .map, .filter) over classic for loops where appropriate. Avoid for…in on arrays.
Avoid deeply nested code by extracting logic into functions.

Files:

  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/toast.types.ts
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/src/Toast.tsx

⚙️ CodeRabbit configuration file

**/*.{ts,tsx}: Review the React and TypeScript code for adherence to component design system best practices, including:

  • Component reusability, composability, and proper prop interfaces
  • Consistent usage of @nimbus-ds/styles package for styling and theming
  • Accessibility compliance (WCAG guidelines, ARIA attributes, keyboard navigation)
  • Cross-browser compatibility and progressive enhancement
  • Maintain comprehensive JSDoc comments with consistent style, documenting complex logic, and relevant references
  • Full testing coverage (Jest unit tests)
  • Performance optimization (memoization, loops)
  • Responsive design patterns
  • Component scalability and maintainability
  • Proper TypeScript types and interfaces usage
  • Component, prop, and storybook documentation
    Highlight any deviations from these standards.

Files:

  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/toast.types.ts
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/src/Toast.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/code.mdc)

**/*.tsx: Use functional components instead of class components.
Props are required by default; mark a prop optional (?:) only when the component can render a sensible fallback. Clearly document all optional props.
Props are immutable—never mutate them. Clone or derive new objects instead of in-place modification.
Prevent prop drilling: Use context or composition patterns to avoid passing props through many layers.
Memoize components where appropriate: Use React.memo or useMemo to optimize performance of pure/presentational components.
Use useCallback for event handlers: Wrap callbacks in useCallback to avoid function recreation unless dependencies change.
Avoid side effects in render: Only use effects inside useEffect or equivalent hooks.
Avoid index-based keys in lists: Always use unique, stable identifiers as React keys.
Enforce accessibility (a11y): Validate ARIA roles, labels, and keyboard navigation for every component.
Name event handlers with handle or on: e.g., handleClick, onChangeInput.
Export only one component per file: Keep files atomic for maintainability and reusability.
Enforce component display names for better debugging.

Files:

  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/src/Toast.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/icon-creation.mdc)

Exported icon component should be PascalCase + 'Icon' (e.g., ShoppingCartIcon).

Files:

  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/toast.types.ts
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/src/Toast.tsx
packages/react/src/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/nimbus-design-system.mdc)

packages/react/src/**/*.tsx: All components should follow all accessibility guidelines, including ARIA roles and labels.
Do not use 'any' types in props unless extremely necessary.
Do not use inline styles or deprecated APIs in components.

Files:

  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/src/Toast.tsx
**/packages/react/src/atomic/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

**/packages/react/src/atomic/**/*.{ts,tsx}: Review atomic components for dependency management in monorepo context:

  • Evaluate if the component is a common dependency across multiple packages
  • If widely used as a dependency, recommend adding the package name to the 'externals' attribute in webpack.config
  • This prevents the component from being bundled multiple times across different packages
  • Ensure proper package naming and versioning for external configuration
  • Verify that the component is properly exported and consumed by dependent packages. IMPORTANT Constants declared within the package must be exported in order to be included in the final published build.
  • Check for circular dependencies and proper dependency tree structure
    Flag components that should be added to webpack 'externals' to optimize bundle size and prevent duplicate code in the monorepo build.

Files:

  • packages/react/src/atomic/Toast/src/toast.spec.tsx
  • packages/react/src/atomic/Toast/src/toast.types.ts
  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
  • packages/react/src/atomic/Toast/src/Toast.tsx
**/*.types.ts

📄 CodeRabbit inference engine (.cursor/rules/types.mdc)

**/*.types.ts: Always export a ComponentNameProperties interface in PascalCase, where ComponentName matches the component's name.
Do NOT inherit from HTMLElement properties, BoxProperties, or large interfaces in component properties interfaces; include ONLY the specific props defined by the component.
You may export another interface like ComponentNameProps with complete inheritance, but the base ComponentNameProperties interface should remain focused.
Prefer type aliases for unions, intersections, and simple object types, using descriptive PascalCase names.
Keep types and interfaces focused; each type should have a single purpose and avoid creating large, multi-purpose types.
Add JSDoc comments for all exported types, including descriptions of the type's purpose and any constraints or special cases.
Leverage TypeScript utility types such as Partial<T>, Pick<T, K>, Omit<T, K>, and other built-in utility types when appropriate.
Avoid using the any type; use unknown for truly unknown types and provide proper type guards when needed.
Use PascalCase for type names and camelCase for property names; use descriptive names that indicate purpose.
Keep types focused and minimal.
Use utility types to reduce duplication.

Files:

  • packages/react/src/atomic/Toast/src/toast.types.ts

⚙️ CodeRabbit configuration file

**/*.types.ts: Review TypeScript type definitions following these standards:

  • Always export a 'ComponentNameProperties' interface, where the ComponentName is the name of the component. This interface should NOT inherit HTMLElement properties or BoxProperties, not any big interface as it will be used for documentation. It should ONLY contain the specific props this component defines.
  • Prefer type aliases for unions, intersections, and simple object types
  • Keep types and interfaces focused and single-purpose
  • Use proper JSDoc comments for all exported types
  • Leverage TypeScript utility types when appropriate (Partial, Pick, Omit)
  • Ensure type names are descriptive and follow PascalCase convention
  • Avoid type 'any' - use 'unknown' for truly unknown types
    Flag any deviations from these patterns.

Files:

  • packages/react/src/atomic/Toast/src/toast.types.ts
**/package.json

📄 CodeRabbit inference engine (.cursor/rules/package-json.mdc)

**/package.json: NEVER bump manually the version of the package.json file. It should be done automatically by the CI/CD pipeline. Only track in the specific CHANGELOG.md file the changes.
The 'name' key in package.json should be the name of the package, prefixed with @nimbus-ds/ (e.g., @nimbus-ds/skeleton).
The 'version' key in package.json: Initial version of a new package must be 0.0.0.
The 'files' key in package.json should list the files to be published to npm and must include: dist, README.md, and CHANGELOG.md.
The 'dependencies' key in package.json should only include runtime dependencies and must include all such dependencies. Do not include development or build-time dependencies here.
The 'devDependencies' key in package.json should only include development or build-time dependencies and must include all such dependencies.
The 'peerDependencies' key in package.json should only include runtime dependencies expected to be installed by the consumer.
The 'scripts' key in package.json should only include build, clean, and version scripts.
The 'homepage' key in package.json must be "https://nimbus.nuvemshop.com.br/documentation".
The 'repository' key in package.json must be of type "git" and have the URL "git+https://github.com/TiendaNube/nimbus-design-system.git".
The 'bugs' key in package.json must be "https://github.com/TiendaNube/nimbus-design-system/issues".
The 'license' key in package.json must be "MIT".
The 'main' key in package.json must be "dist/index.js".
The 'sideEffects' key in package.json must be false (boolean value).

Files:

  • packages/react/src/atomic/Toast/package.json

⚙️ CodeRabbit configuration file

Verify version updates follow SemVer: major for breaking changes, minor for new features, patch for bug fixes. Ensure dependencies are properly versioned and peer dependencies are correctly specified.

Files:

  • packages/react/src/atomic/Toast/package.json
packages/react/src/**/*.stories.tsx

📄 CodeRabbit inference engine (.cursor/rules/nimbus-design-system.mdc)

packages/react/src/**/*.stories.tsx: Structure each component’s stories with: Default (required‑prop baseline), Playground using Args/Controls, and additional explicit stories for each meaningful state (e.g. Primary, Secondary, Disabled).
Include recipe stories for real-life UI flows in Storybook.
Do not repeat stories in Storybook.

Files:

  • packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
🪛 markdownlint-cli2 (0.17.2)
packages/react/src/atomic/Toast/CHANGELOG.md

7-7: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

🪛 GitHub Actions: sonarcloud
packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx

[error] 34-34: yarn build:icons: TS2345: Argument of type '{ type: "success"; text: string; duration: 4000; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.


[error] 55-55: yarn build:icons: TS2345: Argument of type '{ id: string; type: "progress"; text: string; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.


[error] 66-66: yarn build:icons: TS2345: Argument of type '{ type: "primary"; text: string; duration: 4000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type 'Omit<ToastProps, "autoClose">'.


[error] 73-73: yarn build:icons: TS2345: Argument of type '{ type: "success"; text: string; duration: 8000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type 'Omit<ToastProps, "autoClose">'.


[error] 86-86: yarn build:icons: TS2345: Argument of type '{ id: string; type: "progress"; text: string; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'.


[error] 171-171: yarn build:icons: TS2345: Argument of type '{ type: "success"; text: string; duration: 4000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type 'Omit<ToastProps, "autoClose">'.


[error] 179-179: yarn build:icons: TS2345: Argument of type '{ type: "danger"; text: string; duration: 8000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type 'Omit<ToastProps, "autoClose">'.

🪛 GitHub Actions: check-quality
packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx

[error] 34-34: Step: yarn build:icons. TS2345: Argument of type '{ type: "success"; text: string; duration: 4000; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.


[error] 55-55: TS2345: Argument of type '{ id: string; type: "progress"; text: string; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.


[error] 66-70: TS2345: Argument of type '{ type: "primary"; text: string; duration: 4000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type '{ type: "primary"; text: string; duration: 4000; }' but 1 required in type 'Omit<ToastProps, "autoClose">'.


[error] 73-77: TS2345: Argument of type '{ type: "success"; text: string; duration: 8000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type '{ type: "success"; text: string; duration: 8000; }' but 1 required in type 'Omit<ToastProps, "autoClose">'.


[error] 86-86: TS2345: Argument of type '{ id: string; type: "progress"; text: string; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'.


[error] 171-175: TS2345: Argument of type '{ type: "success"; text: string; duration: 4000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type '{ type: "success"; text: string; duration: 4000; }' but 1 required in type 'Omit<ToastProps, "autoClose">'.


[error] 179-183: TS2345: Argument of type '{ type: "danger"; text: string; duration: 8000; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Property 'id' is missing in type '{ type: "danger"; text: string; duration: 8000; }' but 1 required in type 'Omit<ToastProps, "autoClose">'.

🪛 LanguageTool
packages/react/src/atomic/Toast/README.md

[grammar] ~46-~46: Use correct spacing
Context: ...# Indefinite duration (async operations) For async operations with unknown comple...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~48-~48: Use correct spacing
Context: ..., etc.), use indefinite duration toasts: tsx import { useToast } from "@nimbus-ds/toast"; const MyComponent = () => { const { addToast, closeToast } = useToast(); const handleUpload = async () => { // Show indefinite progress toast const toastId = addToast({ type: "progress", text: "Uploading files...", duration: null, // Indefinite duration }); try { await uploadFiles(); // Close progress toast and show success closeToast(toastId); addToast({ type: "success", text: "Upload completed!", duration: 4000, }); } catch (error) { closeToast(toastId); addToast({ type: "danger", text: "Upload failed!", duration: 8000, }); } }; return <button onClick={handleUpload}>Upload Files</button>; }; Alternative API (legacy): You can also...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[typographical] ~88-~88: To join two clauses or set off examples, consider using an em dash.
Context: ... also use autoClose: false instead of duration: null - both achieve the same result. ### Recommend...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~88-~88: Use correct spacing
Context: ...n: null` - both achieve the same result. ### Recommendation for use - Inform about u...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

⏰ Context from checks skipped due to timeout of 30000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: check-version
🔇 Additional comments (2)
packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx (2)

38-47: Good use of duration: null with explicit id for indefinite toast.

This matches the new API intent and keeps manual control via id management.


1-1: All clear—no stale autoClose or missing id in addToast calls detected.

I ran a full ripgrep sweep with PCRE2 across all .ts and .tsx files and found zero occurrences of addToast({ autoClose: … }) or any addToast({ … }) invocations lacking an id property. The stories and docs are clean, so CI should remain green.

Comment on lines +5 to +23
## 2025-01-02 `2.5.0`

#### 🎉 New features

- Added support for indefinite duration toasts using `duration: null` for async operations with unknown completion times. ([#254](https://github.com/TiendaNube/nimbus-design-system/issues/254))
- Enhanced TypeScript types to allow `null` as a duration value, providing a more intuitive API for manual toast control.

#### 📚 Documentation

- Added comprehensive Storybook examples demonstrating indefinite duration usage for async operations.
- Updated README with detailed examples showing how to use indefinite duration toasts for file uploads and API calls.
- Enhanced component documentation to explain the interaction between `duration: null` and `autoClose` properties.

#### 🛠️ API Changes

- **Non-breaking**: `duration` prop now accepts `null` value for indefinite duration toasts.
- **Backward compatible**: Existing `autoClose: false` API continues to work alongside the new `duration: null` approach.
- When `duration: null` is used, `autoClose` is automatically set to `false`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix category headings, add PR/author links, and correct the release date.

  • Use only the allowed categories: New features, Bug fixes, 3rd party library updates, Others.
  • Each bullet must reference the PR and author.
  • The date for 2.5.0 should be the release date. Given this PR is opened on 2025-08-21, 2025-01-02 is incorrect and breaks chronological order versus 2.4.0 (2025-03-18).

Apply:

-## 2025-01-02 `2.5.0`
+## 2025-08-21 `2.5.0`
 
-#### 🎉 New features
+#### 🎉 New features
 
-- Added support for indefinite duration toasts using `duration: null` for async operations with unknown completion times. ([#254](https://github.com/TiendaNube/nimbus-design-system/issues/254))
-- Enhanced TypeScript types to allow `null` as a duration value, providing a more intuitive API for manual toast control.
+- Added support for indefinite-duration toasts using `duration: null` for async operations with unknown completion times. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
+- Enhanced TypeScript types to allow `null` as a duration value, providing a more intuitive API for manual toast control. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
 
-#### 📚 Documentation
+#### 💡 Others
 
-- Added comprehensive Storybook examples demonstrating indefinite duration usage for async operations.
-- Updated README with detailed examples showing how to use indefinite duration toasts for file uploads and API calls.
-- Enhanced component documentation to explain the interaction between `duration: null` and `autoClose` properties.
+- Added Storybook examples demonstrating indefinite duration usage for async operations. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
+- Updated README with examples showing how to use indefinite-duration toasts for file uploads and API calls. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
+- Documented that when `duration: null` is used, `autoClose` is automatically set to `false`. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
-
-#### 🛠️ API Changes
-
-- **Non-breaking**: `duration` prop now accepts `null` value for indefinite duration toasts.
-- **Backward compatible**: Existing `autoClose: false` API continues to work alongside the new `duration: null` approach.
-- When `duration: null` is used, `autoClose` is automatically set to `false`.

Additionally, per repo rules, include the bump summary (recorded here for convenience):

@nimbus-ds/toast@2.5.0|minor: Add indefinite-duration support via duration: null; update types, docs, stories, and tests.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

7-7: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/CHANGELOG.md around lines 5 to 23, the
changelog uses disallowed categories and an incorrect release date and lacks
PR/author links and the required bump summary; update the header for 2.5.0 to
the correct release date (2025-08-21), replace category headings with only the
allowed ones (New features, Bug fixes, 3rd party library updates, Others),
convert each bullet into a line that includes the PR number and author in
brackets (e.g. ([#254](...)/@author)), ensure the note about duration: null and
types/docs/stories/tests is under "New features", move any other notes into the
appropriate allowed categories, and append the repo-required bump summary line
exactly: @nimbus-ds/toast@2.5.0|minor: Add indefinite-duration support via
duration: null; update types, docs, stories, and tests.

{
"name": "@nimbus-ds/toast",
"version": "2.4.0",
"version": "2.5.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Do not bump package.json versions manually—revert to the current published version and let CI handle it.

Per repo guidelines, versions in package.json are managed by CI/CD. Keep the CHANGELOG entry, but drop this manual bump.

Apply this diff to revert the manual bump (assuming previous was 2.4.0 per history):

-  "version": "2.5.0",
+  "version": "2.4.0",
📝 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
"version": "2.5.0",
"version": "2.4.0",
🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/package.json around line 3, revert the manual
version bump from "2.5.0" back to the currently published version ("2.4.0") so
package.json reflects the published version; keep the CHANGELOG entry intact and
remove only the version change, and rely on the CI/CD release process to update
the package version automatically.

Comment on lines +46 to +86
### Indefinite duration (async operations)

For async operations with unknown completion times (file uploads, API calls, etc.), use indefinite duration toasts:

```tsx
import { useToast } from "@nimbus-ds/toast";

const MyComponent = () => {
const { addToast, closeToast } = useToast();

const handleUpload = async () => {
// Show indefinite progress toast
const toastId = addToast({
type: "progress",
text: "Uploading files...",
duration: null, // Indefinite duration
});

try {
await uploadFiles();

// Close progress toast and show success
closeToast(toastId);
addToast({
type: "success",
text: "Upload completed!",
duration: 4000,
});
} catch (error) {
closeToast(toastId);
addToast({
type: "danger",
text: "Upload failed!",
duration: 8000,
});
}
};

return <button onClick={handleUpload}>Upload Files</button>;
};
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Docs and example look good; fix minor style/typography issues.

Great guidance and example for async flows. Two tiny nits:

  • Use an em dash instead of a hyphen before “both achieve the same result”.
  • Ensure a blank line before and after fenced code blocks to appease Markdown linters.

Apply:

-**Alternative API (legacy)**: You can also use `autoClose: false` instead of `duration: null` - both achieve the same result.
+**Alternative API (legacy)**: You can also use `autoClose: false` instead of `duration: null` — both achieve the same result.
📝 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
### Indefinite duration (async operations)
For async operations with unknown completion times (file uploads, API calls, etc.), use indefinite duration toasts:
```tsx
import { useToast } from "@nimbus-ds/toast";
const MyComponent = () => {
const { addToast, closeToast } = useToast();
const handleUpload = async () => {
// Show indefinite progress toast
const toastId = addToast({
type: "progress",
text: "Uploading files...",
duration: null, // Indefinite duration
});
try {
await uploadFiles();
// Close progress toast and show success
closeToast(toastId);
addToast({
type: "success",
text: "Upload completed!",
duration: 4000,
});
} catch (error) {
closeToast(toastId);
addToast({
type: "danger",
text: "Upload failed!",
duration: 8000,
});
}
};
return <button onClick={handleUpload}>Upload Files</button>;
};
```
**Alternative API (legacy)**: You can also use `autoClose: false` instead of `duration: null` — both achieve the same result.
🧰 Tools
🪛 LanguageTool

[grammar] ~46-~46: Use correct spacing
Context: ...# Indefinite duration (async operations) For async operations with unknown comple...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~48-~48: Use correct spacing
Context: ..., etc.), use indefinite duration toasts: tsx import { useToast } from "@nimbus-ds/toast"; const MyComponent = () => { const { addToast, closeToast } = useToast(); const handleUpload = async () => { // Show indefinite progress toast const toastId = addToast({ type: "progress", text: "Uploading files...", duration: null, // Indefinite duration }); try { await uploadFiles(); // Close progress toast and show success closeToast(toastId); addToast({ type: "success", text: "Upload completed!", duration: 4000, }); } catch (error) { closeToast(toastId); addToast({ type: "danger", text: "Upload failed!", duration: 8000, }); } }; return <button onClick={handleUpload}>Upload Files</button>; }; Alternative API (legacy): You can also...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/README.md around lines 46 to 86, fix two
minor typography/style nits: ensure there is a blank line immediately before the
opening fenced code block (```tsx) and a blank line immediately after the
closing fence, and replace the hyphen used before the phrase “both achieve the
same result” with an em dash (—). Update the file accordingly and save.

Comment on lines +29 to +36
const handleAddAutoToast = () => {
addToast({
type: "success",
text: "Auto-closing toast (4 seconds)",
duration: 4000,
autoClose: true,
});
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix type error: remove autoClose (not accepted by addToast) and provide an id.

CI shows TS2345 because addToast expects Omit<ToastProps, "autoClose"> and also requires id. Update the example accordingly.

Apply:

   const handleAddAutoToast = () => {
-    addToast({
-      type: "success",
-      text: "Auto-closing toast (4 seconds)",
-      duration: 4000,
-      autoClose: true,
-    });
+    const id = `toast-${Date.now()}`;
+    addToast({
+      id,
+      type: "success",
+      text: "Auto-closing toast (4 seconds)",
+      duration: 4000,
+    });
   };
📝 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
const handleAddAutoToast = () => {
addToast({
type: "success",
text: "Auto-closing toast (4 seconds)",
duration: 4000,
autoClose: true,
});
};
const handleAddAutoToast = () => {
const id = `toast-${Date.now()}`;
addToast({
id,
type: "success",
text: "Auto-closing toast (4 seconds)",
duration: 4000,
});
};
🧰 Tools
🪛 GitHub Actions: sonarcloud

[error] 34-34: yarn build:icons: TS2345: Argument of type '{ type: "success"; text: string; duration: 4000; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.

🪛 GitHub Actions: check-quality

[error] 34-34: Step: yarn build:icons. TS2345: Argument of type '{ type: "success"; text: string; duration: 4000; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.

🤖 Prompt for AI Agents
In
packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
around lines 29 to 36, the example passed an unsupported autoClose property and
omitted the required id causing TS2345; update the call to remove the autoClose
key and include a unique id (e.g. id: "auto-success-1") in the object passed to
addToast so it matches the expected Omit<ToastProps, "autoClose"> shape and
satisfies the required id field.

Comment on lines +49 to +58
const id = `toast-legacy-${Date.now()}`;
addToast({
id,
type: "progress",
text: "Legacy: autoClose false",
autoClose: false, // Legacy API still works
});
setToastIds(prev => [...prev, id]);
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace legacy autoClose path with duration: null to satisfy types and avoid API drift.

addToast no longer accepts autoClose; keep the “legacy” demo semantically equivalent by switching to duration: null, and adjust the label to avoid promoting a non-supported param.

Apply:

   const handleAddIndefiniteToastLegacy = () => {
     const id = `toast-legacy-${Date.now()}`;
     addToast({
       id,
-      type: "progress", 
-      text: "Legacy: autoClose false",
-      autoClose: false, // Legacy API still works
+      type: "progress",
+      text: "Legacy (migrated): duration: null",
+      duration: null,
     });
     setToastIds(prev => [...prev, id]);
   };

And update the button label below (lines 107-110):

-        <Button onClick={handleAddIndefiniteToastLegacy} appearance="neutral">
-          Add Indefinite Toast (autoClose: false)
-        </Button>
+        <Button onClick={handleAddIndefiniteToastLegacy} appearance="neutral">
+          Add Indefinite Toast (legacy → duration: null)
+        </Button>
📝 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
const handleAddIndefiniteToastLegacy = () => {
const id = `toast-legacy-${Date.now()}`;
addToast({
id,
type: "progress",
text: "Legacy: autoClose false",
autoClose: false, // Legacy API still works
});
setToastIds(prev => [...prev, id]);
};
const handleAddIndefiniteToastLegacy = () => {
const id = `toast-legacy-${Date.now()}`;
addToast({
id,
type: "progress",
text: "Legacy (migrated): duration: null",
duration: null,
});
setToastIds(prev => [...prev, id]);
};
<Button onClick={handleAddIndefiniteToastLegacy} appearance="neutral">
Add Indefinite Toast (legacy duration: null)
</Button>
🧰 Tools
🪛 GitHub Actions: sonarcloud

[error] 55-55: yarn build:icons: TS2345: Argument of type '{ id: string; type: "progress"; text: string; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.

🪛 GitHub Actions: check-quality

[error] 55-55: TS2345: Argument of type '{ id: string; type: "progress"; text: string; autoClose: boolean; }' is not assignable to parameter of type 'Omit<ToastProps, "autoClose">'. Object literal may only specify known properties, and 'autoClose' does not exist in type 'Omit<ToastProps, "autoClose">'.

🤖 Prompt for AI Agents
In
packages/react/src/atomic/Toast/src/components/ToastProvider/toastProvider.stories.tsx
around lines 49 to 58, replace the legacy addToast usage that passes autoClose:
false with the supported API by using duration: null and update the toast text
to not reference the removed param (e.g., "Legacy: duration null"); also update
the related button label at lines 107-110 to match the new demo semantics
(remove mention of autoClose and reference duration=null). Ensure types compile
with duration: null and that toastIds handling remains unchanged.

Comment on lines +47 to 52
// When duration is null, automatically set autoClose to false
const shouldAutoClose = duration === null ? false : autoClose;
const effectiveDuration = duration === null ? 4000 : duration;
const closeIntervalRef = useRef<any>();
const animationIntervalRef = useRef<any>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid any in refs; type timers precisely and align names with actual usage.

Both refs are declared as any and one of them stores a timeout (not an interval). Replace with specific types and names to prevent misuse and improve readability.

Apply this diff within the current hunk:

   // When duration is null, automatically set autoClose to false
   const shouldAutoClose = duration === null ? false : autoClose;
-  const effectiveDuration = duration === null ? 4000 : duration;
-  const closeIntervalRef = useRef<any>();
-
-  const animationIntervalRef = useRef<any>();
+  const effectiveDuration = duration === null ? 4000 : duration;
+  const closeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
+  const animationTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

Follow-up diffs below update the usages accordingly.

📝 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
// When duration is null, automatically set autoClose to false
const shouldAutoClose = duration === null ? false : autoClose;
const effectiveDuration = duration === null ? 4000 : duration;
const closeIntervalRef = useRef<any>();
const animationIntervalRef = useRef<any>();
// When duration is null, automatically set autoClose to false
const shouldAutoClose = duration === null ? false : autoClose;
const effectiveDuration = duration === null ? 4000 : duration;
const closeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const animationTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/src/Toast.tsx around lines 47-52, the refs
are typed as any and one is misnamed (stores a timeout not an interval); change
closeIntervalRef to closeTimeoutRef and type it as number | null (or
NodeJS.Timeout | null if this repo uses Node timers), and type
animationIntervalRef as number | null (or NodeJS.Timeout | null) instead of any;
update all usages to clearTimeout/clearInterval with the correctly named ref and
null-checks, and initialize refs with null (useRef<number | null>(null) or
useRef<NodeJS.Timeout | null>(null)). Ensure you replace variable references and
calls (clearTimeout/clearInterval) to match the new names and types.

Comment on lines +66 to 74
}, effectiveDuration);
}, [
setShow,
closeToast,
id,
duration,
effectiveDuration,
closeIntervalRef,
animationIntervalRef,
]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use setTimeout (one-shot) instead of setInterval; update refs accordingly.

We only need to close once after effectiveDuration. Using setInterval risks multiple executions if unmount is delayed. Also switches to the typed timeout ref names.

Apply:

-          }, effectiveDuration);
+          }, effectiveDuration);
   }, [
     setShow,
     closeToast,
     id,
-    effectiveDuration,
-    closeIntervalRef,
-    animationIntervalRef,
+    effectiveDuration,
+    closeTimeoutRef,
+    animationTimeoutRef,
   ]);

And change the timer creation just above:

-    setShow(true);
-    closeIntervalRef.current = setInterval(() => {
+    setShow(true);
+    closeTimeoutRef.current = setTimeout(() => {
       // remove animation
       setShow(false);
-      animationIntervalRef.current = setTimeout(() => {
+      animationTimeoutRef.current = setTimeout(() => {
         // remove toast in list
         closeToast(id);
       }, 200); // this timeout is to allow render the out transition
-          }, effectiveDuration);
+    }, effectiveDuration);
📝 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
}, effectiveDuration);
}, [
setShow,
closeToast,
id,
duration,
effectiveDuration,
closeIntervalRef,
animationIntervalRef,
]);
// …inside your useEffect(…)…
setShow(true);
closeTimeoutRef.current = setTimeout(() => {
// remove animation
setShow(false);
animationTimeoutRef.current = setTimeout(() => {
// remove toast in list
closeToast(id);
}, 200); // this timeout is to allow render the out transition
}, effectiveDuration);
}, [
setShow,
closeToast,
id,
effectiveDuration,
closeTimeoutRef,
animationTimeoutRef,
]);
🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/src/Toast.tsx around lines 66 to 74, the code
uses setInterval and interval refs to auto-close the toast; change this to a
one-shot setTimeout stored in a typed timeout ref (e.g., closeTimeoutRef) so the
close runs only once after effectiveDuration. Replace creation of the timer to
use window.setTimeout (or setTimeout) and assign the returned timer id to
closeTimeoutRef.current, and in the cleanup clear it with clearTimeout; also
rename any related refs/variables from *Interval* to *Timeout* (e.g.,
closeIntervalRef → closeTimeoutRef, animationIntervalRef → animationTimeoutRef)
and update their types to number | null (or ReturnType<typeof setTimeout>) and
usages accordingly.

Comment on lines +77 to +85
if (shouldAutoClose) {
close();
}
return () => {
// clear interval animation
clearInterval(closeIntervalRef?.current);
clearInterval(animationIntervalRef?.current);
};
}, [close, autoClose]);
}, [close, shouldAutoClose]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Clear timeouts, not intervals, and null-check refs to prevent leaks.

animationIntervalRef was created via setTimeout, but cleared with clearInterval. Use clearTimeout for both and guard with null checks.

Apply:

   useEffect(() => {
     if (shouldAutoClose) {
       close();
     }
     return () => {
       // clear interval animation
-      clearInterval(closeIntervalRef?.current);
-      clearInterval(animationIntervalRef?.current);
+      if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
+      if (animationTimeoutRef.current) clearTimeout(animationTimeoutRef.current);
     };
   }, [close, shouldAutoClose]);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/src/Toast.tsx around lines 77 to 85, the
cleanup currently calls clearInterval on refs that were set with setTimeout and
doesn't null-check the refs; change both clearInterval calls to clearTimeout,
guard each with a null/undefined check (e.g. if (closeIntervalRef?.current !=
null) clearTimeout(closeIntervalRef.current);) and then set the ref current to
null after clearing to avoid leaks.


const isProgress = useMemo(() => type === "progress", [type]);
const isVisible = useMemo(() => show || !autoClose, [autoClose, show]);
const isVisible = useMemo(() => show || !shouldAutoClose, [shouldAutoClose, show]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Manual close path skips the out-transition. Consider exposing an animated close API.

Because isVisible is pinned true for indefinite toasts, calling closeToast(id) removes the toast immediately without the 200ms out animation. Consider exposing a closeWithAnimation(id) from the provider (or routing closeToast through Toast’s close()) to preserve a consistent animated dismissal for manual closes as well.

🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/src/Toast.tsx around line 88, the current
isVisible logic pins toasts with shouldAutoClose=false as visible so calling
closeToast(id) removes the toast immediately and skips the ~200ms
out-transition; change the close flow to trigger the Toast component's out
animation first and only remove the toast from the provider after the animation
finishes. Concretely, add a local visible state in Toast and a
closeWithAnimation that sets visible=false (to start the 200ms CSS/animation out
transition) and, after a 200ms timeout or onAnimationEnd, calls the provider
removal; then either expose closeWithAnimation from the provider API or have
provider.closeToast route to the Toast instance's closeWithAnimation so manual
closes preserve the animated dismissal.

Comment on lines +34 to 41
* Set to null for indefinite duration (manual close required).
* @default 4000
*/
duration?: 4000 | 8000 | 16000;
duration?: 4000 | 8000 | 16000 | null;
/**
* Tells you whether or not Toast should close automatically.
* When duration is null, this is automatically set to false.
* @default true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Allowing duration: null is correct; consider naming the duration union and tighten docs.

Change looks good and keeps ToastProperties minimal. For readability and reuse, introduce a named union for durations. Also clarify in the docs that duration: null requires external/manual closure (usually via closeToast(id)).

 export interface ToastProperties {
@@
-  /**
-   * The time in milliseconds that the toast message should persist.
-   * Set to null for indefinite duration (manual close required).
-   * @default 4000
-   */
-  duration?: 4000 | 8000 | 16000 | null;
+  /**
+   * The time in milliseconds that the toast message should persist.
+   * Use `null` for an indefinite toast; it will not auto-close and must be closed manually.
+   * @default 4000
+   */
+  duration?: ToastDurationMs | null;
@@
   /**
    * Tells you whether or not Toast should close automatically.
    * When duration is null, this is automatically set to false.
    * @default true
    */
   autoClose?: boolean;

Add near the top of the file:

+/** Fixed, supported toast durations in milliseconds. */
+export type ToastDurationMs = 4000 | 8000 | 16000;
📝 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
* Set to null for indefinite duration (manual close required).
* @default 4000
*/
duration?: 4000 | 8000 | 16000;
duration?: 4000 | 8000 | 16000 | null;
/**
* Tells you whether or not Toast should close automatically.
* When duration is null, this is automatically set to false.
* @default true
// … other imports and declarations …
/** Fixed, supported toast durations in milliseconds. */
export type ToastDurationMs = 4000 | 8000 | 16000;
export interface ToastProperties {
// … other props …
/**
* The time in milliseconds that the toast message should persist.
* Use `null` for an indefinite toast; it will not auto-close and must be closed manually
* (e.g. via `closeToast(id)`).
* @default 4000
*/
duration?: ToastDurationMs | null;
/**
* Tells you whether or not Toast should close automatically.
* When `duration` is `null`, this is automatically set to `false`.
* @default true
*/
autoClose?: boolean;
// … remaining props …
}
🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/src/toast.types.ts around lines 34 to 41,
introduce a named union type for the allowed duration values (e.g.,
ToastDuration = 4000 | 8000 | 16000 | null) and replace the inline union on the
duration property with that type; update the JSDoc for duration to explicitly
state that duration: null disables auto-close and requires external/manual
closure (for example via closeToast(id)), and clarify the @default behavior
(auto-close true by default, but auto-close is false when duration is null).

💡 Verification agent

🧩 Analysis chain

Verify no timers are scheduled when duration is null.

Runtime should not start close timers for indefinite toasts. Please confirm Toast.tsx gates setTimeout behind the derived shouldAutoClose flag.


🏁 Script executed:

#!/bin/bash
# Ensure close timers are not created when duration is null
# 1) Find where timers are created
rg -nP -C3 --type=tsx 'setTimeout\s*\(' packages/react/src/atomic/Toast/src/Toast.tsx

# 2) Verify timer creation is guarded by shouldAutoClose (or equivalent)
rg -nP -C3 --type=tsx '(shouldAutoClose|autoClose)\s*&&\s*setTimeout' packages/react/src/atomic/Toast/src/Toast.tsx

# 3) Ensure duration null path sets shouldAutoClose=false
rg -nP -C3 --type=tsx 'duration\s*===\s*null|duration\s*==\s*null' packages/react/src/atomic/Toast/src/Toast.tsx

Length of output: 404


🏁 Script executed:

#!/bin/bash
# 1) Locate any setTimeout calls in the Toast component
rg -n -C3 'setTimeout' packages/react/src/atomic/Toast/src/Toast.tsx

# 2) Confirm any setTimeout usage is gated by the shouldAutoClose flag
rg -n -C3 'shouldAutoClose.*setTimeout' packages/react/src/atomic/Toast/src/Toast.tsx

# 3) Verify that when duration is null, shouldAutoClose is set to false
rg -n -C3 '===\s*null' packages/react/src/atomic/Toast/src/Toast.tsx

Length of output: 866


🏁 Script executed:

#!/bin/bash
# Show the useEffect that schedules and clears timers in Toast.tsx
rg -n -C15 "useEffect" packages/react/src/atomic/Toast/src/Toast.tsx

Length of output: 1434


Guard toast timers behind shouldAutoClose

On inspection, the first useEffect (around lines 59–66 in packages/react/src/atomic/Toast/src/Toast.tsx) always schedules an interval/timeout using effectiveDuration, even when duration is null. Since effectiveDuration falls back to 4000ms when duration === null, an “indefinite” toast still spins up timers. We need to short-circuit timer setup when shouldAutoClose is false.

Locations to update:

  • File: packages/react/src/atomic/Toast/src/Toast.tsx
  • First useEffect block (lines 59–74) that calls setInterval/setTimeout

Suggested diff:

 useEffect(() => {
-  closeIntervalRef.current = setInterval(() => {
+  // only schedule close timers when auto-close is enabled
+  if (!shouldAutoClose) return;
+
+  closeIntervalRef.current = setInterval(() => {
     // remove animation
     setShow(false);
     animationIntervalRef.current = setTimeout(() => {
       // remove toast in list
       closeToast(id);
     }, 200); // allow out-transition to render
-  }, effectiveDuration);
+  }, effectiveDuration);
 }, [
   setShow,
   closeToast,
   id,
   effectiveDuration,
+  shouldAutoClose,
   closeIntervalRef,
   animationIntervalRef,
 ]);

This ensures that when duration === null, shouldAutoClose is false and no timers are scheduled. Please add shouldAutoClose to the dependency array and wrap the timer setup in the if (!shouldAutoClose) return; guard.

📝 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
* Set to null for indefinite duration (manual close required).
* @default 4000
*/
duration?: 4000 | 8000 | 16000;
duration?: 4000 | 8000 | 16000 | null;
/**
* Tells you whether or not Toast should close automatically.
* When duration is null, this is automatically set to false.
* @default true
useEffect(() => {
// only schedule close timers when auto-close is enabled
if (!shouldAutoClose) return;
closeIntervalRef.current = setInterval(() => {
// remove animation
setShow(false);
animationIntervalRef.current = setTimeout(() => {
// remove toast in list
closeToast(id);
}, 200); // allow out-transition to render
}, effectiveDuration);
}, [
setShow,
closeToast,
id,
effectiveDuration,
shouldAutoClose,
closeIntervalRef,
animationIntervalRef,
]);
🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/src/Toast.tsx around lines 59 to 74, the
first useEffect always schedules a timer using effectiveDuration even when
duration === null (shouldAutoClose is false); update the effect to early-return
if shouldAutoClose is false to avoid scheduling timers, add shouldAutoClose to
the effect dependency array, and keep the existing cleanup logic to clear any
interval/timeout; ensure the guard is placed before creating the timer so no
timer is created for indefinite toasts.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
packages/react/src/atomic/Toast/CHANGELOG.md (2)

5-10: Add the required bump summary to the PR description.

Per repo rules, include this exact line in the PR description (or as a PR comment) to record the package bump:

@nimbus-ds/toast@2.5.0|minor: Add indefinite-duration support via duration: null; update types, docs, stories, and tests.

I can post this as a PR comment if you prefer.


5-10: Fix release date, keep allowed categories, and add an “Others” section for docs/stories.

  • Date should match the PR’s release date (this PR was opened on 2025-08-21).
  • Categories must be from the allowed set; current “🎉 New features” is fine.
  • Include docs/stories notes under “💡 Others” with PR and author links.

Apply:

-## 2025-01-02 `2.5.0`
+## 2025-08-21 `2.5.0`

 #### 🎉 New features

 - Added support for indefinite duration toasts using `duration: null` for async operations with unknown completion times. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
+
+#### 💡 Others
+
+- Added Storybook examples demonstrating indefinite-duration usage for async operations. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
+- Updated README with examples showing how to use indefinite-duration toasts for file uploads and API calls. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
+- Documented that when `duration: null` is used, `autoClose` is automatically set to `false`. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4b4ccf6 and 0a959d5.

⛔ Files ignored due to path filters (1)
  • .yarn/versions/75b70fe4.yml is excluded by !**/.yarn/**
📒 Files selected for processing (2)
  • packages/react/CHANGELOG.md (1 hunks)
  • packages/react/src/atomic/Toast/CHANGELOG.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/CHANGELOG.md

📄 CodeRabbit inference engine (.cursor/rules/changelogs.mdc)

**/CHANGELOG.md: Each package must have its own CHANGELOG.md file in its root directory
The main repository must have a root CHANGELOG.md file
Changes must be documented in both the package-specific and root changelogs
Each changelog entry must have a date and version header in the format '## YYYY-MM-DD version', using semantic versioning, with the version enclosed in backticks and the date in YYYY-MM-DD format
Use the following categories with their respective emojis as section headers: '#### 🛠 Breaking changes', '#### 🎉 New features', '#### 🐛 Bug fixes', '#### 📚 3rd party library updates', '#### 💡 Others'
Each changelog entry must follow the format: Description of the change. (#PR by @contributor)
Major version (x.0.0) for breaking changes, minor version (0.x.0) for new features, and patch version (0.0.x) for bug fixes and minor changes
Every change must reference a PR number, using the full GitHub URL and the format '#PR'
Every change must credit the contributor, using GitHub usernames with @ prefix and linking to the contributor's GitHub profile
Changelog entries must be concise but descriptive, use present tense, focus on what changed (not how), group related changes together, and list changes in chronological order within each category
Use proper Markdown syntax, maintain consistent spacing, use proper emoji codes, and keep entries in chronological order (newest first)

Files:

  • packages/react/src/atomic/Toast/CHANGELOG.md
  • packages/react/CHANGELOG.md

⚙️ CodeRabbit configuration file

**/CHANGELOG.md: Ensure CHANGELOG.md updates follow the established format: YYYY-MM-DD version with categorized entries (Breaking changes, New features, Bug fixes, Others).
Each entry must include PR reference and author, and changes must be properly versioned (major/minor/patch). Changes MUST be documented in their respective package's CHANGELOG.md.
CRITICAL: Clearly highlight and document the package bumps in the summary (or a comment, if unable), following exactly this structure: '@nimbus-ds/@|: .' For example: '@nimbus-ds/styles@9.18.0|minor: Added scroll-pane new composite component...'. It is crucial to respect the requested structure.

Files:

  • packages/react/src/atomic/Toast/CHANGELOG.md
  • packages/react/CHANGELOG.md
!packages/icons/src/assets/*.svg

📄 CodeRabbit inference engine (.cursor/rules/icon-creation.mdc)

Do not place icon files outside of packages/icons/src/assets.

Files:

  • packages/react/src/atomic/Toast/CHANGELOG.md
  • packages/react/CHANGELOG.md
🪛 markdownlint-cli2 (0.17.2)
packages/react/src/atomic/Toast/CHANGELOG.md

7-7: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

packages/react/CHANGELOG.md

7-7: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

🔇 Additional comments (2)
packages/react/src/atomic/Toast/CHANGELOG.md (1)

5-10: Update null-duration type check in verification script

The duration field in toast.types.ts is defined as a union of specific numeric literals and null (4000 | 8000 | 16000 | null), so the previous regex didn’t match it. We should loosen the pattern to simply ensure null is included in the union.

Please update the “Verify types accept null duration” step as follows:

 ## Verify types accept null duration
- rg -n -C2 -g 'packages/react/src/atomic/Toast/src/toast.types.ts' -P 'duration\s*:\s*(number\s*\|\s*)?null' || { echo "duration type not accepting null"; exit 1; }
+ rg -n -C2 -g 'packages/react/src/atomic/Toast/src/toast.types.ts' -P 'duration\?:.*null' || { echo "duration type not accepting null"; exit 1; }

The rest of the script remains the same:

#!/bin/bash
set -euo pipefail

echo "== Verify toast package version bump =="
rg -nC1 -g 'packages/react/src/atomic/Toast/package.json' '"version"\s*:\s*"2\.5\.0"' || { echo "Expected version 2.5.0 in Toast package.json"; exit 1; }

echo "== Verify types accept null duration =="
rg -n -C2 -g 'packages/react/src/atomic/Toast/src/toast.types.ts' -P 'duration\?:.*null' || { echo "duration type not accepting null"; exit 1; }

echo "== Verify runtime uses derived flags =="
rg -n -C2 -g 'packages/react/src/atomic/Toast/src/Toast.tsx' -P '(shouldAutoClose|effectiveDuration)'

echo "== Verify tests for duration: null exist =="
rg -n -C1 -g 'packages/react/src/atomic/Toast/src/toast.spec.tsx' -P 'duration:\s*null|autoClose[^\\S\\r\\n]*[:=][^\\S\\r\\n]*false'

echo "== Verify README docs mention indefinite duration =="
rg -n -C1 -g 'packages/react/src/atomic/Toast/README.md' -i 'indefinite|duration:\s*null'

echo "== Verify root changelog mentions the feature =="
rg -n -C1 -g 'packages/react/CHANGELOG.md' -P '##\s*2025-08-21.*`5\.18\.0`' && \
rg -n -C0 -g 'packages/react/CHANGELOG.md' -F '`Toast`: Added support for indefinite duration toasts using `duration: null`'

With this change, the type check will correctly detect that null is part of the duration union.

packages/react/CHANGELOG.md (1)

5-10: LGTM for the root changelog entry.

  • Correct date/version header format.
  • Allowed category used.
  • PR and author are properly linked.

Comment on lines +7 to +9
#### 🎉 New features

- `Toast`: Added support for indefinite duration toasts using `duration: null` for async operations with unknown completion times. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Heads-up: markdownlint MD001 will flag H4 under H2.

Repo guidelines prefer H4 (####) for category headings. Keep as-is; consider a markdownlint override for CHANGELOGs to avoid false positives.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

7-7: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

🤖 Prompt for AI Agents
In packages/react/CHANGELOG.md around lines 7 to 9, the reviewer notes
markdownlint MD001 will flag the H4 heading (#### 🎉 New features) under an H2;
keep the H4 as per repo convention but add a markdownlint override for CHANGELOG
files to prevent the false positive. Modify repository lint config (e.g.,
.markdownlint.json or package.json markdownlint settings) to disable or relax
MD001 for CHANGELOG.md files (or add a per-file frontmatter/HTML comment rule
disable at the top of this CHANGELOG.md) so H4 headings remain unchanged and
linting no longer fails.

Comment on lines +7 to +10
#### 🎉 New features

- Added support for indefinite duration toasts using `duration: null` for async operations with unknown completion times. ([#335](https://github.com/TiendaNube/nimbus-design-system/pull/335) by [@joacotornello](https://github.com/joacotornello))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Note on markdownlint MD001 vs repo convention.

The linter warns that heading levels should increment by one (expects H3 after H2). Repo guidelines explicitly require category headings as H4 (####). Keep H4 here; consider ignoring/suppressing MD001 for CHANGELOGs.

Would you like a quick markdownlint config snippet to disable MD001 for CHANGELOG.md files?

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

7-7: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

🤖 Prompt for AI Agents
In packages/react/src/atomic/Toast/CHANGELOG.md around lines 7 to 10, the
markdown linter flags MD001 because headings are H4 while the linter expects
incrementing levels; per repo convention CHANGELOG category headings must remain
H4. Keep the H4 heading as-is and suppress MD001 for CHANGELOG.md files by
updating the repository's markdownlint configuration (or adding a per-file
ignore) to disable MD001 for CHANGELOG.md so the linter does not error on these
files.

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

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants