Render flash messages with UI::Alerts::FlashMessage - #4020
Merged
Conversation
Switches the four layouts that rendered flash through /layouts/revised_messages to the component. The partial stays for @page_errors and the mustache template BikeIndexAlerts renders client-side alerts into. Maps flash[:info] to the notice kind, and skips rendering when the flash is empty. The unknown-kind guard now falls back to notice outside dev/test -- Rails sweeps the flash after the layout renders, so raising would raise again on every subsequent request. Also moves UI::Alert to UI::Alerts::Base, so every alert component shares the one namespace. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Member
Author
The multi-update form redirects back to a turbo_stream response, so its flash needed a copy inside the results frame to survive. Replace #flash-messages alongside the frame instead, and drop the render_flash local and the bootstrap alert markup it rendered. The flash component renders its container even when empty, so the turbo_stream has something to target. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
flash[:errors] on the theft alert plan forms is validation errors on an object that's already in scope, set on a render rather than a redirect. Render UI::Alerts::ObjectError above the form instead, the way the other admin forms do -- the flash never displayed, it just wasn't a flash type. Three sites assigned errors.full_messages -- an Array -- to flash[:error]; to_sentence them, matching their siblings. UI::Alerts::FlashMessage skips non-strings, so those messages rendered nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Was tw:px-4, which cost the alert enough width that the dismiss button wrapped below the message at 390px. Desktop keeps its 16px gutter. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
users_controller and admin/theft_alerts_controller still assigned an Array to flash[:error]. UI::Alerts::FlashMessage skips non-strings, so a failed terms-of-service update and a failed promoted alert update both redirected with no error shown. to_sentence them, matching their siblings. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
info isn't one of UI::Alerts::Base's KINDS -- 24 call sites across 14 controllers set it, and four views passed it as a kind, where it silently fell back to notice. Rename them rather than aliasing info to notice in the component, so the flash type and the kind it renders stay the same word. KINDS now derives from TEXT_CLASSES, which is the list a kind actually needs an entry in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
find raises Capybara::Ambiguous when a page carries two, which is whenever a controller sets two flash keys. minimum: 1 keeps find's wait-for-it-to-appear, which a bare all would drop -- the assertion below would then pass on a flash that hadn't rendered yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four controllers reach flash[:info] indirectly, by passing flash_type: :info to authenticate_user, so the direct-assignment rename missed them. Signed-out /my_account, /choose_registration and the Strava connect flow all raised "Unknown flash type: info" out of the layout once the alias was gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deriving KINDS from TEXT_CLASSES moved lines in a file all three cached components reach through TEXT_CLASSES. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every impound index filter and sort hits format.turbo_stream, so replacing #flash-messages unconditionally wiped whatever alert the rider hadn't dismissed yet -- and shipped an empty container to do it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sethherr
marked this pull request as ready for review
August 2, 2026 20:40
sethherr
added a commit
that referenced
this pull request
Aug 3, 2026
Follow-up to #4020. An unknown alert kind used to fall back to notice silently, so a caller that passed a typo'd or unhandled kind got a blue box and no signal. And a dismissable alert's text could only wrap inside its own column, so a long message pushed the dismiss button onto a line of its own. - **`kind` defaults to `:notice`, and anything outside `KINDS` raises.** An omitted kind and a wrong one used to be the same input; now only the wrong one is an error. Deployed environments notify Honeybadger and fall back instead of raising — the flash is swept after the layout renders, so a raise from there would raise again on every subsequent request. That's `production? || sandbox?`, per the gotcha in `config/environments/sandbox.rb`. - **`UI::Alerts::FlashMessage` drops its own copy of that guard** and hands the flash type straight to the alert. - **The icon and dismiss button float rather than sitting in a flex row**, so an alert's first line renders between them and every line after runs the full width. A float displaces only the lines it overlaps, which a flex item can't do — its text is stuck in its own column. Both are kept to about a line tall and precede the text, which is what floats require; the dismiss button moving above the message in the DOM also puts it first in tab order. - **Preview reorganization**: the warning kind variant is now the header variant, the separate header group is gone, and the dismissable group picks up a header variant and a long-text purple one that exercises the wrapping above. The `MARKUP_DIGEST` bumps are these edits reaching templates inside fragment caches.
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.




The four layouts that rendered flash through
/layouts/revised_messagesnow render the component instead, the way admin already did. The partial stays behind for@page_errorsand the mustache templateBikeIndexAlertsrenders client-side alerts into, so the JS alerts on the bike-edit and payments pages keep working.flash[:info]becomesflash[:notice].infoisn't one ofKINDS— 24 call sites across 14 controllers set it directly, four more reach it by passingflash_type: :infotoauthenticate_user, and four views passed it as a kind, where it silently fell back. Renamed rather than aliased in the component, so the flash type and the kind it renders stay the same word.KINDSnow derives fromTEXT_CLASSES.errors.full_messages) or aflash[:errors]key; the component renders neither, and the old bootstrap partial rendered the Array'sinspect. Five getto_sentence, and the theft alert plan forms getUI::Alerts::ObjectErrorabove the form like the other admin forms.#flash-messagesalongside the results frame, rather than rendering a second copy of the flash inside the frame. The component renders its container even when empty so there's something to target, and the replace only fires when there's a flash — otherwise every filter and sort would wipe an alert the rider hadn't dismissed.UI::Alertmoves toUI::Alerts::Base, so all three alert components share the namespace. The threeMARKUP_DIGESTbumps are that rename reaching templates inside fragment caches.Flash now sits bottom-center instead of top, and success messages no longer auto-fade after 10s — the component's behavior, already what admin gets.