From 09c946894bd1a33cb32628379daf031fe91ee11b Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 29 Aug 2023 09:57:58 -0400 Subject: [PATCH 01/26] fix(tabs-extended): add hyphens auto to handle word breaks (#10849) * fix(tabs-extended): add hyphens auto to handle long word breaks appropriately based on lang * fix(tabs-extended): add hyphens auto to accordion title * fix(tabs-extended): replace blank line --------- Co-authored-by: kennylam <909118+kennylam@users.noreply.github.com> --- .../scss/components/tabs-extended/_tabs-extended.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/styles/scss/components/tabs-extended/_tabs-extended.scss b/packages/styles/scss/components/tabs-extended/_tabs-extended.scss index 1f9f575f80f..ac1ed7a9c0c 100644 --- a/packages/styles/scss/components/tabs-extended/_tabs-extended.scss +++ b/packages/styles/scss/components/tabs-extended/_tabs-extended.scss @@ -109,7 +109,7 @@ overflow: hidden; height: 100%; line-height: 1.375rem; - word-break: break-word; + hyphens: auto; @include type-style('body-short-02'); } @@ -274,3 +274,7 @@ button.#{$prefix}--tabs__nav-link { button.#{$prefix}--tabs__nav-link:active { color: $text-02; } + +.#{$prefix}--accordion__title { + hyphens: auto; +} From 883a7e55873b81b1a8c7f73c675f339733f8703c Mon Sep 17 00:00:00 2001 From: Pauline Date: Tue, 29 Aug 2023 11:24:27 -0400 Subject: [PATCH 02/26] fix(docs): add documentation regarding the carbonElement decorator (#10871) ### Related Ticket(s) Closes #10278 ### Description This PR updates documentation to include information on the `@carbonElement` decorator and its usage. This will help ensure contributors use the decorator correctly and understand its purpose. ### Changelog **New** - Added a 'Custom Elements' heading to documentation; added information about `@carbonElement` decorator in a subheading to that. --- .../web-components/docs/coding-conventions.md | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/web-components/docs/coding-conventions.md b/packages/web-components/docs/coding-conventions.md index 167dce68aec..3c89698c993 100644 --- a/packages/web-components/docs/coding-conventions.md +++ b/packages/web-components/docs/coding-conventions.md @@ -29,8 +29,10 @@ - [Null checks](#null-checks) - [Updating view upon change in `private`/`protected` properties](#updating-view-upon-change-in-privateprotected-properties) - [Avoiding global `document`/`window` reference](#avoiding-global-documentwindow-reference) -- [Custom element registration](#custom-element-registration) -- [Custom element itself as an eleement](#custom-element-itself-as-an-eleement) +- [Custom Elements](#custom-elements) + - [@carbonElement Decorator](#carbon-element-decorator) + - [Custom element registration](#custom-element-registration) + - [Custom element itself as an element](#custom-element-itself-as-an-element) - [Propagating misc attributes from shadow host to an element in shadow DOM](#propagating-misc-attributes-from-shadow-host-to-an-element-in-shadow-dom) - [Private properties](#private-properties) - [Preferring class inheritance pattern over React composition pattern](#preferring-class-inheritance-pattern-over-react-composition-pattern) @@ -260,7 +262,7 @@ A component variant with different options can be created by creating a derived | CSS selectors/classes used in imperative DOM API calls (Doing so allows overriding `.render()` method) | `selectorNonSelectedItem` | An exception is where `lit-element`'s `@query` decorator is applicable | | [Custom event](#custom-events) names | `eventBeforeSelect` | | -#### Areas where component optinos are _not_ applied +#### Areas where component options are _not_ applied - CSS classes used in template (Should be done by overriding `.render()` method) @@ -437,7 +439,31 @@ To cause re-rendering upon change in `private`/`protected` properties, use `stat Global `document`/`window` can be different from the ones associated with custom element instance, when the custom element is transported to a different frame e.g. with `document.importNode()`. Though such cases are rare, the codebase avoids global `document`/`window` reference to keep ourselves in a good DOM citizen. We use [`element.ownerDocument`](https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument)/[`.element.ownerDocument.defaultView`](https://developer.mozilla.org/en-US/docs/Web/API/Document/defaultView), respectively, instead. -## Custom element registration +## Custom Elements +### @carbonElement Decorator + +We use a custom [`@carbonElement`](../../carbon-web-components/src/globals/decorators/carbon-element.ts) decorator instead of Lit's [`@customElement`](https://lit.dev/docs/v1/api/lit-element/decorators/#customElement), which doesn't provide a way to check if an element has already been defined in the window's `CustomElementRegistry`. If an attempt is made to redefine an element that has already been registered, an error will occur and any remaining code will fail to execute. + +`@carbonElement` is identical to `@customElement` with the exception that it gracefully handles any failures from duplicate registrations and continues executing the remainder of the running script. + +#### Usage + +1. Use this project's `carbon-element.ts` file to supply the decorator +2. Alias `@carbonElement` to `@customElement` + +The second item is **required** for proper creation of the react-wrapped components + +Example: + +```typescript +import { html, property, LitElement } from 'lit-element'; +import { carbonElement as customElement } from '../../globals/decorators/carbon-element'; + +@customElement(`${prefix}-accordion-item`) +class BXAccordionItem extends FocusMixin(LitElement) { + ... +``` +### Custom element registration This library registers custom elements to global `window` automatically upon importing the corresponding modules. It may not be desirable in two scenarios: @@ -445,7 +471,7 @@ It may not be desirable in two scenarios: - One is when consumer wants to customize our custom element's behavior before it's registered. In such case, consumer can create a derived class and register it with a different custom element name. - Another, though the use case is rare, is using our custom element in a different realm. In such case, consumer can re-register the custom element in the realm. -## Custom element itself as an eleement +### Custom element itself as an element In Custom Elements world, the custom element itself (the host of shadow DOM) itself is an element. From 29434ed90536fefe8473059332f5efa2e573ec0b Mon Sep 17 00:00:00 2001 From: John Kaeser Date: Tue, 29 Aug 2023 14:04:32 -0400 Subject: [PATCH 03/26] fix(lightbox-video-player): use more reliable reference to video player (#10878) ### Related Ticket(s) none ### Description `` can handle multiple Kaltura video embed requests within the same modal/lightbox by slotting a `
` per video into the same ``. When the modal is activated by user interaction, the current video ID is sent along, and the `` sets `hidden` on the `
`s that don't have a matching ID. This works great when there is only one ``. The problems start when multiple video containers are used throughout the document. Each creates some number modal render root elements depending on the structure of the content, and the lightbox composite uses `document.querySelector('dds-lightbox-video-player')` to find the video player when trying to hide embedded Kaltura videos that are not active. As we know, `querySelector` returns the first matching element, and since we've established there may be multiple of these video players in various modal render roots, sometimes it found the wrong one and failed to hide non-active videos. Luckily, the fix was pretty simple. Lightbox composites already have an internal reference to their video player, so I swapped out the document query to use that reference, which _should_ guarantee the composite is looking in the right place when hiding inactive videos. ### Changelog **Changed** - Ensure `` hides inactive videos by using an internal reference to modal's video player instead of querying for it from the document root. --- .../__stories__/card-group.stories.react.tsx | 201 ++++++++++++++---- .../__stories__/card-group.stories.ts | 10 +- .../lightbox-video-player-composite.ts | 7 +- 3 files changed, 166 insertions(+), 52 deletions(-) diff --git a/packages/web-components/src/components/card-group/__stories__/card-group.stories.react.tsx b/packages/web-components/src/components/card-group/__stories__/card-group.stories.react.tsx index 49da9decf00..f1f337360e8 100644 --- a/packages/web-components/src/components/card-group/__stories__/card-group.stories.react.tsx +++ b/packages/web-components/src/components/card-group/__stories__/card-group.stories.react.tsx @@ -1,7 +1,7 @@ /** * @license * - * Copyright IBM Corp. 2020, 2022 + * Copyright IBM Corp. 2020, 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. @@ -77,67 +77,119 @@ const textCTAContent = ( ); -const imageContent = ; +const imageContent = ( + +); -const cardsDiffLengthPhrase = (index, tagGroup, media, gridMode, cardType, addCta) => { +const cardsDiffLengthPhrase = ( + index, + tagGroup, + media, + gridMode, + cardType, + addCta +) => { const defaultCardGroupItem = ( + colorScheme={ + cardType === 'Card static' || gridMode === 'border' ? 'light' : null + }> {media ? imageContent : ''} Topic - {index < 5 ? phraseArray[index] : 'Lorem ipsum dolor sit amet'} -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et ultricies est.'

+ + {index < 5 ? phraseArray[index] : 'Lorem ipsum dolor sit amet'} + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et + ultricies est.' +

{tagGroup ? tagGroupContent : ''} - {cardType === 'Card static' && addCta ? textCTAContent : } + {cardType === 'Card static' && addCta ? ( + textCTAContent + ) : ( + + )}
); - const videoCardGroupItem = ( - + const videoCardGroupItem = (videoId = '1_9h94wo6b') => ( + Topic {tagGroup ? tagGroupContent : ''} - + ); + const demoVideoIds = ['1_9h94wo6b', '0_ibuqxqbe', '1_6b6qjovy']; + count = count > 3 ? 0 : count + 1; - return media && index % 2 ? videoCardGroupItem : defaultCardGroupItem; + return media && index % 2 + ? videoCardGroupItem(demoVideoIds[index % 3]) + : defaultCardGroupItem; }; -const longHeadingCardGroupItem = (tagGroup, media, gridMode, cardType, addCta) => { +const longHeadingCardGroupItem = ( + tagGroup, + media, + gridMode, + cardType, + addCta +) => { return ( + colorScheme={ + cardType === 'Card static' || gridMode === 'border' ? 'light' : null + }> {media ? imageContent : ''} Topic - Nunc convallis lobortis Nunc convallis lobortis Nunc convallis lobortis + + Nunc convallis lobortis Nunc convallis lobortis Nunc convallis lobortis +

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et ultricies est. Mauris iaculis eget dolor nec hendrerit. - Phasellus at elit sollicitudin, sodales nulla quis, consequat libero. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et + ultricies est. Mauris iaculis eget dolor nec hendrerit. Phasellus at + elit sollicitudin, sodales nulla quis, consequat libero.

{tagGroup ? tagGroupContent : ''} - {cardType === 'Card static' && addCta ? textCTAContent : } + {cardType === 'Card static' && addCta ? ( + textCTAContent + ) : ( + + )}
); }; -const pictogramCard = gridMode => ( - +const pictogramCard = (gridMode) => ( + Aerospace and defence

- Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Ut enim ad minim - veniam, quis nostrud exercitation. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Ut enim ad minim veniam, quis nostrud + exercitation.

); const cardLink = ( - + IBM Developer

Learn, code and connect with your community

@@ -149,15 +201,24 @@ const emptyCard = ; const cardInCardItems = (i, tagGroup, media, gridMode) => { if (media) { return i % 2 === 0 ? ( - + {imageContent} Label - The United Nations Environment Program works with IBM to reduce marine litter + + The United Nations Environment Program works with IBM to reduce marine + litter + {tagGroup ? tagGroupContent : ''} ) : ( - + Topic {tagGroup ? tagGroupContent : ''} @@ -165,17 +226,33 @@ const cardInCardItems = (i, tagGroup, media, gridMode) => { ); } return ( - + Label - The United Nations Environment Program works with IBM to reduce marine litter + + The United Nations Environment Program works with IBM to reduce marine + litter + {tagGroup ? tagGroupContent : ''} ); }; -export const Default = args => { - const { cards, cardType, media, tagGroup, cardsPerRow, gridMode, offset, cta, addCta } = args?.CardGroup ?? {}; +export const Default = (args) => { + const { + cards, + cardType, + media, + tagGroup, + cardsPerRow, + gridMode, + offset, + cta, + addCta, + } = args?.CardGroup ?? {}; const allCards: object[] = []; @@ -184,15 +261,24 @@ export const Default = args => { } if (cardType === 'Card - default') { - allCards.push(longHeadingCardGroupItem(tagGroup, media, gridMode, cardType, addCta)); + allCards.push( + longHeadingCardGroupItem(tagGroup, media, gridMode, cardType, addCta) + ); for (let i = 1; i < cards; i++) { - allCards.push(cardsDiffLengthPhrase(i, tagGroup, media, gridMode, cardType, addCta)); + allCards.push( + cardsDiffLengthPhrase(i, tagGroup, media, gridMode, cardType, addCta) + ); } if (cta) { allCards.push( - + Top level card link - + ); } @@ -205,13 +291,20 @@ export const Default = args => { } if (cardType === 'Card static') { - allCards.push(longHeadingCardGroupItem(tagGroup, media, gridMode, cardType, addCta)); + allCards.push( + longHeadingCardGroupItem(tagGroup, media, gridMode, cardType, addCta) + ); for (let i = 1; i < cards; i++) { - allCards.push(cardsDiffLengthPhrase(i, tagGroup, media, gridMode, cardType, addCta)); + allCards.push( + cardsDiffLengthPhrase(i, tagGroup, media, gridMode, cardType, addCta) + ); } if (cta) { allCards.push( - + Top level card link @@ -248,11 +341,22 @@ Default.story = { ['Card - default', 'Card - pictogram', 'Card static', 'Card link'], 'Card - default' ); - const media = cardType === 'Card - default' || cardType === 'Card static' ? boolean('Add media:', false) : ''; - const tagGroup = cardType === 'Card - default' || cardType === 'Card static' ? boolean('Add tags:', false) : ''; - const addCta = cardType === 'Card static' ? boolean('Add CTA Links:', false) : ''; + const media = + cardType === 'Card - default' || cardType === 'Card static' + ? boolean('Add media:', false) + : ''; + const tagGroup = + cardType === 'Card - default' || cardType === 'Card static' + ? boolean('Add tags:', false) + : ''; + const addCta = + cardType === 'Card static' ? boolean('Add CTA Links:', false) : ''; const cards = number('Number of cards:', 5, { min: 2, max: 6 }); - const cardsPerRow = select('Cards per row:', cardsCol, cardsCol['3 cards per row (default)']); + const cardsPerRow = select( + 'Cards per row:', + cardsCol, + cardsCol['3 cards per row (default)'] + ); const gridMode = cardType === 'Card static' || cardType === 'Card link' ? '' @@ -275,7 +379,7 @@ Default.story = { }, }; -export const withCardInCard = args => { +export const withCardInCard = (args) => { const { cards, tagGroup, media, gridMode } = args?.CardGroup ?? {}; const allCards: object[] = []; for (let i = 0; i < cards; i++) { @@ -283,14 +387,21 @@ export const withCardInCard = args => { } return ( <> - - + + Label - Standard Bank Group prepares to embrace Africa’s AI opportunity + + Standard Bank Group prepares to embrace Africa’s AI opportunity + {allCards} @@ -317,7 +428,7 @@ withCardInCard.story = { export default { title: 'Components/Card group', decorators: [ - story => { + (story) => { return ( <> diff --git a/packages/web-components/src/components/card-group/__stories__/card-group.stories.ts b/packages/web-components/src/components/card-group/__stories__/card-group.stories.ts index a7d8e5a003d..e5760feb979 100644 --- a/packages/web-components/src/components/card-group/__stories__/card-group.stories.ts +++ b/packages/web-components/src/components/card-group/__stories__/card-group.stories.ts @@ -104,10 +104,10 @@ const cardsDiffLengthPhrase = ( `; - const videoCardGroupItem = html` + const videoCardGroupItem = (videoId = '1_9h94wo6b') => html` Topic ${tagGroup ? tagGroupContent : ''} @@ -116,8 +116,12 @@ const cardsDiffLengthPhrase = ( `; + const demoVideoIds = ['1_9h94wo6b', '0_ibuqxqbe', '1_6b6qjovy']; + count = count > 3 ? 0 : count + 1; - return media && index % 2 ? videoCardGroupItem : defaultCardGroupItem; + return media && index % 2 + ? videoCardGroupItem(demoVideoIds[index % 3]) + : defaultCardGroupItem; }; const longHeadingCardGroupItem = ( diff --git a/packages/web-components/src/components/lightbox-media-viewer/lightbox-video-player-composite.ts b/packages/web-components/src/components/lightbox-media-viewer/lightbox-video-player-composite.ts index c386b42d6f8..392c69b12be 100644 --- a/packages/web-components/src/components/lightbox-media-viewer/lightbox-video-player-composite.ts +++ b/packages/web-components/src/components/lightbox-media-viewer/lightbox-video-player-composite.ts @@ -46,7 +46,8 @@ class DDSLightboxVideoPlayerComposite extends ModalRenderMixin( * Handles aria state depending on the modal's state. */ private _handleAriaAndHiddenState = () => { - const iFrame = this._videoPlayer?.querySelector('iframe'); + const { _videoPlayer: videoPlayer } = this; + const iFrame = videoPlayer?.querySelector('iframe'); // Handles edge case where screen reader still reads video title within iFrame try { @@ -69,9 +70,7 @@ class DDSLightboxVideoPlayerComposite extends ModalRenderMixin( .constructor as typeof DDSLightboxVideoPlayerComposite; const elems = Array.prototype.slice.call( - document - .querySelector('dds-lightbox-video-player') - ?.querySelectorAll(selectorEmbeddedVideoContainer) + videoPlayer?.querySelectorAll(selectorEmbeddedVideoContainer) ); elems.forEach((element) => { From ec3e4cfaa4f50282c037c789898b7d6a61d6d54c Mon Sep 17 00:00:00 2001 From: Matthew Oliveira Date: Thu, 31 Aug 2023 10:31:50 -0400 Subject: [PATCH 04/26] fix(pagination): mark selected option in page-sizes-select component (#10884) ### Related Ticket(s) Closes https://github.com/carbon-design-system/carbon-for-ibm-dotcom/issues/10553 https://jsw.ibm.com/browse/ADCMS-3821 ### Description Fixes a bug where the initial value of the `page-size` attribute on the `` component previously did not set the correct `