Add the FeedbackButton component.
This commit is contained in:
parent
c78d088d00
commit
dfeaa5db22
|
@ -0,0 +1,68 @@
|
||||||
|
import {html} from 'htm/preact';
|
||||||
|
import {Component, VNode} from 'preact';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component properties for {@linkcode FeedbackButton}.
|
||||||
|
*/
|
||||||
|
export type FeedbackButtonProps = {
|
||||||
|
click: (event: MouseEvent) => unknown;
|
||||||
|
extraAttributes: Record<string, string>;
|
||||||
|
feedbackText: string;
|
||||||
|
text: string;
|
||||||
|
timeout: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component state for {@linkcode FeedbackButton}.
|
||||||
|
*/
|
||||||
|
export type FeedbackButtonState = {
|
||||||
|
currentText: string;
|
||||||
|
timeoutHandle: number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@linkcode https://developer.mozilla.org/docs/Web/HTML/Element/button <button>}
|
||||||
|
* element wrapper that changes its text for a given time after being clicked.
|
||||||
|
*/
|
||||||
|
export class FeedbackButton extends Component<
|
||||||
|
FeedbackButtonProps,
|
||||||
|
FeedbackButtonState
|
||||||
|
> {
|
||||||
|
constructor(props: FeedbackButtonProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
currentText: this.props.text,
|
||||||
|
timeoutHandle: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
click = (event: MouseEvent) => {
|
||||||
|
this.props.click(event);
|
||||||
|
|
||||||
|
let {timeoutHandle} = this.state;
|
||||||
|
if (timeoutHandle !== undefined) {
|
||||||
|
window.clearTimeout(timeoutHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutHandle = window.setTimeout(() => {
|
||||||
|
this.setState({
|
||||||
|
currentText: this.props.text,
|
||||||
|
timeoutHandle: undefined,
|
||||||
|
});
|
||||||
|
}, this.props.timeout);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
currentText: this.props.feedbackText,
|
||||||
|
timeoutHandle,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render(): VNode {
|
||||||
|
return html`
|
||||||
|
<button ...${this.props.extraAttributes} onclick=${this.click}>
|
||||||
|
${this.state.currentText}
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
// Button Exports
|
// Button Exports
|
||||||
export * from './buttons/confirm-button.js';
|
export * from './buttons/confirm-button.js';
|
||||||
|
export * from './buttons/feedback-button.js';
|
||||||
|
|
||||||
// Link Exports
|
// Link Exports
|
||||||
export * from './links/privacy-link.js';
|
export * from './links/privacy-link.js';
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {GlobalRegistrator} from '@happy-dom/global-registrator';
|
||||||
|
import test from 'ava';
|
||||||
|
import {html} from 'htm/preact';
|
||||||
|
import {render} from 'preact';
|
||||||
|
|
||||||
|
import {FeedbackButton, FeedbackButtonProps} from '../../source/gram.js';
|
||||||
|
import {sleep} from '../utilities.js';
|
||||||
|
|
||||||
|
test.before(() => {
|
||||||
|
GlobalRegistrator.register();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('FeedbackButton', async (t) => {
|
||||||
|
t.plan(5);
|
||||||
|
|
||||||
|
const props: FeedbackButtonProps = {
|
||||||
|
click: (event) => t.true(event !== undefined),
|
||||||
|
extraAttributes: {
|
||||||
|
id: 'feedback-button',
|
||||||
|
},
|
||||||
|
feedbackText: 'Feedback Example',
|
||||||
|
text: 'Example',
|
||||||
|
timeout: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
render(html`<${FeedbackButton} ...${props} />`, document);
|
||||||
|
|
||||||
|
const buttonElement =
|
||||||
|
document.querySelector<HTMLButtonElement>('#feedback-button')!;
|
||||||
|
|
||||||
|
t.snapshot(buttonElement.outerHTML, 'Default state');
|
||||||
|
buttonElement.click();
|
||||||
|
|
||||||
|
// Wait for Preact to do its stuff.
|
||||||
|
await sleep();
|
||||||
|
|
||||||
|
t.snapshot(buttonElement.outerHTML, 'Feedback state');
|
||||||
|
buttonElement.click();
|
||||||
|
|
||||||
|
await sleep(props.timeout);
|
||||||
|
|
||||||
|
t.snapshot(buttonElement.outerHTML, 'Back to default state');
|
||||||
|
});
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Snapshot report for `tests/buttons/feedback-button.test.ts`
|
||||||
|
|
||||||
|
The actual snapshot is saved in `feedback-button.test.ts.snap`.
|
||||||
|
|
||||||
|
Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
|
## FeedbackButton
|
||||||
|
|
||||||
|
> Default state
|
||||||
|
|
||||||
|
'<button id="feedback-button">Example</button>'
|
||||||
|
|
||||||
|
> Feedback state
|
||||||
|
|
||||||
|
'<button id="feedback-button">Feedback Example</button>'
|
||||||
|
|
||||||
|
> Back to default state
|
||||||
|
|
||||||
|
'<button id="feedback-button">Example</button>'
|
Binary file not shown.
Loading…
Reference in New Issue