diff --git a/.changeset/angry-lemons-shop.md b/.changeset/angry-lemons-shop.md deleted file mode 100644 index 8c3181d510..0000000000 --- a/.changeset/angry-lemons-shop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rhds/elements": patch ---- - -``: fixed issue that stop tabs from correctly resizing on mobile diff --git a/.changeset/empty-suns-sip.md b/.changeset/empty-suns-sip.md new file mode 100644 index 0000000000..d96575fbd9 --- /dev/null +++ b/.changeset/empty-suns-sip.md @@ -0,0 +1,5 @@ +--- +"@rhds/elements": patch +--- + +``: corrected icon slot visibility with a slotted icon diff --git a/.changeset/itchy-tools-marry.md b/.changeset/itchy-tools-marry.md new file mode 100644 index 0000000000..45b6a0668a --- /dev/null +++ b/.changeset/itchy-tools-marry.md @@ -0,0 +1,5 @@ +--- +"@rhds/elements": patch +--- + +``: ensure that `cancel`, `open`, and `closed` events fire diff --git a/.changeset/late-shrimps-shake.md b/.changeset/late-shrimps-shake.md deleted file mode 100644 index 706b791b51..0000000000 --- a/.changeset/late-shrimps-shake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rhds/elements": patch ---- - -``: fixed issue with click target area of tile \ No newline at end of file diff --git a/.changeset/sixty-lemons-smoke.md b/.changeset/sixty-lemons-smoke.md deleted file mode 100644 index 8793a51259..0000000000 --- a/.changeset/sixty-lemons-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rhds/elements": patch ---- - -``: corrected custom background hover color tokens. diff --git a/.changeset/swift-starfishes-perform.md b/.changeset/swift-starfishes-perform.md deleted file mode 100644 index e2a67cb3a4..0000000000 --- a/.changeset/swift-starfishes-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rhds/elements": patch ---- - -``: improved documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index f9dcffa6d0..9ee41dadd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # @rhds/elements +## 1.3.1 + +### Patch Changes + +- d87dfb94a: ``: fixed issue that stop tabs from correctly resizing on mobile +- 01f100cf8: ``: fixed issue with click target area of tile +- 08722dd71: ``: corrected custom background hover color tokens. +- 4259ba0ed: ``: improved documentation + ## 1.3.0 ### Minor Changes diff --git a/elements/rh-dialog/demo/events.html b/elements/rh-dialog/demo/events.html new file mode 100644 index 0000000000..f3e55d7310 --- /dev/null +++ b/elements/rh-dialog/demo/events.html @@ -0,0 +1,37 @@ +
+ +

Modal dialog with a header

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt + ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu + fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit + anim id est laborum.

