Repository navigation
Conversation
Update generated markup for the upcoming Bootstrap 6 release, per the v5-to-v6 migration guide and the v6 forms documentation: - Selects: use form-control instead of form-select - Checkboxes/radios: form-field wrapper with check/radio input classes, labels without form-check-label; inline via d-inline-grid utilities - Switches: input wrapped in div.switch with role="switch" and the native switch attribute - Range fields: div.form-range wrapper with form-range-input class - Floating labels: label rendered before the control - Buttons: btn-solid theme-primary/theme-secondary instead of btn btn-primary/btn-secondary - Grid: new breakpoint prefix syntax (sm:col-2, sm:offset-2, sm:me-2) for default label/control cols and offset calculation - Alerts: alert theme-danger instead of alert alert-danger Update test suite and README examples to the new markup, add UPGRADE-6.0.md, and bump version to 6.0.0.alpha1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit ecdd35f)
Bootstrap 6 ships a datepicker component activated by data-bs-toggle="datepicker" on a text input. Add a datepicker_field helper that delegates to text_field and renders the :datepicker option hash as data-bs-* attributes (Date values as ISO 8601, arrays as JSON). autocomplete="off" is set by default per the Bootstrap docs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit e4275d5)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 37015a1)
Bootstrap 6's form-field class is a CSS-grid wrapper that lays out a control with its label, help text, and validation feedback — exactly what bootstrap_form's form groups contain. Emit it by default: - Vertical form groups: form-field mb-3 (was mb-3) - Grouped collections (group_around_collections): form-group mb-3, Bootstrap 6's wrapper for multiple form-fields with a shared label - Horizontal, inline, and floating-label groups are unchanged since they lay out via grid columns, utilities, or form-floating, which would conflict with the form-field grid Also drop text-muted from help text (removed in Bootstrap 6; form-text styles itself). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit abe45e3)
Bootstrap 6's combobox is a native select-like control with optional search and multiple selection — a plain-Bootstrap replacement for plugins like use-bootstrap-select. The new combobox helper generates the toggle button, menu items with data-bs-value, pre-selected state (from the object value or the :selected option), the search input and no-results block, and the multiple-selection check icons. Bootstrap's JavaScript handles the hidden input for form submission via data-bs-name. The chips component was considered for multiple-value display, but as of 6.0.0-alpha1 it has no form-submission integration, so no chip mark-up is generated; this is documented in the README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit c33f6a5)
Thorough pass over the remaining v6 forms documentation pages: - form-adorn: new `adorn` option on text-style helpers renders an icon or text decoration inside a form-control form-adorn wrapper with a form-ghost input (leading or trailing, with custom wrapper classes) - otp-input: new otp_field helper renders the .otp[data-bs-otp] container around a single text input (slots from maxlength, config via the :otp option as data-bs-* attributes, is-invalid on the container on errors, autocomplete="one-time-code" by default) - password-strength: new `strength` option on password_field renders the segmented meter or strength-bar, with optional strength-text and data-bs-min-length - validation: `validate: true` form option emits data-bs-validate and novalidate on the form; checkbox/radio/switch feedback (and new help text support) now nests in form-field-content per the v6 validation docs; input-group feedback moves outside the input-group, a sibling in the form-field wrapper - input-group: document that buttons in input groups need the v6 input-group-btn class Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 8605392)
(cherry picked from commit dae8c29)
The demo resolves Rails through the root Gemfile's open-ended REQUIRED_RAILS_VERSION constraint and now runs on Rails 8.1.4. Its config was already generated by Rails 8.x and loads framework defaults dynamically, so only the README heading needed to change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 22aed46)
The demo builds its JavaScript with esbuild from app/javascript/application.js and its CSS with Sass. The Webpacker config, webpack runner scripts, an unused webpack.config.js, the packs/ and channels/ entry points, the PostCSS config and a webpack license artifact were all dead. Drop the turbolinks, Action Cable and Active Storage npm packages that only those files referenced, and the public/packs ignore rules. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit a652def)
Pin bootstrap to the v6 alpha so the demo renders the markup this branch generates. v6 replaces Popper with Floating UI and adds vanilla-calendar-pro for its datepicker, so swap the peer packages accordingly. Its stylesheets use the Sass module system and need Sass 1.103+, so bump sass and switch the demo stylesheets from @import to @use. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit c16eb94)
Bring @floating-ui/dom, @rails/actiontext, bootstrap-icons, esbuild and trix up to their latest releases. The build scripts are unchanged and the demo builds and renders as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 8e9abae)
(cherry picked from commit a34d0eb)
Add a demo section per page of the Bootstrap 6 forms documentation: form field, form controls, disabled form, checkboxes, radios, switches, range, input groups, extended floating labels, form adorn, chips, combobox, datepicker, OTP input, password strength, layout variants, client-side validation and server-side validation states for every supported element. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 5cfa3d7)
Rails prefixes a form's namespace onto label `for` attributes and input ids, but the combobox toggle is rendered directly, so its id was left unprefixed and the label pointed at "ns_ns_user_status". Keep the id Rails sees unprefixed and prefix it only on the toggle button. Also key the error feedback off the same id so aria-describedby matches. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 58f7a25)
The hidden field that collection_check_boxes prepends shared its id with the group's label div, so every collection produced duplicate ids. Render it with hidden_field_tag and no id, as Rails does for its own helper. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 1a7b127)
The id passed to collection_check_boxes or collection_radio_buttons was deleted before rendering. Use it for the group's label id and aria-labelledby, and derive the shared error feedback id from it, so two collections of the same attribute on one page can be given distinct ids. The inputs themselves keep their value-based ids. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 10f8644)
Help text now carries an id derived from the control (or the group for collections), and the control's aria-describedby lists it alongside any validation feedback id, as Bootstrap's accessibility guidance recommends. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 27c6ec8)
Render the attribute's values as dismissible chips inside a chip-input container with a form-ghost text input, configured through a `chips` hash of data attributes like the OTP helper. Bootstrap has no submission integration for chips, which the docs now spell out. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 9b30d6c)
Bootstrap 6 puts theme colors, sizes and custom widths on the `switch` wrapper rather than the checkbox. Accept a string of classes or a hash of attributes in the `switch` option so they can be set from the helper. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit e79f065)
Bootstrap 6 puts theme classes and `data-bs-bubble` on the `form-range`
wrapper. Accept `range: "theme-primary"` or
`range: { bubble: true, class: "..." }` on range_field to set them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG
(cherry picked from commit 979b940)
Support option groups rendered as menu headers, per-item icons, descriptions and disabled state, optional check icons for single select, a disabled toggle via the html options, and a `combobox` hash for placement, offset, boundary and accent-insensitive search. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit abfc784)
`inline: true` renders an always-visible calendar in a div with a hidden input that Bootstrap binds for form submission, pre-selecting the attribute's value. `button:` renders Bootstrap's button trigger with a display span, optionally with an icon. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 8ac394b)
`strength: { level: :good }` renders Bootstrap's CSS-only strength meter
with the level in data-bs-strength and the matching segments active, and
`text:` accepts a string for a static message.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG
(cherry picked from commit 1841dac)
Combining `floating: true` with `prepend` or `append` now renders the form-floating wrapper (label and input) inside the input-group, with the validation feedback as a sibling in the form field, matching the docs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 5666781)
Every helper now accepts `invalid_feedback:` and `valid_feedback:` for browser-validation messages (a model error replaces the static invalid one), `tooltip: true` for Bootstrap's tooltip-style feedback, and `valid: true` for the is-valid success state. Feedback rendering is centralised in generate_feedback so text fields, selects, checks, radios, OTP, combobox, chip and datepicker fields all behave the same. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 08a4d89)
The form-adorn wrapper is now a label with the adornment aria-hidden, as in the Bootstrap docs, and it carries the is-invalid/is-valid state along with the ghost input. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 71a3760)
`card: true` renders Bootstrap's form-field-card variant for a checkbox or radio, which with `help` gives the docs' group cards. A form_group label whose `for` matches no element in the group (e.g. above a set of radios or a date_select) now has the attribute removed instead of pointing at nothing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 27bbd71)
…trap's JS Bootstrap auto-initialises every strength meter and re-evaluates the neighbouring password field, which overwrote a static `level:`; a static meter now points data-bs-input at a selector that matches nothing. Rendering an inline calendar into the datepicker element wiped the hidden input Bootstrap binds for submission, so the calendar is now mounted on a child element through data-bs-position-element. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 031a52e)
Drive the combobox, chips, OTP, datepicker, strength, range, switch, card and validation examples like a user and assert on the resulting values. Add Bootstrap's client-side validation starter script to the demo layout so invalid forms don't submit, and fix the README adorn example that referenced a helper the demo doesn't have. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit ae2b25e)
Apply RuboCop's corrections to the component system test, give the range bubble examples room above the track, and size the datepicker button triggers to their content. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit 6c723ea)
Bootstrap's floating label is positioned against the full height of its wrapper, so help text or validation feedback inside `.form-floating` pushed the label onto the value. Floating fields now render a regular form-field group with a form-floating wrapper around only the label and control (inside the input group, if any), and the label is generated before the group strips the label options so custom text is kept. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit d16ab30)
Run the demo's README and index screenshot system tests against the updated gem and demo: the README's generated HTML blocks now reflect the current mark-up (help ids, floating label structure, chips, combobox, datepicker and validation helpers), and the index baselines cover all 29 demo sections. The index test grows the browser window to each section's height so tall sections can be cropped, and the combobox reads the attribute value only when the object responds to it, so README examples with non-model attributes render. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KwMXFtvXUNo65gxKB2X2nG (cherry picked from commit bd82efb)
The demo layout carried an inline copy of the datetime-select rule the gem ships in app/assets/stylesheets/rails_bootstrap_forms.css. Add the gem's stylesheet directory to the Sass load path and @use the stylesheet from the demo's bundle instead, which also exercises the install path the README documents. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 68e4dd1)
Every other npm package is already on its latest release; Bootstrap stays on the 6.0.0-alpha.1 "next" tag. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 9c08aa8)
(cherry picked from commit f1ca36f)
The JavaScript bundle imports Trix, but its CSS was never loaded: the two Action Text stylesheets left over from the Sprockets setup were not part of the Sass bundle, so the rich text editor rendered unstyled. Rewrite actiontext.scss for the Sass module system, @use it from the bundle entry, and drop the redundant actiontext.css. Update the two screenshots that show the editor. The datepicker system test now closes the popup before using the inline calendar: Bootstrap keeps the popup open after a pick, and dismissing it with a click elsewhere refocuses and scrolls to its input mid-click. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit bd32281)
Replace the hand-written Sass wrapper with the stylesheet that `rails action_text:install` generates for Rails 8.1, which inlines the Trix styles and the attachment gallery overrides as plain CSS. Sass loads it into the bundle through the existing @use. The install generator also produced Active Storage and Action Text migrations; those tables already exist in db/schema.rb, so the migrations were dropped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit f213b3e)
…iables Bootstrap 6 writes its custom properties unprefixed in Sass and relies on postcss-prefix-custom-properties to add the `bs-` prefix at build time. The demo compiled the Sass directly, so the CSS read `--range-fill` while Bootstrap's range plugin wrote `--bs-range-fill`: the track never filled and the value bubble stayed pinned at the start of the slider. Follow cssbundling-rails's Bootstrap recipe: split the CSS build into a Sass compile and a PostCSS pass (prefixing plus Autoprefixer), and watch with nodemon in Procfile.dev. The range system test now asserts that the bubble moves with the value, and the range screenshots are regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 7eb80ae)
Wrap the spinner markup and a long script line, use a hash assignment instead of merge!, and order the gems in the 8.0 gemfile, so that `rubocop` reports no offences and CI passes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 4fc558b11aea4aea06830461ef4e33ad76c0334f)
Point the install section at the Bootstrap 6 pre-release and its peer dependencies, explain the PostCSS prefixing step that Bootstrap 6 requires when compiling its Sass, and note that the bootstrap rubygem doesn't package Bootstrap 6. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 1951c2894b3a481d7ca0f4cde99edb5a4b8d08e8)
Rails 7.2 leaves an explicit label `for` untouched while the control's id gets the form namespace, so the group label pointed at a non-existent id and was detached. Namespace it ourselves on Rails 7. The new tests also expected hidden fields without `autocomplete="off"`, which only Rails 8.1 drops; use the existing helper for that attribute. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 6cbfa677f646a0c32b6465c2af5cc071edee15be)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
|
Super interesting work, @pardeyke . Thank you. I will need some time to digest this. I've always felt that the implementation of |
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.
Summary
Ports
bootstrap_formto Bootstrap 6 (currently 6.0.0-alpha.1) and bumps the gem to6.0.0.alpha1. Opened as a draft because Bootstrap 6 is still in alpha; the aim is to get the port in front of maintainers early and align on direction. Happy to split this into smaller PRs if that's preferred.Markup changes
form-fieldgrid; horizontal and inline layouts keepmb-3. Labels come before controls, help text usesform-text.check,radioand.switchwrapper markup.switch:accepts classes or attributes for the wrapper;card: truerendersform-field-card.form-rangewrapper withform-range-input;range:sets wrapper classes andbubble: true.form-adornadornments follow the v6 docs, including floating labels nested inside input groups.invalid_feedback:,valid_feedback:,tooltip: trueandvalid: trueon every helper;is-valid/is-invalidplacement per the v6 docs;form[data-bs-validate]client-side validation covered in the demo.aria-describedby.btn-solid theme-*, alerts usetheme-danger, legacyform-selectis gone (v6 folds it intoform-control).New helpers
combobox(single/multi, search, groups, icons, descriptions, disabled items,combobox:hash for thedata-bs-*options)datepicker_field(popup,inline: truewith a bound hidden input,button:trigger)chip_inputotp_fieldstrength:onpassword_field, including staticlevel:Demo app
postcss-prefix-custom-properties. Bootstrap 6 adds itsbs-variable prefix at build time and its JS expects the prefixed names; without the step the range fill and bubble silently don't move. Reported upstream in v6: JS plugins hardcode the bs- variable prefix, so Sass compiled without postcss-prefix-custom-properties breaks range (fill + bubble) twbs/bootstrap#43098, and documented in the README install section.Screenshots and README
The README examples and screenshot baselines were regenerated because the generated markup changed throughout; the screenshot diffs are intentional. Note the screenshot-commit step in the workflow is currently commented out, so CI won't add a screenshot commit here.
Checklist (CONTRIBUTING.md)
rubocopreports no offencesbin/rails test:allgreen (18 runs)Notes for reviewers
demo/.ruby-versionis set to 4.0.7 rather than the oldest supported Ruby; CI still runs the matrix down to 3.2.for(Rails 8 does), so the group label namespaces it itself on Rails 7.turbo_submits_withoption that was on this branch earlier has been removed from it; that change lives in add option submits_with to button #783.🤖 Generated with Claude Code