Problem/Motivation
The <button> tag is a long standing element in HTML
Per http://www.w3.org/TR/html4/interact/forms.html#h-17.5
Buttons created with the BUTTON element function just like buttons created with the INPUT element, but they offer richer rendering possibilities: the BUTTON element may have content. For example, a BUTTON element that contains an image functions like and may resemble an INPUT element whose type is set to "image", but the BUTTON element type allows content.
In themes, the <button> allows for much more advanced styling compared to <input />.
It also fixes an inconsistency in the Form API where elements are addressed as 'buttons' but are output as <input type="submit" />
Proposed resolution
Replace all submit <input />s with <button />s.
Remaining tasks
Manual testing
- Be sure to test with special characters within the button. Example the text
Next >should render without escaping the angle bracket.
User interface changes
Input submit buttons are consistently styled as buttons.
API changes
None
Original report by @sanguis
The tag is a long standing element in HTML (http://dev.w3.org/html5/markup/button.html), and it has not support in Drupal.
it is counter intuitive to label as a button a something that will output as a .
To add to this confusion the variable 'button_type' does noting but set a class in the output to a class of form-#BUTTON_TYPE with in the tag generated.
This means that to genreate a "reset button" I have to add it as a "markup" type form elemnt.
Beta phase evaluation
| Issue category | Task because it doesn't add any new features or fix any bugs |
|---|---|
| Issue priority | Normal because there is no community consensus this is a major issue |
| Unfrozen changes | Unfrozen because it only changes markup |
| Prioritized changes | The main goal of this issue is improving the Themer experience. |
| Disruption | Not disruptive. |
| Comment | File | Size | Author |
|---|
Issue fork drupal-1671190
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
cameron tod commentedComment #2
crobinson commentedRelated, but not a duplicate (providing this here for convenience):
#1342066: Document that buttons with the same #value need a unique #name for the form API to distinguish them, or change the form API to assign unique #names automatically
Comment #3
nod_We're dropping IE6/7 we can use button properly now.
Comment #4
sunAre there (semi-)official browser/UA/screenreader compatibility tables/stats for
<BUTTON type="submit" />anywhere?As you already noted in #1238484-72: Ability to mark the form buttons to be of a specific type (so that they can be styled differently):
That's a concern, actually. Most of the other IE-incompatible modernizations are frontend-related only and be easily made backwards-compatible again, I think.
This change though, would touch a range of bare Form API essentials, JS, CSS, theme functions, and whatnot all over the place, potentially hard or even impossible to get back to.
Comment #5
nod_All browsers except IE implements button properly, only IE8+ implements it properly, see last paragraph (at the very bottom of the page) http://msdn.microsoft.com/en-us/library/ie/ms535211(v=vs.85).aspx
And yes it's likely that it'll make it impossible for contrib to make D8 IE6/7 compatible. It would clean-up a lot of things though.
We don't support IE6/7 so that shouldn't be an issue. D7 is still around once again it all comes down to what "not supporting" means.
Comment #6
xjmI don't think preventing contrib from supporting IE7 is an option. That would prevent me from upgrading my employer's site to D8 a year (or less) ;) from now.
That said, does this proposal actually do that? Couldn't contrib just override the rendering of the element?
Comment #7
nod_Sure it can override the rendering, but the submit input will need to have the value "save" or "cancel" in english and not capitalized.
Comment #8
xjmAlso see:
http://drupal.org/node/1569578
I'm fine with IE7 being buggy without contrib. Not being able to use forms at all is not an option. Hopefully we can work around that in contrib.
Comment #9
nod_Need to wait for IE7 to be truly forsaken in core and contrib :(
Comment #10
idebr commentedThe time is now! Worldwide browser share for IE7 has dropped below 1% based on https://www.netmarketshare.com/.
@xjm in #8
IE7 will submit forms just fine with a button element with the current markup. Contrib themes/modules can also override the button template file to revert buttons to an input tag if absolutely necessary.
Core already uses
<button>elements, for example in #1719640: Use 'button' element instead of empty linksComment #12
nod_We use buttons but never for form submit, only JS things.
Comment #13
idebr commented@_nod Ah yes, thanks for setting the record straight :)
Let's see how many failures are left
Comment #15
idebr commentedThis should fix the remaining tests. I have updated the issue summary and included a beta evaluation.
@nod_ in #7
Submit buttons already have a wide variation of labels currently in HEAD.
I suppose this will warrants a change record as well?
Comment #16
idebr commentedComment #17
nod_I belive the benefit of going with button is that we can finally remove that type of code from form processing:
And replace is with a more sensible:
Because the value and the text displayed for button can be different. Granted that is the only use of get op that I could find. D7 is littered with that kind of stuff so I guess it's much less important now.
Comment #22
idebr commentedStraight reroll of #16
Comment #24
idebr commentedThis should fix the failing test.
Comment #25
nod_For what it's worth, the issue doesn't introduce visual regressions as far as I can see and forms are still working.
It's all about what we want to do with IE7, I'd say we can forsake it and go with this patch. Needs reroll though, almost all the JS files have changed in the last 2 days and it doesn't apply cleanly.
Comment #27
Lucasljj commentedreroll of #24
Comment #28
Lucasljj commentedops... fix the path of Drupal core `-`
Comment #29
nod_Comment #32
Lucasljj commentedreroll after Rewrite Views UI CSS inline with our CSS standards - Part 1 changed some css files
Comment #33
Lucasljj commentedadded a related issue
Comment #37
Lucasljj commented:)
Comment #38
nod_Comment #39
Lucasljj commentedsome screenshots
Comment #40
Lucasljj commentedthe other attributes are not enough to "hide" the tag
Comment #41
Lucasljj commentedI did some manual testing, in views, admin/content, search page, node/1 (with lorem ipsum), node/1/edit and several other administration pages, I noticed that the previous patch(#37) contains some minor bugs
Size of *input type=button* is smaller than *button* tag in Bartik theme
- Fixed in #40 :)
Views current display not show - image after
- Fixed in #40, changes below :)
Others...
- Fixed :)
Comment #44
Lucasljj commentedRe-roll #40
Comment #45
Lucasljj commentedevoke the bot
Comment #47
Lucasljj commented*fix core location in the previous patch*
re-roll of #40
and... i think this should in 8.0.x because most of css frameworks stopped mentioning <input type="button"> as a button or not fully support the input element as button, some even require extra work to be displayed similarly to tag <button>
http://getbootstrap.com/css/#buttons
http://semantic-ui.com/elements/button.html
http://www.getmdl.io/components/index.html
http://getuikit.com/docs/button.html
http://purecss.io/buttons/
check out the pages and search for some input, input type="button" or input type="submit"
Comment #48
Lucasljj commentedComment #50
Lucasljj commentedThis can not be done in a minor release, since that would break existing themes :(
Comment #51
tim.plunkettIt could be written as opt-in though.
Comment #52
Lucasljj commentedWhat do you think of a optional flag in mytheme.info.yml file like this "button-tag: true"
the flag can be checked in the pre-processing layer of the button(input type=button) and, based on the flag, the render template for all buttons on theme can be replaced
this keeps the BC layer for old themes
Comment #53
droplet commentedIt's worth to create a new issue for D8.1 to apply these CSS. Therefore we have better decoupled CSS.
Optional doesn't a good idea. We didn't have a template engine in JS to handle these stuff.
Comment #55
vg3095 commentedPatch needs a re-roll
Comment #56
cameron tod commentedHere's a reroll.
Comment #58
dawehnerIn an ideal world we would split up the patch into two pieces:
Comment #64
tea.time commentedThis issue has been quiet for awhile, but I just ran into something related to it.
I briefly tried replacing a Views exposed form's
<input type="submit" />with a<button type="submit">, and discovered that AJAX handling does not get attached because in ajax_view.es6.js,Drupal.views.ajaxView.prototype.attachExposedFormAjax(), the selector explicitly looks for'input[type=submit]'. I don't see that change included in the last patch (#56).Comment #66
pcambraFollowing up on #64, the bits where the button ajax are fixed are in #1551534: Submit buttons themed as <button> element fail to trigger ajax in Views exposed forms
Comment #67
idebr commentedClosed #3070446: Use <button type="submit"> instead <input type=submit> in Drupal forms (login etc.) by default for better styling opportunities as a duplicate issue.
Comment #69
mlncn commented@dawehner so the idea of splitting up would be to add a new form element? With using it (opting in) is as easy as changing
'#type' => 'submit'to'#type' => 'button'? (Or perhapssubmit_button?)Comment #71
bburgI'm running into this trying to add a button with an attached ajax behavior that performs a validation. This makes it very challenging to work around issues when the form is submitted. I've had to avoid injecting the button while the form is being rebuilt during submission. So I think there is a good use case for this. See #3171142: Form does not reload with ajax element when it fails validation.
I haven't seen any discussion around how FormBuilder designates a "triggering element" by just grabbing the first button on the form. I'd assume that would need to be a little smarter to handle this.
Comment #74
chr.fritschLet's restart this.
First, let's see how many tests are failing. Second, we need some BC mode I guess.
Comment #75
mdupontComment #76
effulgentsia commentedhttps://dispatcher.drupalci.org/job/drupal_patches/86958/ shows some of the failures for #74.
I just now committed #1551534: Submit buttons themed as <button> element fail to trigger ajax in Views exposed forms, but that by far was not the only bug.
Comment #77
danielvezaI'm implementing an external design system that has it's submits as buttons. I've done the twig work for this to work but now of course AJAX is broken since it's not being attached.
Taking a step back from this issue since it's taking a long time, I'm suggesting a smaller patch for progresses sake that just allows us to use buttons, even if core doesn't ship them out of the box.
This is mainly here so I can pull it through with composer, but I hope it can provide some value or thoughts too.
Comment #78
mdupontIsn't it a similar patch to @effulgentsia's one at #1551534: Submit buttons themed as <button> element fail to trigger ajax in Views exposed forms, which has been committed in Drupal 9.3?
Comment #79
andypostYes, patch in #77 is a copy so I hide it
Also hide all other useless for ro-roll patches
Comment #80
anweshasinha commentedHi,
I have applied a patch. Please review my work.
Comment #81
andypostthank you but it's not patch from #74
now needs work to fix 14 failed tests https://dispatcher.drupalci.org/job/drupal_patches/94277/
Comment #82
vsujeetkumar commentedFixed fail tests, Please have a look.
Comment #83
danielvezaOh how did I miss that? I checked first and rolled it against a fresh core.. Must have accidentally done 9.2
Comment #84
mdupontSome of the test fixes in #82 do not seem to come from introducing <button>, are they fixing unrelated bugs?
Comment #85
mdupontMy concern is that the current approach is breaking BC since it changes the default output of the Button render element.
I would rather use a different approach. First, support outputting <button> but still default to <input>. Then maybe switch to using <button> by default in Drupal 10 or another major release.
Note that the Olivero theme already uses the <button> tag in a custom template.
I would re-use the pattern from Dropbutton to provide different values to
#theme_wrappersdepending on the context.Basic patch attached to validate the approach, before fixing bugs and adding the necessary tests.
Comment #86
mdupontI started working on an issue fork: https://git.drupalcode.org/issue/drupal-1671190/-/compare/9.3.x...167119...
The final goal is to allow outputting
<button>when using form elements#button,#submitand#image_button, but still default to<input>in order to avoid breaking backward compatibility.Steps:
<button>from#button(DONE)<button>from#submit(DONE)<button>from#image_button, using an<input>tag<button>output<button>in addition to<input><button>in all core themes, so that it aligns as much as possible with<input>Comment #87
b-prod commentedPlease note that replacing all inputs may cause issues with some modules, e.g. Field UI, whose code expects precisely an input:
$('input[data-drupal-selector="edit-refresh"]').trigger('mousedown');Ideally, the JS code from Field UI should be adapted, after the "button by default" feature is ready.
Comment #88
b-prod commentedPatch in #85 contains a syntax error.
Comment #89
slasher13Comment #92
jeroentComment #93
akhildev.cs commentedhi
patch #92 applied cleanly,
(it made changes at following files:- Applied patch core/includes/form.inc cleanly.Applied patch core/includes/theme.inc cleanly.Applied patch core/lib/Drupal/Core/Render/Element/Button.php cleanly.Applied patch core/modules/system/templates/button.html.twig cleanly.Applied patch core/themes/stable/templates/form/button.html.twig cleanly.Applied patch core/themes/stable9/templates/form/button.html.twig cleanly.)
but still appear,
node-edit:-< input data-drupal-selector="edit-submit" type="submit" id="edit-submit" name="op" value="Save" class="button button--primary js-form-submit form-submit" tabindex="-1">"
view exposed filter btn:-< input data-drupal-selector="edit-submit-content" type="submit" id="edit-submit-content" value="Filter" class="button js-form-submit form-submit" tabindex="-1">
Comment #94
andeersg commentedApplied the patch from #92, and added this:
The input element is correctly replaced with a button. And it looks right:
But when I press it the page reloads and the submitForm method is not called.
Comment #95
sthomen commentedThe patch in #92 seems to work just fine for my needs which was to replace the submit input on exposed views forms with a button.
All I had to do was to hook the form and add
$build['actions']['submit']['#uses_button_tag'] = true;.My only criticism is that the template variable is a bit cumbersome, you have to remember if it was "uses" or "use", but this is very minor.
Minimally intrusive and useful when you actually need to say have an icon submit button. Can we have this in core please?
Comment #96
nsciaccaThis patch seems to work for its intended purpose when setting the #uses_button_tag property. However, if you have Paragraphs installed and are using the default widget (previously Experimental widget) all the submit buttons throughout the widget form are duplicated.
Comment #97
sthomen commentedI can confirm #96, it duplicates the paragraphs buttons, even the collapse and dot-menu items.
My suspicions was that it's because of the use of #theme_wrappers; in the paragraph buttons they end up as:
I tried making a simple check that another input__submit wrapper wasn't added in the preprocess function if one already existed and that made the duplicates go away.
The code in ParagraphsWidget sets #theme_wrappers and this is the way I would expect/want the "API" for renderable elements to work but now that Button::preRenderButton has logic for setting the wrapper template it becomes complicated.
Should the preRenderButton code replace "input__submit" with "button__submit" if #uses_button_tag is set? What happens if a module (like paragraphs) has a specific wrapper template they want to use? Should it leave the wrapper alone if there already is one that matches the input__submit pattern?
I'm inclined to suggest putting the default for '#theme_wrappers' back into Button::getInfo() and then replacing input with button in any input__submit pattern in the list of wrappers, since #uses_button_tag (I still don't like the name) is the latecomer here I feel that making use of it should carry the weight of handling any overridden template.
Comment #100
sahil.goyal commentedI'm confirming that the patch #92 seems alright with the version 10.1.x so it still do not need to be rerolled. it applied successfully to 10.1.x successfully.
Comment #101
sahil.goyal commentedComment #102
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Tagging for accessibility in case this has unforeseen consequences
#92 includes stable which was removed.but skimming comments #93-#97 seems there is still work to be done.
Was also previously tagged for screenshots which would need to happen.
Thanks.
Comment #103
Deshna Chauhan commentedAdded patch against #92 in 10.1 version
Comment #104
bramdriesenHiding patch #103 as it is missing files.
/core/modules/system/templates/button.html.twig
/core/themes/stable/templates/form/button.html.twig
/core/themes/stable9/templates/form/button.html.twig
Please include interdiffs in your re-rolls. I also don't think a re-roll was needed as it was confirmed to apply to 10.1 in #100
Comment #105
circuscowboy commentedPer sthomen's comment on comment #97 I have adapted the patch to only add the new #theme_wrapper if one doesn't already exist. This allows the patch to work with paragraphs enabled.
Comment #106
circuscowboy commentedI guess it needs review again.
Comment #109
anybodyJust ran into this again when preparing the Drupal 10 Version (3.0x.) of the Homebox module. The issue clearly still exists and for theming it's really horrible that Drupal FAPI's
'#type' => 'button'forces an<input type="submit" .../>and there's no real button FAPI element.Are there any plans or initiatives planning to work on this area?
Comment #111
nod_moving to MR to get all the gitlab CI goodness.
Comment #112
anybodyHere's what I did in Homebox now to have buttons instead of input submit's for #ajax actions with the goal to use icons:
https://git.drupalcode.org/project/homebox/-/blob/3.0.x/src/Element/Home...
If it helps anyone :) It works, now we have a real button type.
Idea: We could provide this additional FAPI element in contrib first, in a similar way!
Comment #114
paulbeaney commentedBeen looking at this at Contrib Day after Lille Drupalcon but haven't been able to make any progress as it looks like the MR hasn't been rebased, and when manually rebased to drupal-1671190/11.x ended up with this error on /core/install.php.
Fatal error: Cannot redeclare format_size() (previously declared in /var/www/html/repos/drupal/core/includes/common.inc:141) in /var/www/html/core/includes/common.inc on line 143Looks like a manual rebase of this branch is required to bring everything up to date?
Comment #119
taran2lhi all,
I've created an alternative PR which follows recommendations from #58 by @dawenher:
The main difference is that we are not introducing any new form element properties but rather allowing usage of button whenever needed (#uses_button_tag feels weird and unnecessary imo)
The question is how far should we go with that approach as clearly
<button>element can do more, and atm it's not possible to achieve that, for exampleI would love to address those things here without any changes to the Drupal forms (there is only a single usage of #type => button across all core codebase) so impact of such changes is minimal (as most of the form will still be using input type=submit)
Then in the follow-up we can start converting some form elements from input type=submit to a button leveraging the new features of the latter, like in #17:
Comment #120
taran2lComment #121
dwwThanks for working on this, seems like a good improvement.
Adding
<code>tags to the first line of the summary, where<button>wasn't visible, making this confusing to read.Comment #122
smustgrave commentedDo the other themes need a template?
Seems like this would break contrib themes though that still have the input__submit templates.
Comment #123
vincepick commentedAdding screenshots and testing online using Simplytest now.
Comment #124
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #125
nod_Comment #126
vincepick commentedTesting and taking screenshots now.
Comment #127
vincepick commentedThe button can contain complex HTML content such as images, allowing for much more versatility. It can also be styled much more extensively with CSS. To implement buttons, all form elements rendered using '' can be replaced with elements.
For example, this button displays both an image and text, something not possible with ''
Before:
After, a button with an image in it:
Submit Form
Comment #128
smustgrave commentedSeems the solution is different then the issue summary proposal, can that be updated to reflect.
Can a draft change record be written.
Once the summary is clearer can ask the #accessibility channel if anyone can take a look.
Do have concern if this will impact the other themes or contrib ones but guess that will be covered under the manual testing.
Question though of adding
{{ children }}outside the button. Is that needed? Seems odd.Comment #129
seanbI had an issue in AJAX views not picking up
button[type=button]:I needed the following to fix it:
Comment #130
anybody@seanB would you suggest incorporating this into the general MR? Could you do it then?
Comment #132
b-prod commentedIf using the
valueproperty from theattributesvariable, the rendered string cannot contains HTML. It would be better to use the$element['#value']instead.For example:
<button{{ attributes }}>{{ element['#value'] }}</button>{{ children }}Comment #133
bramdriesenIs this duplicated by #289240: Allow #type 'button' that aren't form submits ? It's a bit of a different approach judging from the code changes. Will need a reroll anyway because there is a merge conflict.
Comment #134
divyansh.gupta commentedRebasing it.
Comment #135
divyansh.gupta commentedRebased and resolved a PHPStan error,
Please review.
Comment #136
seanbI don't think this is the same issue. Allowing input type "button" is not the same as switching input elements to button elements.
Comment #137
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #138
evilargest commentedAttaching a patch, created from the latest MR version. Works fine on 11.2.4After testing, I found that the patch actually breaks the inputs in some cases. Trying to see what's going on.
Comment #140
evilargest commentedComment #141
evilargest commentedAttaching a fixed patch for 11.2.4
Comment #142
egontinno commentedAttaching a patch for 11.2.4 witch combine #141 and #105 patches, so that icons can be used on buttons, but the button would still be a submit button, not just a button.
Comment #143
evilargest commentedReroll of #141 for 11.3.1
Comment #149
fskreuz commentedUpdated MR using branch
1671190-11.xto incorporate changes from branchesbutton,1671190-button-full-replace,11.x-1671190-138, and patch #143. Hid everything else to simplify things.Comment #150
fskreuz commentedComment #151
smustgrave commentedThere already appeared to be a multiple branches for 11.x can someone differentiate those. Normally would request work continue on the original 11.x branch but that ship long sailed, so will remove the reroll tag for that.
This was tagged for screenshots which appear to be missing from the summary so leaving that tag. Should be added before NR please.
Still needs accessibility review, this can be moved to NR for that
Change record appears missing, draft should be started before NR so it can be reviewed together.
Pipeline appears to have phpcs issue also.
Comment #152
mherchelI ran into an issue implementing this on one of my themes, and ran into an issue where Drupal was double escaping special characters.
The Webform module uses the text
Next >in their multistep form.I updated the IS to ensure we test for that.
Comment #154
prudloff commentedIndeed the MR causes double-escaping because it tries to print
{{ attributes.value }}but it is an AttributeString object.AttributeString::__toString() escapes the value and then Twig escapes it again.
Instead I think the preprocess should provide #value as a simple string that can be printed (and escaped) in the Twig template.
Probably something like this:
And then: