Skip to content

Commit

Permalink
Merge branch 'main' into staging/chansey
Browse files Browse the repository at this point in the history
  • Loading branch information
bennypowers authored Mar 28, 2024
2 parents b415fbb + 1d16407 commit 5ce0e5e
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 48 deletions.
5 changes: 0 additions & 5 deletions .changeset/angry-lemons-shop.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/empty-suns-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rhds/elements": patch
---

`<rh-tile>`: corrected icon slot visibility with a slotted icon
5 changes: 5 additions & 0 deletions .changeset/itchy-tools-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rhds/elements": patch
---

`<rh-dialog>`: ensure that `cancel`, `open`, and `closed` events fire
5 changes: 0 additions & 5 deletions .changeset/late-shrimps-shake.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/sixty-lemons-smoke.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/swift-starfishes-perform.md

This file was deleted.

9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @rhds/elements

## 1.3.1

### Patch Changes

- d87dfb94a: `<rh-tabs>`: fixed issue that stop tabs from correctly resizing on mobile
- 01f100cf8: `<rh-tile>`: fixed issue with click target area of tile
- 08722dd71: `<rh-table>`: corrected custom background hover color tokens.
- 4259ba0ed: `<rh-tabs>`: improved documentation

## 1.3.0

### Minor Changes
Expand Down
37 changes: 37 additions & 0 deletions elements/rh-dialog/demo/events.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<form id="dialog-events">
<rh-dialog id="dialog" trigger="trigger">
<h2 slot="header">Modal dialog with a header</h2>
<p>Lorem ipsum dolor sit amet, <a href="#foo">consectetur adipisicing</a> 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.</p>
<rh-cta>
<a href="#bar">Learn more</a>
</rh-cta>
</rh-dialog>
<rh-button id="trigger">Open</rh-button>
<fieldset>
<legend>Events Fired</legend>
<output name="events">No events yet</output>
</fieldset>
</form>

<script type="module">
import '@rhds/elements/rh-button/rh-button.js';
import '@rhds/elements/rh-cta/rh-cta.js';
import '@rhds/elements/rh-dialog/rh-dialog.js';

const dialog = document.getElementById('dialog');
const form = document.getElementById('dialog-events');
const events = [];
form.addEventListener('submit', e => e.preventDefault());
const onDialogEvent = event => {
events.push(event.type);
form.elements.events.value = events.join(', ');
};
dialog.addEventListener('close', onDialogEvent);
dialog.addEventListener('open', onDialogEvent);
dialog.addEventListener('cancel', onDialogEvent);
</script>

31 changes: 16 additions & 15 deletions elements/rh-dialog/rh-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand All @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down
89 changes: 84 additions & 5 deletions elements/rh-dialog/test/rh-dialog.spec.ts
Original file line number Diff line number Diff line change
@@ -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`
<rh-dialog></rh-dialog>
`;
function press(key: string) {
return async function() {
await sendKeys({ press: key });
};
}

describe('<rh-dialog>', function() {
it('should upgrade', async function() {
const el = await createFixture<RhDialog>(element);
const el = await createFixture<RhDialog>(html`
<rh-dialog></rh-dialog>
`);
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`
<rh-dialog trigger="trigger">
<h2 slot="header">Header</h2>
<p>Body</p>
<rh-button slot="footer">Footer Action</rh-button>
</rh-dialog>
<rh-button id="trigger">Open</rh-button>
`);
trigger = document.getElementById('trigger')!;
});
describe('clicking the trigger', function() {
let openEventPromise: Promise<Event>;
let closeEventPromise: Promise<Event>;
let cancelEventPromise: Promise<Event>;
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');
});
});
});
});
});
36 changes: 36 additions & 0 deletions elements/rh-tile/demo/icon.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!-- Slotted Icon -->
<rh-tile>
<img slot="icon" src="https://fakeimg.pl/24x24" alt="">
<div slot="title">Title</div>
<h2 slot="headline"><a href="#top">Link</a></h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<div slot="footer">Suspendisse eu turpis elementum</div>
</rh-tile>

<!-- PFE icon -->
<rh-tile icon="check-circle">
<div slot="title">Title</div>
<h2 slot="headline"><a href="#top">Link</a></h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<div slot="footer">Suspendisse eu turpis elementum</div>
</rh-tile>

<!-- No icon -->
<rh-tile>
<div slot="title">Title</div>
<h2 slot="headline"><a href="#top">Link</a></h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<div slot="footer">Suspendisse eu turpis elementum</div>
</rh-tile>

<script type="module">
import '@rhds/elements/rh-tile/rh-tile.js';
</script>

<link rel="stylesheet" href="../rh-tile-lightdom.css">

<style>
rh-tile {
margin-inline-end: var(--rh-space-md, 8px);
}
</style>
15 changes: 8 additions & 7 deletions elements/rh-tile/rh-tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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`
<div id="outer" class="${classMap({
bleed,
Expand All @@ -195,13 +199,10 @@ export class RhTile extends LitElement {
?hidden="${this.checkable}"
></slot>
<div id="inner">
<slot id="icon"
name="icon"
?hidden="${!this.icon}">
<pf-icon icon="${ifDefined(this.icon)}"
size="md"
set="far"
></pf-icon>
<slot id="icon" name="icon" ?hidden="${this.icon === undefined && !hasSlottedIcon}">
${this.icon !== undefined ?
html`<pf-icon icon="${ifDefined(this.icon)}" size="md" set="far"></pf-icon>`
: html``}
</slot>
<div id="content">
<div id="header">
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rhds/elements",
"version": "1.3.0",
"version": "1.3.1",
"description": "Red Hat Design System Elements",
"type": "module",
"license": "MIT",
Expand Down

0 comments on commit 5ce0e5e

Please sign in to comment.