Skip to content

Commit

Permalink
fix(core/button): pass through submit related events (#578)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielleroux committed Jun 15, 2023
1 parent 76f00d0 commit 8a0b410
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 11 deletions.
11 changes: 7 additions & 4 deletions packages/core/src/components/button/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@

@import 'common-variables';
@import './components/buttons';
@import 'mixins/shadow-dom/component';

:host {
@include ix-component;

display: inline-block;
width: auto;
height: 2rem;
vertical-align: middle;

&.disabled {
pointer-events: none;
}

.btn {
width: 100%;
height: 100%;
Expand All @@ -29,3 +28,7 @@
cursor: pointer;
}
}

:host(.disabled) {
pointer-events: none;
}
41 changes: 41 additions & 0 deletions packages/core/src/components/button/button.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2023 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { newSpecPage } from '@stencil/core/testing';
import { fireEvent } from '@testing-library/dom';
import { Button } from './button';

describe('button', () => {
it('form submit', async (done) => {
const page = await newSpecPage({
components: [Button],
html: `
<form>
<input type="text" />
<ix-button type="submit">Submit</ix-button>s
</form>
`,
});

await page.waitForChanges();
const btn = page.doc
.querySelector('ix-button[type="submit"]')
.shadowRoot.querySelector('button');

const form = page.doc.querySelector('form');

const onSubmit = jest.fn(() => {
done();
});

form.addEventListener('submit', onSubmit);
fireEvent.click(btn);

expect(onSubmit).toHaveBeenCalled();
});
});
15 changes: 14 additions & 1 deletion packages/core/src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* LICENSE file in the root directory of this source tree.
*/

import { Component, h, Host, Prop } from '@stencil/core';
import { Component, Element, h, Host, Prop } from '@stencil/core';
import { getButtonClasses } from './base-button';

export type ButtonVariant = 'Primary' | 'Secondary';
Expand Down Expand Up @@ -55,6 +55,18 @@ export class Button {
*/
@Prop() type: 'button' | 'submit' = 'button';

@Element() hostElement: HTMLIxButtonElement;

dispatchFormEvents() {
if (this.type === 'submit') {
const form = this.hostElement.closest('form');

if (form) {
form.dispatchEvent(new Event('submit'));
}
}
}

render() {
return (
<Host
Expand All @@ -63,6 +75,7 @@ export class Button {
}}
>
<button
onClick={() => this.dispatchFormEvents()}
type={this.type}
class={getButtonClasses(
this.variant,
Expand Down
50 changes: 50 additions & 0 deletions packages/core/src/components/button/test/button.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* SPDX-FileCopyrightText: 2023 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { newSpecPage } from '@stencil/core/testing';
import { fireEvent } from '@testing-library/dom';
import { Button } from '../button';

describe('button', () => {
it('should not be clickable with disabled prop', async () => {
const page = await newSpecPage({
components: [Button],
html: `<ix-button disabled>Example</ix-button>`,
});

await page.waitForChanges();
const btn = page.doc.querySelector('ix-button');
expect(btn.className).toContain('disabled');
});

it('should submit form if type is submit', async () => {
const page = await newSpecPage({
components: [Button],
html: `
<form>
<input name="some_input" />
<ix-button type="submit">Example</ix-button>
</form>
`,
});

await page.waitForChanges();
const submitButton = page.doc
.querySelector('ix-button')
.shadowRoot.querySelector('button');
const form = page.doc.querySelector('form');

const onSubmit = jest.fn();

form.addEventListener('submit', onSubmit);

fireEvent.click(submitButton);

expect(onSubmit).toHaveBeenCalled();
});
});
8 changes: 4 additions & 4 deletions packages/core/src/components/icon-button/icon-button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
display: inline-block;
vertical-align: middle;

&.disabled {
pointer-events: none;
}

.icon-button {
padding: 0;
overflow: hidden;
Expand All @@ -27,3 +23,7 @@
cursor: pointer;
}
}

:host(.disabled) {
pointer-events: none;
}
20 changes: 18 additions & 2 deletions packages/core/src/components/icon-button/icon-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* LICENSE file in the root directory of this source tree.
*/

import { Component, h, Host, Prop } from '@stencil/core';
import { Component, Element, h, Host, Prop } from '@stencil/core';
import { getButtonClasses } from '../button/base-button';
import { Button, ButtonVariant } from '../button/button';

Expand All @@ -19,6 +19,8 @@ export type IconButtonVariant = ButtonVariant;
shadow: true,
})
export class IconButton implements Button {
@Element() hostElement: HTMLIxIconButtonElement;

/**
* Variant of button
*/
Expand Down Expand Up @@ -76,6 +78,16 @@ export class IconButton implements Button {
*/
@Prop() type: 'button' | 'submit' = 'button';

dispatchFormEvents() {
if (this.type === 'submit') {
const form = this.hostElement.closest('form');

if (form) {
form.dispatchEvent(new Event('submit'));
}
}
}

private getIconSizeClass() {
return {
'btn-icon-12': this.size === '12',
Expand Down Expand Up @@ -103,7 +115,11 @@ export class IconButton implements Button {
render() {
return (
<Host class={{ ...this.getIconSizeClass(), disabled: this.disabled }}>
<button class={this.getIconButtonClasses()} type={this.type}>
<button
class={this.getIconButtonClasses()}
type={this.type}
onClick={() => this.dispatchFormEvents()}
>
<ix-icon size={this.size} name={this.icon} color={this.color} />
<div style={{ display: 'none' }}>
<slot></slot>
Expand Down

0 comments on commit 8a0b410

Please sign in to comment.