Conversation
Implement core R functions for toast notifications: - toast(): Create toast objects with customizable options - show_toast(): Display toasts in Shiny apps - hide_toast(): Manually dismiss toasts - toast_header(): Create structured headers with icons/status Follows bslib component patterns with object-oriented design and server-side creation model. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Implement client-side toast functionality: - ToastContainerManager for auto-creating position-specific containers - showToast handler to display toasts with Bootstrap Toast API - hideToast handler to manually dismiss toasts - Auto-cleanup of toast elements and empty containers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add minimal custom styles for toast component: - CSS variable for runtime theming support - Ensure close button visibility on colored backgrounds 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Import toast component to ensure message handlers are registered when the components bundle is loaded. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Test coverage includes: - Toast object creation and validation - Position and type argument validation - Accessibility attribute generation - Close button rendering logic - HTML structure generation - toast_header() functionality - All type and position options 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Create comprehensive demo app showcasing toast features: - Basic toasts with different types (success, error, warning, info) - Position options (all 9 positions) - Advanced features (persistent, long duration, no close button) - Interactive toasts with action buttons - Multiple toasts and stacking behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Change from direct import to window.bootstrap access pattern: - Import Toast type only, not implementation - Access Toast from window.bootstrap with class fallback - Add console warning if Bootstrap is not available - Follows pattern used by tooltip and popover components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Replace basic examples with comprehensive toast builder: - Interactive form with all toast options - input_switch() for binary settings (header, icon, status, autohide, etc) - Conditional panels to show/hide relevant options - Select menus for type, position, and icon choices - Slider for duration control - Custom ID option for manual toast management - Two buttons: show toast and hide last toast - Keep advanced features and interactive toast examples Users can now experiment with all toast parameters interactively. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Change the status parameter in toast_header() from a colored indicator to status text (e.g., "11 mins ago", "just now") that appears as small muted text in the header, matching Bootstrap's toast examples. - Remove validation for status parameter - Render status as <small class="text-muted"> instead of badge - Update documentation and examples - Update tests to match new behavior
Replace separate autohide (logical) and duration (milliseconds) parameters with single autohide_s parameter in seconds: - autohide_s = 0, NA, or NULL disables auto-hiding - autohide_s > 0 enables auto-hiding after N seconds - Internally converts to milliseconds for Bootstrap Toast - Simplifies API: one parameter instead of two Updates: - toast() function signature and implementation - All examples in demo app - All tests to use new parameter 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add two interactive features for autohiding toasts: 1. Progress Bar Animation: - Animated bar at top of toast shows remaining time - Uses CSS transform animation for smooth performance - Gradient styling with primary color theme integration - Automatically added only to autohiding toasts 2. Hover Pause Behavior: - Mouse hover pauses the auto-hide timer - Progress bar animation pauses when hovered - Both resume when mouse leaves - Override Bootstrap's hide() to check hover state Implementation: - addProgressBar(): Creates and styles progress element - setupHoverPause(): Configures hover event handlers - CSS keyframe animation for progress bar - Toast positioned relative with overflow hidden 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Change progress bar animation from emptying (1 → 0) to filling (0 → 1) to better indicate time passing. Bar now grows from left to right as the toast approaches auto-hide time. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Extract random ID generation into `toast_random_id()` helper function - Replace duplicate ID generation logic with centralized helper - Simplify `show_toast()` by using `processDeps()` instead of manual HTML rendering and dependency resolution - Remove redundant comments and streamline code flow
…simplify implementation - Consolidate documentation for `show_toast()` and `hide_toast()` into a single help page using `@describeIn` - Remove `session$onFlush()` callbacks in favor of immediate `sendCustomMessage()` calls - Make `hide_toast()` accept toast objects with IDs and return the ID consistently - Add error handling for hiding toasts without IDs - Update documentation examples and parameter descriptions - Add tests for `show_toast()` return value and `hide_toast()` functionality
| observeEvent(input$hide_toast, { | ||
| req(last_toast_id()) | ||
| hide_toast(last_toast_id()) | ||
| last_toast_id(NULL) | ||
| }) |
There was a problem hiding this comment.
If I click 'show' repeatedly, then 'hide' repeatedly, only the 1st hide works (since we're only tracking the last ID).
Related to this problem, would it make sense for hide_toast() to remove the "oldest" toast? Or provide access to a input[["toast_id"]] == T/F ?
There was a problem hiding this comment.
Yeah, that's why I labelled the button "Hide Last Toast". We certainly could keep track of a stack of toasts, but I don't think it's worth it for this example app.
I'm also fairly strongly against creating inputs for toasts to track their state. Toasts are primarily ephemeral by design; I don't think it's a good idea to add to the input namespace for something that is intended to be short-lived in the app.
I could be convinced to add a toast_state(id) helper that would return a reactive value indicating whether a toast with the given ID is currently visible or not. But I don't think it's a necessary feature so I'd rather hold off on that for now.
Co-authored-by: Carson Sievert <[email protected]>
Co-authored-by: Carson Sievert <[email protected]>
Also link to PR from bullet for #1204
Introduces a comprehensive toast notification system for Shiny applications, including
toast()(withtoast_header()helper),show_toast()andhide_toast().Toasts are small notification messages that are shown temporarily on screen. By default they autohide after 5 seconds, but this delay can be customized. bslib toasts have a few interesting features above and beyond the Bootstrap standard toasts:
show_toast()returns the ID of the toast that was shown (either auto-generated or from thetoastobject being shown). This ID can then be used withhide_toast()to hide the toast.bslib toasts come with an additional demo app to try out all of the features:
Examples
Basic toast
Toast with
headershow_toast( toast( "This is a toast notification!", header = toast_header( title = "Notification Title", icon = bsicons::bs_icon("star"), status = "16s ago" ) ) )Toast with
headerandtype = "success"show_toast( toast( "Your profile has been updated successfully", header = toast_header( title = "Profile updated", icon = bsicons::bs_icon("check", class = "text-success"), status = "just now" ) ) )Toast with Shiny controls
show_toast( toast( id = "unsaved_changes_toast", p("Would you like to save your changes?"), actionButton("save_yes", "Save", class = "btn-sm btn-primary me-2"), actionButton( "save_no", "Don't Save", class = "btn-sm btn-secondary" ), header = "Unsaved Changes", type = "warning", duration_s = 0 ) )