+ + Learn more + +
+ Open +
+ Events Fired + No events yet +
+
+ + + diff --git a/elements/rh-dialog/rh-dialog.ts b/elements/rh-dialog/rh-dialog.ts index 66411dba6b..4a2b32fef4 100644 --- a/elements/rh-dialog/rh-dialog.ts +++ b/elements/rh-dialog/rh-dialog.ts @@ -10,10 +10,11 @@ import { ScreenSizeController } from '../../lib/ScreenSizeController.js'; import styles from './rh-dialog.css'; -import '@rhds/elements/rh-surface/rh-surface.js'; import { query } from 'lit/decorators/query.js'; import { ifDefined } from 'lit/directives/if-defined.js'; +import '@rhds/elements/rh-surface/rh-surface.js'; + export class DialogCancelEvent extends Event { constructor() { super('cancel', { bubbles: true, cancelable: true }); @@ -40,16 +41,6 @@ async function pauseYoutube(iframe: HTMLIFrameElement) { await pauseVideo(iframe); } -function openChanged(this: RhDialog, oldValue: unknown) { - if (this.type === 'video' && oldValue === true && this.open === false) { - this.querySelector('video')?.pause?.(); - const iframe = this.querySelector('iframe'); - if (iframe?.src.match(/youtube/)) { - pauseYoutube(iframe); - } - } -} - /** * A dialog displays important information to users without requiring them to navigate away from the page. * @summary Communicates information requiring user input or action @@ -94,7 +85,7 @@ export class RhDialog extends LitElement { */ @property({ reflect: true }) position?: 'top'; - @observed(openChanged) + @observed @property({ type: Boolean, reflect: true }) open = false; /** Optional ID of the trigger element */ @@ -204,9 +195,19 @@ export class RhDialog extends LitElement { } protected async _openChanged(oldValue?: boolean, newValue?: boolean) { - // loosening types to prevent running these effects in unexpected circumstances - // eslint-disable-next-line eqeqeq - if (oldValue == null || newValue == null || oldValue == newValue) { + if (this.type === 'video') { + if (oldValue === true && this.open === false) { + this.querySelector('video')?.pause?.(); + const iframe = this.querySelector('iframe'); + if (iframe?.src.match(/youtube/)) { + pauseYoutube(iframe); + } + } + } else if (oldValue == null || + newValue == null || + // loosening types to prevent running these effects in unexpected circumstances + // eslint-disable-next-line eqeqeq + oldValue == newValue) { return; } else if (this.open) { // This prevents background scroll diff --git a/elements/rh-dialog/test/rh-dialog.spec.ts b/elements/rh-dialog/test/rh-dialog.spec.ts index 221308cf21..70ca6e6c40 100644 --- a/elements/rh-dialog/test/rh-dialog.spec.ts +++ b/elements/rh-dialog/test/rh-dialog.spec.ts @@ -1,18 +1,97 @@ -import { expect, html } from '@open-wc/testing'; +import { expect, html, oneEvent } from '@open-wc/testing'; import { createFixture } from '@patternfly/pfe-tools/test/create-fixture.js'; +import { clickElementAtOffset } from '@patternfly/pfe-tools/test/utils.js'; +import { sendKeys } from '@web/test-runner-commands'; import { RhDialog } from '@rhds/elements/rh-dialog/rh-dialog.js'; +import { RhButton } from '@rhds/elements/rh-button/rh-button.js'; -const element = html` - -`; +function press(key: string) { + return async function() { + await sendKeys({ press: key }); + }; +} describe('', function() { it('should upgrade', async function() { - const el = await createFixture(element); + const el = await createFixture(html` + + `); const klass = customElements.get('rh-dialog'); expect(el) .to.be.an.instanceOf(klass) .and .to.be.an.instanceOf(RhDialog); }); + describe('with a trigger', function() { + let element: RhDialog; + let trigger: RhButton; + const updateComplete = () => element.updateComplete; + beforeEach(async function() { + element = await createFixture(html` + +

Header

+

Body

+ Footer Action +
+ Open + `); + trigger = document.getElementById('trigger')!; + }); + describe('clicking the trigger', function() { + let openEventPromise: Promise; + let closeEventPromise: Promise; + let cancelEventPromise: Promise; + beforeEach(function() { + openEventPromise = oneEvent(element, 'open'); + closeEventPromise = oneEvent(element, 'close'); + cancelEventPromise = oneEvent(element, 'cancel'); + }); + beforeEach(() => trigger.click()); + beforeEach(updateComplete); + it('opens the dialog', function() { + expect(element.open).to.be.true; + }); + it('fires "open" event', async function() { + const openEvent = await openEventPromise; + expect(openEvent.type).to.equal('open'); + }); + describe('pressing Escape', function() { + beforeEach(press('Escape')); + beforeEach(updateComplete); + it('closes the dialog', function() { + expect(element.open).to.be.false; + }); + it('fires the cancel event', async function() { + const cancelEvent = await cancelEventPromise; + expect(cancelEvent.type).to.equal('cancel'); + }); + }); + describe('clicking outside the dialog', function() { + beforeEach(() => clickElementAtOffset(document.body, [10, 10])); + beforeEach(updateComplete); + it('closes the dialog', function() { + expect(element.open).to.be.false; + }); + it('fires the cancel event', async function() { + const cancelEvent = await cancelEventPromise; + expect(cancelEvent.type).to.equal('cancel'); + }); + }); + describe('clicking the close button', function() { + // ordinarily we try our best to avoid querying the shadow root in test files + // in this case, we feel justified in making an exception, because the "close-button" + // css part is already included in the element's public API. + // NOTE: we query specifically for the element with that part, not by shadow class or id + beforeEach(() => element.shadowRoot.querySelector('[part="close-button"]')?.click()); + beforeEach(updateComplete); + it('closes the dialog', function() { + expect(element.open).to.be.false; + }); + it('fires the close event', async function() { + const closeEvent = await closeEventPromise; + expect(closeEvent.type).to.equal('close'); + }); + }); + }); + }); }); diff --git a/elements/rh-tile/demo/icon.html b/elements/rh-tile/demo/icon.html new file mode 100644 index 0000000000..4423dfca48 --- /dev/null +++ b/elements/rh-tile/demo/icon.html @@ -0,0 +1,36 @@ + + + +
Title
+

Link

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. +
Suspendisse eu turpis elementum
+
+ + + +
Title
+

Link

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. +
Suspendisse eu turpis elementum
+
+ + + +
Title
+

Link

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. +
Suspendisse eu turpis elementum
+
+ + + + + + diff --git a/elements/rh-tile/rh-tile.ts b/elements/rh-tile/rh-tile.ts index edca58e894..8f7a8f902f 100644 --- a/elements/rh-tile/rh-tile.ts +++ b/elements/rh-tile/rh-tile.ts @@ -8,6 +8,7 @@ import { state } from 'lit/decorators/state.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { InternalsController } from '@patternfly/pfe-core/controllers/internals-controller.js'; +import { SlotController } from '@patternfly/pfe-core/controllers/slot-controller.js'; import { Logger } from '@patternfly/pfe-core/controllers/logger.js'; import '@patternfly/elements/pf-icon/pf-icon.js'; @@ -145,6 +146,8 @@ export class RhTile extends LitElement { #logger = new Logger(this); + #slots = new SlotController(this, { slots: ['icon'] }); + get #isCheckable() { return !!this.radioGroup || this.checkable; } @@ -180,6 +183,7 @@ export class RhTile extends LitElement { render() { const { bleed, compact, checkable, checked, desaturated, on = '' } = this; const disabled = this.disabledGroup || this.disabled || this.#internals.formDisabled; + const hasSlottedIcon = this.#slots.getSlotted('icon').length > 0 ?? false; return html`
- - + + ${this.icon !== undefined ? + html`` + : html``}