feat: Add toolbar_download_button()#1298
Open
elnelson575 wants to merge 49 commits into
Open
Conversation
cpsievert
reviewed
Mar 18, 2026
elnelson575
commented
May 28, 2026
elnelson575
commented
May 28, 2026
elnelson575
commented
May 28, 2026
elnelson575
commented
May 28, 2026
elnelson575
commented
May 28, 2026
elnelson575
commented
May 28, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
elnelson575
commented
May 29, 2026
Addresses issue #1292 - adds a download button styled for toolbars. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add base styles and data-type attribute selectors for .bslib-toolbar-download-button to match the existing toolbar input button styling. This includes hover/focus/active states, disabled state, and responsive sizing for label-only, icon-only, and combined icon+label button layouts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds comprehensive test coverage for toolbar_download_button(): - Basic structure validation (classes, button types) - show_label parameter behavior - disabled state with accessibility attributes - border parameter (border-0 vs border-1) - tooltip parameter (default, custom, and disabled) - custom icon support All tests follow existing patterns from toolbar_input_button() tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix border=TRUE to use Bootstrap's 'border' class instead of 'border-1' (border-1 only sets width, not style) for both toolbar_input_button and toolbar_download_button - Add rel="noopener noreferrer" to target="_blank" anchor tag - Add @examplesIf block to toolbar_download_button docs - Add NEWS.md entry under new "New features" section - Update snapshots to reflect border and rel changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…yles - Fix hover text color on toolbar_download_button: restructure SCSS mixin to avoid LibSass dropping the .btn-default guard with 3-level & nesting; rely on pointer-events:none on .disabled instead of :not(.disabled) guards - Support user-supplied class via ... in toolbar_download_button(); extract from dots before forwarding to shiny::downloadButton() (which has class as a formal arg, unlike shiny::actionButton()) - Fix early-return bug in toolbarDownloadButton.ts that silently aborted icon and subsequent updates in a multi-field message - Remove redundant snapshot and test cases in test-toolbar.R
- Simplify enabled normalization to match shiny::downloadButton() style: collapse 4-branch if/else into a vector-default guard + hard abort - Add accessibility comments to label_id and icon_elem explaining why the aria-labelledby pattern and aria-hidden wrapping are necessary - Add label_text emptiness check/warning to update_toolbar_download_button, matching update_toolbar_input_button
Instead of a mixin, write the shared .btn-default interaction styles as explicit descendant selectors (no &) combined in a comma list. LibSass drops the .btn-default guard when & is used inside a combined selector, but plain descendant selectors compile correctly. A $_btn-not variable holds the shared :not() exclusion list to avoid repeating it on every line.
…tton Use border-1 to match the released behavior of toolbar_input_button on main.
…ector Turns out the alleged LibSass combined-selector bug doesn't exist — it compiled correctly all along. The earlier failure was from serving stale dist/components.css before recompiling. Replace the $_btn-not interpolation workaround with a simple comma-separated selector block.
…yles - Move shared layout properties (flex, height, line-height, action-icon/label margins) into the combined input+download selector block to eliminate duplication - Move color and text-decoration overrides inside the .btn-default:not(...) block so they are scoped to the default variant only, not btn-success etc. - Reduce .bslib-toolbar-download-button block to only its unique styles (text-decoration base, disabled state)
…ants text-decoration: none on hover is an <a>-tag concern, not .btn-default-specific. Scoping it inside the .btn-default guard caused btn-success etc. to show an underline on hover. Keep it in the broad .bslib-toolbar-download-button block.
…ighten class check
…with shinyApp + downloadHandler
…r, not specific here
eed8dce to
e2a889e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1292
NOTE: The gates can be removed when the latest version of shiny is released.
Summary
Adds
toolbar_download_button()to the toolbar component family, providing a download button styled consistently with other toolbar inputs for use in card headers, footers, and other toolbar contexts.toolbar_download_button()R function that creates an<a>tag with Shiny's download machineryupdate_toolbar_download_button()for dynamically updating the disabled statetoolbar_input_button()patternsDependencies:
Manual Test Cases:
Display:
Activation/Deactivation Logic
Updating:
Demo App
Screen.Recording.2026-05-29.at.12.48.59.PM.mov
App Code:
Test Plan
downloadHandler()