Commit 79d4c9bd authored by Jack Steinberg's avatar Jack Steinberg Committed by Commit Bot

Add toast type attribute support with IDL property and default styles

This change adds the toast type attribute and property
according to the PR on the toast explainer here:
https://github.com/jackbsteinberg/std-toast/pull/49

There is still work TODO on implementing this PR,
w.r.t the showToast type option, a11y behavior for warning / error,
and default features for those types (Infinity duration, closebutton, etc)

Additionally, a follow-up CL will come out to reconfigure the current
reflection tests for type and open to use established reflection test
methodology
(ex: https://cs.chromium.org/chromium/src/third_party/blink/web_tests/wpt_internal/std-switch/tentative/form-associated-basic.js)

Bug: 972945
Change-Id: I58c7079dc4f748928eea44103dece835e549986e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1708313
Commit-Queue: Jack Steinberg <jacksteinberg@chromium.org>
Reviewed-by: default avatarFergal Daly <fergal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680073}
parent 95dfe564
......@@ -13,6 +13,7 @@
import * as reflection from '../internal/reflection.mjs';
const DEFAULT_DURATION = 3000;
const TYPES = new Set(['success', 'warning', 'error']);
function stylesheetFactory() {
let stylesheet;
......@@ -38,6 +39,18 @@ function stylesheetFactory() {
.default-closebutton {
user-select: none;
}
:host([type=success i]) {
border-color: green;
}
:host([type=warning i]) {
border-color: orange;
}
:host([type=error i]) {
border-color: red;
}
`);
// TODO(jacksteinberg): use offset-block-end: / offset-inline-end: over bottom: / right:
// when implemented https://bugs.chromium.org/p/chromium/issues/detail?id=538475
......@@ -127,6 +140,25 @@ export class StdToastElement extends HTMLElement {
}
}
get type() {
const typeAttr = this.getAttribute('type');
if (typeAttr === null) {
return '';
}
const typeAttrLower = typeAttr.toLowerCase();
if (TYPES.has(typeAttrLower)) {
return typeAttrLower;
}
return '';
}
set type(val) {
this.setAttribute('type', val);
}
show({duration = DEFAULT_DURATION} = {}) {
this.setAttribute('open', '');
clearTimeout(this.#timeoutID);
......
......@@ -115,7 +115,48 @@ testToastElementAsync((t, toast) => {
}, 'toggling open attribute does not start timeout');
testToastElement((toast) => {
const permitted_properties = ['constructor', 'show', 'hide', 'toggle', 'open', 'action', 'closeButton'];
const permitted_properties = ['constructor', 'show', 'hide', 'toggle', 'open', 'action', 'closeButton', 'type'];
assert_array_equals(permitted_properties.sort(), Object.getOwnPropertyNames(toast.__proto__).sort());
}, 'toast only exposes certain properties');
testToastElement((toast) => {
assert_false(toast.hasAttribute('type'));
assert_equals(toast.type, '');
}, 'default type is empty string without attribute present');
testToastElement((toast) => {
toast.type = 'warning';
assert_equals(toast.getAttribute('type'), 'warning');
assert_equals(toast.type, 'warning');
}, 'setting type property to an enumerated value changes the type attribute to that value');
testToastElement((toast) => {
toast.type = 'WaRnInG';
assert_equals(toast.getAttribute('type'), 'WaRnInG');
assert_equals(toast.type, 'warning');
}, 'setting type property to an enumerated value is case-insensitive');
testToastElement((toast) => {
toast.type = ' WaRnInG ';
assert_equals(toast.getAttribute('type'), ' WaRnInG ');
assert_equals(toast.type, '');
}, 'setting type property to an enumerated value with whitespace does not work');
testToastElement((toast) => {
toast.type = 'test';
assert_equals(toast.type, '');
assert_equals(toast.getAttribute('type'), 'test');
}, 'setting type to a non-enumerated value sets the type property to empty string');
testToastElement((toast) => {
toast.setAttribute('type', 'test');
assert_equals(toast.type, '');
assert_equals(toast.getAttribute('type'), 'test');
}, 'setting type attribute to a non-enumerated value sets the type property to empty string');
testToastElement((toast) => {
toast.type = 'info';
assert_equals(toast.type, '');
assert_equals(toast.getAttribute('type'), 'info');
}, 'info was briefly a valid type, but no longer is, so it will return empty string');
</script>
......@@ -61,4 +61,40 @@ testToastElement((toast) => {
assertComputedStyleMapsEqual(toast, mockToast);
}, 'the computed style map of a closed unstyled toast is the same as a span given toast defaults');
</script>
\ No newline at end of file
testToastElement((toast) => {
toast.type = 'error';
const styles = window.getComputedStyle(toast);
assert_equals(styles.borderColor, 'rgb(255, 0, 0)');
}, 'changing type to error changes the border color to red');
testToastElement((toast) => {
toast.type = 'warning';
const styles = window.getComputedStyle(toast);
assert_equals(styles.borderColor, 'rgb(255, 165, 0)');
}, 'changing type to warning changes the border color to orange');
testToastElement((toast) => {
toast.type = 'success';
const styles = window.getComputedStyle(toast);
assert_equals(styles.borderColor, 'rgb(0, 128, 0)');
}, 'changing type to success changes the border color to green');
testToastElement((toast) => {
const styler = document.createElement('style');
styler.append(`
[type=error i] {
border-color: pink;
}
`);
document.querySelector('main').appendChild(styler);
toast.type = 'error';
const styles = window.getComputedStyle(toast);
assert_equals(styles.borderColor, 'rgb(255, 192, 203)');
}, 'outside styles can set type styles');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment