Skip to content

fix: prevent <button>'s from becoming form submit when they shouldn't #4221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extensions/emoji/js/src/forum/addComposerAutocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default function addComposerAutocomplete() {
return (
<Tooltip text={name}>
<button
type="button"
key={emoji}
onclick={() => applySuggestion(emoji)}
onmouseenter={function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class MentionsDropdownItem<CustomAttrs extends IMentionsDropdownI
const className = classList('MentionsDropdownItem', 'PostPreview', `MentionsDropdown-${mentionable.type()}`);

return (
<button className={className} {...attrs}>
<button className={className} type="button" {...attrs}>
<span className="PostPreview-content">{vnode.children}</span>
</button>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class PostQuoteButton extends Fragment {
return (
<button
className="Button PostQuoteButton"
type="button"
onclick={() => {
reply(this.post, this.content);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ export default class StatisticsWidget extends DashboardWidget {
return (
<button
className={classList('Button--ua-reset StatisticsWidget-entity', { active: this.selectedEntity === entity })}
type="button"
onclick={this.changeEntity.bind(this, entity)}
>
<h3 className="StatisticsWidget-heading">{app.translator.trans('flarum-statistics.admin.statistics.' + entity + '_heading')}</h3>
Expand Down
8 changes: 7 additions & 1 deletion framework/core/js/src/admin/components/AdminPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAt
*/
submitButton(): Mithril.Children {
return (
<Button onclick={this.saveSettings.bind(this)} className="Button Button--primary" loading={this.loading} disabled={!this.isChanged()}>
<Button
type="submit"
onclick={this.saveSettings.bind(this)}
className="Button Button--primary"
loading={this.loading}
disabled={!this.isChanged()}
>
{app.translator.trans('core.admin.settings.submit_button')}
</Button>
);
Expand Down
4 changes: 2 additions & 2 deletions framework/core/js/src/admin/components/PermissionsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ export default class PermissionsPage extends AdminPage {
.all<Group>('groups')
.filter((group) => [Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()!) === -1)
.map((group) => (
<button className="Button Group" onclick={() => app.modal.show(EditGroupModal, { group })}>
<button className="Button Group" type="button" onclick={() => app.modal.show(EditGroupModal, { group })}>
<GroupBadge group={group} className="Group-icon" label={null} />
<span className="Group-name">{group.namePlural()}</span>
</button>
))}
<button className="Button Group Group--add" onclick={() => app.modal.show(EditGroupModal)}>
<button className="Button Group Group--add" type="button" onclick={() => app.modal.show(EditGroupModal)}>
<Icon name="fas fa-plus" className="Group-icon" />
<span className="Group-name">{app.translator.trans('core.admin.permissions.new_group_button')}</span>
</button>
Expand Down
1 change: 1 addition & 0 deletions framework/core/js/src/admin/components/UserListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ export default class UserListPage extends AdminPage {
<button
onclick={toggleEmailVisibility}
className="Button Button--text UserList-emailIconBtn"
type="button"
title={app.translator.trans('core.admin.users.grid.columns.email.visibility_show')}
>
<Icon name="far fa-eye-slash fa-fw" className="icon" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class DetailedDropdownItem<
> extends Component<CustomAttrs> {
view() {
return (
<button className="DetailedDropdownItem hasIcon" onclick={this.attrs.onclick}>
<button type="button" className="DetailedDropdownItem hasIcon" onclick={this.attrs.onclick}>
<Icon name={this.attrs.active ? 'fas fa-check' : 'fas'} className="Button-icon" />
<span className="DetailedDropdownItem-content">
<Icon name={this.attrs.icon} className="Button-icon" />
Expand Down
1 change: 1 addition & 0 deletions framework/core/js/src/common/components/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export default class Dropdown<CustomAttrs extends IDropdownAttrs = IDropdownAttr
getButton(children: Mithril.ChildArray): Mithril.Vnode<any, any> {
let button = (
<button
type="button"
className={'Dropdown-toggle ' + this.attrs.buttonClassName}
aria-haspopup="menu"
aria-label={this.attrs.accessibleToggleLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default class SplitDropdown<CustomAttrs extends ISplitDropdownAttrs = ISp
<>
{button}
<button
type="button"
className={'Dropdown-toggle Button Button--icon ' + this.attrs.buttonClassName}
aria-haspopup="menu"
aria-label={this.attrs.accessibleToggleLabel}
Expand Down
1 change: 1 addition & 0 deletions framework/core/js/src/forum/components/AvatarEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default class AvatarEditor extends Component {
<div className={classList(['AvatarEditor', 'Dropdown', this.attrs.className, this.loading && 'loading', this.isDraggedOver && 'dragover'])}>
<Avatar user={user} loading="eager" />
<button
type="button"
className={user.avatarUrl() ? 'Dropdown-toggle' : 'Dropdown-toggle AvatarEditor--noAvatar'}
title={app.translator.trans('core.forum.user.avatar_upload_tooltip')}
ariaLabel={app.translator.trans('core.forum.user.avatar_upload_tooltip')}
Expand Down
1 change: 1 addition & 0 deletions framework/core/js/src/forum/components/PostMeta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default class PostMeta<CustomAttrs extends IPostMetaAttrs = IPostMetaAttr
items.add(
'time',
<button
type="button"
className={classList({
'Button Button--text': true,
'Dropdown-toggle Button--link': !!permalink,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default class PostStreamScrubber extends Component {

return (
<div className={classNames.join(' ')}>
<button className="Button Dropdown-toggle" data-toggle="dropdown">
<button type="button" className="Button Dropdown-toggle" data-toggle="dropdown">
{viewing} <Icon name={'fas fa-sort'} />
</button>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default class ReplyPlaceholder<CustomAttrs extends IReplyPlaceholderAttrs
});

return (
<button className="Post ReplyPlaceholder" onclick={reply}>
<button type="button" className="Post ReplyPlaceholder" onclick={reply}>
<div className="Post-container">
<div className="Post-side">
<Avatar user={app.session.user} className="Post-avatar" />
Expand Down
Loading