Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lightbox-media-viewer]: Auto-open and play media from targeted link #11253

Merged
merged 19 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6deb075
feat(lightbox): detect URL fragment to trigger the lightbox to open
m4olivei Dec 19, 2023
67d6540
feat(lightbox): move cta video trigger code into cta mixin
m4olivei Dec 19, 2023
81b196a
feat(lightbox): revert changes to the expressive modal, not needed
m4olivei Dec 19, 2023
bb5d9ae
feat(cta): adjust cta video trigger URL fragment name
m4olivei Dec 20, 2023
0470b61
chore(cta): document new cta URL fragment feature
m4olivei Dec 20, 2023
b5b302d
test(cta): add tests for the video cta type including url fragment
m4olivei Dec 20, 2023
6206680
Merge branch 'main' into feat/lightbox-url-trigger
m4olivei Dec 20, 2023
35f36a6
feat(cta): only trigger the first element with a given video id
m4olivei Dec 27, 2023
6a329a8
test(cta): adjust storybook param name
m4olivei Dec 27, 2023
7b532dc
Merge branch 'main' into feat/lightbox-url-trigger
m4olivei Dec 27, 2023
b5c81ad
Merge branch 'main' into feat/lightbox-url-trigger
m4olivei Jan 8, 2024
f270427
feat(cta): move url trigger logic to firstUpdated
m4olivei Jan 8, 2024
88c6fef
feat(cta): use strict equals check when looking at url hash
m4olivei Jan 8, 2024
7f153ba
Merge branch 'main' into feat/lightbox-url-trigger
m4olivei Jan 8, 2024
028a29d
Merge branch 'main' into feat/lightbox-url-trigger
m4olivei Jan 9, 2024
983f98f
feat(cta): adjust window to root for ssr
m4olivei Jan 9, 2024
d815657
fix(cta): fixes an error due to a bad selector
m4olivei Jan 9, 2024
bb500c5
Merge branch 'main' into feat/lightbox-url-trigger
kennylam Jan 10, 2024
c17d244
Merge branch 'main' into feat/lightbox-url-trigger
kennylam Jan 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/web-components/IMPLEMENTATION_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ There are some common behaviors in CTA components that are implemented by
attribute of `<a>` for `external` CTA types.
- [Use a hash link](https://github.com/carbon-design-system/carbon-for-ibm-dotcom/blob/v1.15.0-rc.0/packages/web-components/src/component-mixins/cta/cta.ts#L113-L122)
for `video` CTA types.
- Trigger a CTA video on page load using a `#cta-video-[video-id]` URL fragment.
For any page that includes a CTA component composed with `CTAMixin`, the CTA
will look for a URL fragment following the pattern `#cta-video-[video-id]`,
where `[video-id]` is the video id configured for the component. If there is a
match, the CTA will automatically be triggered, which in most cases will open
a lightbox and begin video playback (subject to browser auto-play policies).

### Video CTA

Expand Down
51 changes: 51 additions & 0 deletions packages/web-components/src/component-mixins/cta/cta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,57 @@ const CTAMixin = <T extends Constructor<HTMLElement>>(Base: T) => {
if (ctaType === CTA_TYPE.VIDEO && this.offsetWidth > 0) {
this._updateVideoThumbnailUrl();
}

// Once the eventRequestVideoData finishes and has set the videoName,
// check for the URL trigger meant to fire eventRunAction.
if (
ctaType === CTA_TYPE.VIDEO &&
href &&
changedProperties.has('videoName') &&
videoName
) {
this._checkUrlVideoTrigger();
}
m4olivei marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Check the URL for a fragment including the video id.
*
* If we find a URL fragment that includes the video id, we trigger the
* eventRunAction event, which for video will open the video and start
* playback in a lightbox. This is the same thing that happens when the user
* clicks on the CTA.
*/
_checkUrlVideoTrigger() {
const { ctaType, disabled, href, videoDescription, videoName } = this;
// Without a video id, or if the button is disabled, there is nothing to
// do here.
if (ctaType !== CTA_TYPE.VIDEO || !href || disabled) {
return;
}
// Only trigger for the first CTA with the video id in the page.
if (this.ownerDocument.querySelector(`[href='${href}']`) !== this) {
return;
}
const { eventRunAction } = this.constructor as typeof CTAMixinImpl;
const hash = window.location.hash;
m4olivei marked this conversation as resolved.
Show resolved Hide resolved
const urlTrigger = `cta-video-${href}`;

if (hash.includes(urlTrigger)) {
m4olivei marked this conversation as resolved.
Show resolved Hide resolved
this.dispatchEvent(
new CustomEvent(eventRunAction, {
bubbles: true,
cancelable: true,
composed: true,
detail: {
href,
ctaType,
videoName,
videoDescription,
},
})
);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2021, 2022
* Copyright IBM Corp. 2021, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand All @@ -15,13 +15,19 @@
*/
const _path = '/iframe.html?id=components-link-with-icon--default';

const _videoId = '0_ibuqxqbe';

const _videoPath = `/iframe.html?&id=components-link-with-icon--default&knob-CTA%20type%20(cta-type)=video&knob-Icon%20Position%20(icon-placement):=right&knob-Video%20ID%20(href)=${_videoId}`;

/**
* Defines the component selector.
*
* @type {string}
* @private
*/
const _selector = '[data-autoid="cds--link-with-icon"]';
const _selector = '[data-autoid="c4d--link-with-icon"]';

const _lightboxVideoPlayerSelector = 'c4d-lightbox-video-player';

/**
* Collection of test scenarios.
Expand All @@ -47,7 +53,9 @@ const _tests = [
.then(([copy]) => {
defaultCopy = copy.innerText.trim();
})
.visit(`${_path}&knob-Link%20text%20(unnamed%20slot)=${customCopyInput}`)
.visit(
`${_path}&knob-Link%20text%20(unnamed%20slot)=${customCopyInput}`
)
.get(_selector)
.should(([copy]) => {
customCopyOutput = copy.innerText.trim();
Expand All @@ -66,16 +74,18 @@ const _tests = [
.get(_selector)
.shadow()
.find('a')
.should($link => {
.should(($link) => {
defaultHref = $link.prop('href');

expect($link.prop('href')).not.to.be.empty;
})
.visit(`${_path}&knob-Link%20href%20(href)=${customHrefInput}`)
.visit(
`${_path}&knob-Content%20link%20href%20(href)=${customHrefInput}`
)
.get(_selector)
.shadow()
.find('a')
.should($link => {
.should(($link) => {
customHrefOutput = $link.prop('href');

expect(customHrefOutput).to.be.eq(customHrefInput);
Expand All @@ -94,16 +104,18 @@ const _tests = [
},
() => {
it('should check icon placements', () => {
['left', 'right'].forEach(placement => {
['left', 'right'].forEach((placement) => {
let $svg;
cy.visit(`${_path}&knob-Icon%20Position%20(icon-placement):=${placement}`)
cy.visit(
`${_path}&knob-Icon%20Position%20(icon-placement):=${placement}`
)
.get(_selector)
.then($elem => {
.then(($elem) => {
$svg = $elem.find('svg');
})
.shadow()
.find('a')
.should($link => {
.should(($link) => {
const svgPosition = $svg[0].getBoundingClientRect();
const textPosition = $link.find('span')[0].getBoundingClientRect();

Expand All @@ -123,20 +135,35 @@ const _tests = [
});
});
},
() => {
it('should replace the button title with the video title for a video cta type', () => {
cy.visit(_videoPath);
cy.get(_selector)
.shadow()
.find('a > span')
.should('contain.text', 'Mombo');
cy.get(_lightboxVideoPlayerSelector).should('not.exist');
});

it('should trigger the lightbox for video when using the right URL fragment', () => {
cy.visit(`${_videoPath}#cta-video-${_videoId}`);
cy.get(_lightboxVideoPlayerSelector).should('exist').and('be.visible');
});
},
];

describe('cds-link-with-icon | default (desktop)', () => {
beforeEach(() => {
cy.viewport(1280, 780);
});

_tests.forEach(test => test());
_tests.forEach((test) => test());
});

describe('cds-link-with-icon | default (mobile)', () => {
beforeEach(() => {
cy.viewport(375, 720);
});

_tests.forEach(test => test());
_tests.forEach((test) => test());
});
Loading