diff --git a/.yarn/cache/@carbon-ibm-products-styles-npm-2.20.1-1f210e0807-a069cae6b7.zip b/.yarn/cache/@carbon-ibm-products-styles-npm-2.20.1-1f210e0807-a069cae6b7.zip deleted file mode 100644 index 2f402d6b5a4..00000000000 Binary files a/.yarn/cache/@carbon-ibm-products-styles-npm-2.20.1-1f210e0807-a069cae6b7.zip and /dev/null differ diff --git a/.yarn/cache/@carbon-ibm-products-styles-npm-2.24.0-7b5a90470f-cd8103d46a.zip b/.yarn/cache/@carbon-ibm-products-styles-npm-2.24.0-7b5a90470f-cd8103d46a.zip new file mode 100644 index 00000000000..d0bccc054f2 Binary files /dev/null and b/.yarn/cache/@carbon-ibm-products-styles-npm-2.24.0-7b5a90470f-cd8103d46a.zip differ diff --git a/packages/carbon-web-components/package.json b/packages/carbon-web-components/package.json index 5c8c6d6dafc..eeb0674918c 100644 --- a/packages/carbon-web-components/package.json +++ b/packages/carbon-web-components/package.json @@ -68,7 +68,7 @@ ], "dependencies": { "@babel/runtime": "^7.16.3", - "@carbon/ibm-products-styles": "2.20.1", + "@carbon/ibm-products-styles": "^2.24.0", "@carbon/styles": "1.51.0", "flatpickr": "4.6.1", "lit": "^2.7.6", diff --git a/packages/carbon-web-components/src/components/side-panel/side-panel-story.ts b/packages/carbon-web-components/src/components/side-panel/side-panel-story.ts index 73e96082ded..ce924b80c30 100644 --- a/packages/carbon-web-components/src/components/side-panel/side-panel-story.ts +++ b/packages/carbon-web-components/src/components/side-panel/side-panel-story.ts @@ -26,6 +26,18 @@ const toggleButton = () => { document.querySelector(`${prefix}-side-panel`)?.toggleAttribute('open'); }; +const nextStep = () => { + document + .querySelector(`${prefix}-side-panel`) + ?.setAttribute('current-step', '1'); +}; + +const prevStep = () => { + document + .querySelector(`${prefix}-side-panel`) + ?.setAttribute('current-step', '0'); +}; + const sizes = { // 'default (md)': null, [`Extra small size (${SIDE_PANEL_SIZE.EXTRA_SMALL})`]: @@ -69,7 +81,8 @@ const getContent = (index) => { class="${storyPrefix}text-input"> `; case 2: - return html`
Section
@@ -99,7 +112,9 @@ const getContent = (index) => { - `; + + `; + default: return null; } @@ -276,6 +291,7 @@ const DefaultTemplate = (argsIn) => { ), animateTitle: boolean('animate-title (Title animates on scroll)', true), class: text('class', 'a-user-class'), + closeIconDescription: text('Close icon description', 'Close panel'), condensedActions: boolean('condensed-actions', false), content: getContent(select('Slot (default), panel contents', contents, 2)), includeOverlay: boolean('include-overlay', true), @@ -325,9 +341,11 @@ const DefaultTemplate = (argsIn) => { size=${args.size} ?slide-in=${args.slideIn} slug=${args.slug} - title=${args.title}> + title=${args.title} + @cds-side-panel-navigate-back=${prevStep}> ${args.content} + Step two ${args.subtitle} diff --git a/packages/carbon-web-components/src/components/side-panel/side-panel.scss b/packages/carbon-web-components/src/components/side-panel/side-panel.scss index a17bb65cd8b..8d56df90168 100644 --- a/packages/carbon-web-components/src/components/side-panel/side-panel.scss +++ b/packages/carbon-web-components/src/components/side-panel/side-panel.scss @@ -39,7 +39,7 @@ $block-class-action-set: #{$pkg-prefix}--action-set; } .#{$block-class} { - @extend .#{$block-class}__container; + @extend .#{$block-class}; /* for actions container query - note this changes the size calculation */ container-name: side-panel; @@ -76,7 +76,7 @@ $block-class-action-set: #{$pkg-prefix}--action-set; } &[placement='right'] { - @extend .#{$block-class}__container-right-placement; + @extend .#{$block-class}--right-placement; /* remove if https://github.com/carbon-design-system/ibm-products/pull/3983 merged */ border-inline-end: 1px solid $border-subtle-02; @@ -85,7 +85,7 @@ $block-class-action-set: #{$pkg-prefix}--action-set; /* stylelint-disable-next-line no-duplicate-selectors -- disabled to keep close to 'right' setting */ &[placement='left'] { - @extend .#{$block-class}__container-left-placement; + @extend .#{$block-class}--left-placement; /* remove if https://github.com/carbon-design-system/ibm-products/pull/3983 merged */ border-inline-end: 1px solid $border-subtle-02; @@ -94,21 +94,20 @@ $block-class-action-set: #{$pkg-prefix}--action-set; @each $size, $size_value in spv.$side-panel-sizes { &[size='#{$size}'] { - @extend .#{$block-class}__container--#{$size}; + @extend .#{$block-class}--#{$size}; } } + } - &:not([overlay]) { - @extend .#{$block-class}__container-without-overlay; - } + #{$prefix}-layer { + display: contents; } .#{$block-class}__overlay { - @extend .#{$block-class}__overlay; - &[opening] { opacity: 0; } + @media screen and (prefers-reduced-motion: reduce) { &[open] { opacity: 1; @@ -133,32 +132,22 @@ $block-class-action-set: #{$pkg-prefix}--action-set; } } - .#{$block-class}__title-container { - @extend .#{$block-class}__title-container; - + .#{$block-class}__header { &::before { z-index: 99; /* must be higher than action toolbar */ } &[detail-step] { - @extend .#{$block-class}__on-detail-step; - } - - &:not([has-title]) { - @extend .#{$block-class}__title-container-without-title; - } - - &[detail-step]:not([has-title]) { - @extend .#{$block-class}__on-detail-step-without-title; + @extend .#{$block-class}__header--on-detail-step; } &[no-title-animation] { - @extend .#{$block-class}__title-container--no-title-animation; + @extend .#{$block-class}__header--no-title-animation; // inset-block-start: 0; } &[reduced-motion] { - @extend .#{$block-class}__title-container--reduced-motion; + @extend .#{$block-class}__header--reduced-motion; } &[has-action-toolbar] { @@ -167,115 +156,35 @@ $block-class-action-set: #{$pkg-prefix}--action-set; } } - .#{$block-class} - .#{$block-class}__title-container[has-action-toolbar]::before { + .#{$block-class} .#{$block-class}__header[has-action-toolbar]::before { content: initial; /* remove border below */ } - .#{$block-class}__nav-back-button { - @extend .#{$block-class}__navigation-back-button; - } - - .#{$block-class}__collapsed-title { - @extend .#{$block-class}__collapsed-title-text; - } - - .#{$block-class}__title { - @extend .#{$block-class}__title-text; - } - - .#{$block-class} .#{$block-class}__title { - margin-block-end: calc(-1 * var(--#{$block-class}--reduce-titles-by)); - } - - .#{$block-class}__slug-and-close { - @extend .#{$block-class}__slug-and-close; - } - - .#{$block-class}__close-button { - @extend .#{$block-class}__close-button; - } - - .#{$block-class}__label { - @extend .#{$block-class}__label-text; - - // opacity: var(--#{$block-class}--subtitle-opacity, 1); - } - - .#{$block-class}__subtitle { - @extend .#{$block-class}__subtitle-text; - + .#{$block-class}__subtitle-text { &[hidden] { @extend .#{$prefix}--visually-hidden; } - - &[no-title-animation] { - @extend .#{$block-class}__subtitle-text-no-animation; - } - - &[no-title-animation][no-action-toolbar] { - /* not working @extend .#{$block-class}__subtitle-text-no-animation-no-action-toolbar; */ - border-block-end: 1px solid $layer-active-01; - margin-block-end: $spacing-05; - } - - &[no-title] { - @extend .#{$block-class}__subtitle-without-title; - } } .#{$block-class}__action-toolbar { - @extend .#{$block-class}__action-toolbar; - margin-block-end: 0; padding-inline-start: 0; &[hidden] { @extend .#{$prefix}--visually-hidden; } - - &[no-title-animation] { - @extend .#{$block-class}__action-toolbar-no-animation; - } - - &::after { - position: absolute; - background-color: $border-subtle-02; - block-size: 1px; - content: ''; - inline-size: 100%; - inset-block-end: 0; - inset-inline-start: 0; - opacity: var(--#{$block-class}--divider-opacity); - } } .#{$block-class} .#{$block-class}__action-toolbar[hidden] { @extend .#{$prefix}--visually-hidden; } - .#{$block-class}__inner-content { - @extend .#{$block-class}__inner-content; - - block-size: calc( - 100% - var(--#{$block-class}--actions-height, $spacing-09) - ); - - &[no-title-animation] { - @extend .#{$block-class}__static-inner-content; - } - - &[has-actions] { - @extend .#{$block-class}__inner-content-with-actions; - } - - &[no-title-animation]:not([has-actions]) { - @extend .#{$block-class}__static-inner-content-no-actions; - } + .#{$block-class}[has-slug] { + @extend .#{$block-class}--has-slug; } - .#{$block-class}[has-slug] .#{$block-class}__inner-content { - @include callout-gradient('default'); + [scrolls] { + @extend .#{$block-class}--scrolls; } .#{$block-class}__body-content { @@ -288,13 +197,13 @@ $block-class-action-set: #{$pkg-prefix}--action-set; flex-direction: var(--flex-direction); /* stylelint-disable-next-line selector-type-no-unknown */ - ::slotted(cds-button) { + ::slotted(#{$prefix}-button) { flex: 0 1 25%; max-inline-size: to-rem(232px); } /* stylelint-disable-next-line selector-type-no-unknown */ - ::slotted(cds-button[kind='ghost']) { + ::slotted(#{$prefix}-button[kind='ghost']) { flex: 1 1 25%; max-inline-size: none; } @@ -302,7 +211,7 @@ $block-class-action-set: #{$pkg-prefix}--action-set; // -1 in @container query is for 1px left border @container (width <= #{map.get(spv.$side-panel-sizes, lg)}) { /* stylelint-disable-next-line selector-type-no-unknown */ - &:not([actions-multiple='triple']) ::slotted(cds-button) { + &:not([actions-multiple='triple']) ::slotted(#{$prefix}-button) { // double and single on lg use 50% flex: 0 1 50%; max-inline-size: none; @@ -314,19 +223,26 @@ $block-class-action-set: #{$pkg-prefix}--action-set; // md is 50% for two and 100% for one // column for triple /* stylelint-disable-next-line selector-type-no-unknown */ - &[actions-multiple] ::slotted(cds-button) { + &[actions-multiple] ::slotted(#{$prefix}-button) { flex: 0 0 100%; max-inline-size: none; } /* stylelint-disable-next-line selector-type-no-unknown */ - &[actions-multiple='double'] ::slotted(cds-button) { + &[actions-multiple='double'] ::slotted(#{$prefix}-button) { flex: 0 1 50%; max-inline-size: none; } &[actions-multiple='triple'] { --flex-direction: column; + + /* stylelint-disable-next-line selector-type-no-unknown */ + ::slotted(#{$prefix}-button) { + flex: initial; + inline-size: 100%; + max-inline-size: none; + } } } @@ -335,15 +251,15 @@ $block-class-action-set: #{$pkg-prefix}--action-set; --flex-direction: column; /* stylelint-disable-next-line selector-type-no-unknown */ - &[actions-multiple] ::slotted(cds-button) { - flex: 0 0 100%; + ::slotted(#{$prefix}-button) { + flex: initial; + inline-size: 100%; max-inline-size: none; } } } - .#{$block-class}__actions { - @extend .#{$block-class}__actions-container; + .#{$block-class}__actions-container { @extend .#{$block-class-action-set}; @include actions-placement(); @@ -351,7 +267,7 @@ $block-class-action-set: #{$pkg-prefix}--action-set; inline-size: 100%; /* stylelint-disable-next-line selector-type-no-unknown */ - ::slotted(cds-button) { + ::slotted(#{$prefix}-button) { @extend .#{$block-class-action-set}__action-button; } @@ -361,10 +277,6 @@ $block-class-action-set: #{$pkg-prefix}--action-set; display: none; } - &[condensed] { - @extend .#{$block-class}__actions-container-condensed; - } - $multiples: 'single' 'double' 'triple'; @each $m in $multiples { &[actions-multiple='#{$m}'] { diff --git a/packages/carbon-web-components/src/components/side-panel/side-panel.ts b/packages/carbon-web-components/src/components/side-panel/side-panel.ts index a5867c04bbc..6adf5965b2b 100644 --- a/packages/carbon-web-components/src/components/side-panel/side-panel.ts +++ b/packages/carbon-web-components/src/components/side-panel/side-panel.ts @@ -92,6 +92,7 @@ function tryFocusElems(elems: NodeListOf, reverse: boolean) { * The custom event fired before this side-panel is being closed upon a user gesture. * Cancellation of this event stops the user-initiated action of closing this side-panel. * @fires cds-side-panel-closed - The custom event fired after this side-panel is closed upon a user gesture. + * @fires cds-side-panel-navigate-back - custom event fired when clicking navigate back (available when step > 0) */ @customElement(`${prefix}-side-panel`) class CDSSidePanel extends HostListenerMixin(LitElement) { @@ -123,32 +124,23 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { @query(`.${blockClass}`) private _sidePanel!: HTMLDivElement; - /** - * Node to track size of actions - */ - @query(`.${blockClass}__actions`) - private _actions!: HTMLElement; + @query(`.${blockClass}__animated-scroll-wrapper`) + private _animateScrollWrapper?: HTMLElement; - @query(`.${blockClass}__label`) + @query(`.${blockClass}__label-text`) private _label!: HTMLElement; - @query(`.${blockClass}__title-container`) - private _titleContainer!: HTMLElement; - - @query(`.${blockClass}__title`) + @query(`.${blockClass}__title-text`) private _title!: HTMLElement; - @query(`.${blockClass}__subtitle`) + @query(`.${blockClass}__subtitle-text`) private _subtitle!: HTMLElement; - @query(`.${blockClass}__action-toolbar`) - private _actionToolbar!: HTMLElement; - @query(`.${blockClass}__inner-content`) private _innerContent!: HTMLElement; - @query(`.${blockClass}__body-content`) - private _bodyContent!: HTMLElement; + @state() + _doAnimateTitle = true; @state() _isOpen = false; @@ -319,6 +311,52 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { ); } + private _adjustPageContent = () => { + // sets/resets styles based on slideIn property and selectorPageContent; + if (this.selectorPageContent) { + const pageContentEl: HTMLElement | null = document.querySelector( + this.selectorPageContent + ); + + if (pageContentEl) { + const newValues = { + marginInlineStart: '', + marginInlineEnd: '', + inlineSize: '', + transition: this._reducedMotion.matches + ? 'none' + : `all ${moderate02}`, + transitionProperty: 'margin-inline-start, margin-inline-end', + }; + if (this.open) { + newValues.inlineSize = 'auto'; + if (this.placement === 'left') { + newValues.marginInlineStart = `${this?._sidePanel?.offsetWidth}px`; + } else { + newValues.marginInlineEnd = `${this?._sidePanel?.offsetWidth}px`; + } + } + + Object.keys(newValues).forEach((key) => { + pageContentEl.style[key] = newValues[key]; + }); + } + } + }; + + private _checkSetOpen = () => { + const { _sidePanel: sidePanel } = this; + if (sidePanel && this._isOpen) { + // wait until the side panel has transitioned off the screen to remove + sidePanel.addEventListener('transitionend', () => { + this._isOpen = false; + }); + } else { + // allow the html to render before animating in the side panel + this._isOpen = this.open; + } + }; + private _checkUpdateIconButtonSizes = () => { const slug = this.querySelector('cds-slug'); const otherButtons = this?.shadowRoot?.querySelectorAll( @@ -375,16 +413,6 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { } } - private _checkUpdateBottomPadding = () => { - const actionHeightPx = this._actions?.offsetHeight + 16; // add additional 1rem spacing to bottom padding - const actionsHeight = `${Math.round(actionHeightPx / 16)}rem`; - - this._sidePanel.style?.setProperty( - `--${blockClass}--content-bottom-padding`, - actionsHeight - ); - }; - private _handleActionsChange(e: Event) { const target = e.target as HTMLSlotElement; const actions = target?.assignedElements(); @@ -393,9 +421,7 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { this._checkUpdateIconButtonSizes(); const actionsCount = actions?.length ?? 0; - if (actionsCount === 0) { - return; - } else if (actionsCount > 3) { + if (actionsCount > 3) { this._actionsCount = 3; console.warn(`Too many side-panel actions, max 3.`); } else { @@ -415,13 +441,47 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { actions[i].classList.add(`${blockClassActionSet}__action-button`); } } - - setTimeout(() => { - // update after the updates above are applied - this._checkUpdateBottomPadding(); - }, 1); } + private _checkSetDoAnimateTitle = () => { + let canDoAnimateTitle = false; + + if ( + this._sidePanel && + this.open && + this.animateTitle && + this?.title?.length && + !this._reducedMotion.matches + ) { + const scrollAnimationDistance = this._getScrollAnimationDistance(); + // used to calculate the header moves + this?._sidePanel?.style?.setProperty( + `--${blockClass}--scroll-animation-distance`, + `${scrollAnimationDistance}` + ); + + let scrollEl = this._animateScrollWrapper; + if (!scrollEl && this.animateTitle && !this._doAnimateTitle) { + scrollEl = this._innerContent; + } + + if (scrollEl) { + const innerComputed = window?.getComputedStyle(this._innerContent); + const innerPaddingHeight = innerComputed + ? parseFloat(innerComputed?.paddingTop) + + parseFloat(innerComputed?.paddingBottom) + : 0; + + canDoAnimateTitle = + (!!this.labelText || !!this._hasActionToolbar || this._hasSubtitle) && + scrollEl.scrollHeight - scrollEl.clientHeight >= + scrollAnimationDistance + innerPaddingHeight; + } + } + + this._doAnimateTitle = canDoAnimateTitle; + }; + /** * The `ResizeObserver` instance for observing element resizes for re-positioning floating menu position. */ @@ -429,182 +489,36 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { // @ts-ignore private _resizeObserver = new ResizeObserver(() => { if (this._sidePanel) { - this._checkUpdateBottomPadding(); + this._checkSetDoAnimateTitle(); } }); - private _measurements: any = {}; + private _getScrollAnimationDistance = () => { + const labelHeight = this?._label?.offsetHeight ?? 0; + const subtitleHeight = this?._subtitle?.offsetHeight ?? 0; + const titleVerticalBorder = this._hasActionToolbar + ? this._title.offsetHeight - this._title.clientHeight + : 0; - private _setMeasuredCustomProperties = async (reason, scrollY = 0) => { - await this.updateComplete; - - if (!this._sidePanel || (!this.open && !this._innerContent)) { - return; - } + return labelHeight + subtitleHeight + titleVerticalBorder; + }; - await (this.constructor as typeof CDSSidePanel)._delay(); // measure after brief delay for render - this._measurements.subtitleHeight = this._subtitle?.offsetHeight || 0; // set default subtitle height if a subtitle is not provided to enable scrolling animation - this._sidePanel?.style.setProperty( - `--${blockClass}--subtitle-container-height`, - `${this._measurements.subtitleHeight}px` + private _scrollObserver = () => { + const scrollTop = this._animateScrollWrapper?.scrollTop ?? 0; + const scrollAnimationDistance = this._getScrollAnimationDistance(); + this?._sidePanel?.style?.setProperty( + `--${blockClass}--scroll-animation-progress`, + `${ + Math.min(scrollTop, scrollAnimationDistance) / scrollAnimationDistance + }` ); - - if (reason !== 'scroll') { - this._measurements.panelHeight = this._sidePanel?.offsetHeight || 0; - this._measurements.scrollSectionHeight = - this._bodyContent?.offsetHeight || 0; - this._measurements.titleContainerHeight = - this._titleContainer?.offsetHeight || 0; - this._measurements.titleHeight = this._title?.offsetHeight || 0; - this._measurements.labelHeight = this._label?.offsetHeight || 0; - this._measurements.totalScrollingHeight = - this._measurements.titleContainerHeight + - this._measurements.subtitleHeight + - this._measurements.scrollSectionHeight; - this._measurements.actionToolbarHeight = - this?._actionToolbar?.offsetHeight || 0; - - this._sidePanel?.style.setProperty( - `--${blockClass}--title-text-height`, - this.animateTitle ? '0' : `${this._measurements.titleHeight + 24}px` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--action-bar-container-height`, - this.animateTitle ? '0' : `${this._measurements.actionToolbarHeight}px` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--label-text-height`, - `${this._measurements.labelHeight}px` - ); - if (this.animateTitle) { - this._measurements.titlePaddingTop = parseInt( - (this._titleContainer && - window && - window?.getComputedStyle?.(this._titleContainer)?.[ - 'padding-top' - ]) ?? - '0', - 10 - ); - - this._measurements.transitionDistance = - -1 * - Math.max( - this._measurements.titleHeight + - this._measurements.actionToolbarHeight + - this._measurements.titlePaddingTop - - this._measurements.titleContainerHeight, - this._innerContent?.offsetHeight - this._innerContent?.scrollHeight - ); - - // if the difference between the total scrolling height and the panel height is less than - // the subtitleElement height OR if the subtitle element height is 0, use that difference - // as the length of the scroll animation (otherwise the animation will not be able to complete - // because there is not enough scrolling distance to complete it). - this._measurements.subtitleHeight = - this._measurements.totalScrollingHeight - - this._measurements.panelHeight < - this._measurements.subtitleHeight - ? this._measurements.totalScrollingHeight - - this._measurements.panelHeight - : this._measurements.subtitleHeight === 0 - ? 16 - : this._measurements.subtitleHeight; - this._measurements.subtitleHeight = - this._measurements.subtitleHeight < 0 - ? this._innerContent?.scrollHeight - - this._innerContent?.clientHeight - : this._measurements.subtitleHeight; - - this._sidePanel.style.setProperty( - `--${blockClass}--action-bar-container-height`, - `${this._measurements.actionToolbarHeight || 0}px` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--title-height`, - `${this._measurements.titleHeight + 16}px` - ); - } - } else { - if (this.animateTitle) { - const scrollAnimationProgress = - this._measurements.transitionDistance && - this._measurements.transitionDistance > scrollY - ? scrollY / this._measurements.transitionDistance - : 1; - - this._sidePanel.style.setProperty( - `--${blockClass}--scroll-y`, - `${scrollY}px` - ); - - const scrolled = scrollY > 0; - - this._sidePanel.style.setProperty( - `--${blockClass}--subtitle-opacity`, - !scrolled - ? '1' - : `${ - 1 - - Math.min(this._measurements.transitionDistance, scrollY) / - this._measurements.transitionDistance - }` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--divider-opacity`, - !scrolled ? '0' : `${scrollAnimationProgress}` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--title-y-position`, - !scrolled - ? '0rem' - : `${-Math.abs( - Math.min(1, scrollY / this._measurements.subtitleHeight) - )}rem` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--collapsed-title-y-position`, - !scrolled - ? '1rem' - : `${ - Math.max(0, this._measurements.subtitleHeight - scrollY) / - this._measurements.subtitleHeight - }rem` - ); - - this._sidePanel.style.setProperty( - `--${blockClass}--title-container-height`, - !scrolled ? '0px' : `${this._measurements.titleContainerHeight}px` - ); - - const reduceTitleContainerHeightAmount = - ((this._measurements.labelHeight * scrollAnimationProgress) / - this._measurements.titleContainerHeight) * - 100; - - this._sidePanel.style.setProperty( - `--${blockClass}--reduce-titles-by`, - !scrolled && !this.animateTitle - ? '0px' - : `${Math.trunc(reduceTitleContainerHeightAmount)}px` - ); - } else { - this._sidePanel.style.setProperty( - `--${blockClass}--reduce-titles-by`, - '0px' - ); - } - } }; - private _scrollObserver = (event) => { - this._setMeasuredCustomProperties('scroll', event.target.scrollTop); + private _handleCurrentStepUpdate = () => { + const scrollable = this._animateScrollWrapper ?? this._innerContent; + if (scrollable) { + scrollable.scrollTop = 0; + } }; /** @@ -710,10 +624,6 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { if (this._hObserveResize) { this._hObserveResize = this._hObserveResize.release(); } - - if (this._innerContent) { - this._innerContent.removeEventListener('scroll', this._scrollObserver); - } } connectedCallback() { @@ -729,7 +639,6 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { render() { const { - animateTitle, closeIconDescription, condensedActions, currentStep, @@ -751,88 +660,110 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { this._actionsCount ]; - const titleTemplate = html` + const titleTemplate = html`
+

+ ${title} +

+ + ${this._doAnimateTitle + ? html`` + : ''} +
`; + + const headerHasTitleClass = this.title + ? ` ${blockClass}__header--has-title ` + : ''; + const headerTemplate = html`
0} - ?has-title=${!!title} - ?no-title-animation=${!animateTitle} - ?reduced-motion=${this._reducedMotion.matches} - ?has-action-toolbar=${this._hasActionToolbar}> + ?no-title-animation=${!this._doAnimateTitle} + ?reduced-motion=${this._reducedMotion.matches}> ${currentStep > 0 ? html` ${ArrowLeft16({ slot: 'icon' })} + + ${navigationBackIconDescription} + ` : ''} ${title?.length && labelText?.length - ? html`

${labelText}

` - : ''} - - - ${animateTitle && title?.length && !this._reducedMotion.matches - ? html`` - : ''} - - - ${title?.length - ? html`

- ${title} -

` + ? html`

${labelText}

` : ''} -
- -
- - - - ${Close20({ slot: 'icon' })} - + + ${title ? titleTemplate : ''} + + +
+ + + + ${Close20({ slot: 'icon' })} + ${closeIconDescription} + +
+ + +

+ +

+ +
+ +
+ `; - -

- -

+ const mainTemplate = html`
+ + + +
`; -
- -
- `; + const sidePanelAnimateTitleClass = this._doAnimateTitle + ? ` ${blockClass}--animated-title` + : ''; return html` ${includeOverlay @@ -895,75 +818,52 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { `; } - checkSetOpen = () => { - const { _sidePanel: sidePanel } = this; - if (sidePanel && this._isOpen) { - // wait until the side panel has transitioned off the screen to remove - sidePanel.addEventListener('transitionend', () => { - this._isOpen = false; - }); - } else { - // allow the html to render before animating in the side panel - window.requestAnimationFrame(() => { - this._isOpen = this.open; - }); + async updated(changedProperties) { + if (changedProperties.has('currentStep')) { + this._handleCurrentStepUpdate(); } - }; - adjustPageContent = () => { - // sets/resets styles based on slideIn property and selectorPageContent; - if (this.selectorPageContent) { - const pageContentEl: HTMLElement | null = document.querySelector( - this.selectorPageContent + if (changedProperties.has('_doAnimateTitle')) { + this?._animateScrollWrapper?.removeEventListener( + 'scroll', + this._scrollObserver ); - if (pageContentEl) { - const newValues = { - marginInlineStart: '', - marginInlineEnd: '', - inlineSize: '', - transition: this._reducedMotion.matches - ? 'none' - : `all ${moderate02}`, - transitionProperty: 'margin-inline-start, margin-inline-end', - }; - if (this.open) { - newValues.inlineSize = 'auto'; - if (this.placement === 'left') { - newValues.marginInlineStart = `${this._sidePanel.offsetWidth}px`; - } else { - newValues.marginInlineEnd = `${this._sidePanel.offsetWidth}px`; - } - } - - Object.keys(newValues).forEach((key) => { - pageContentEl.style[key] = newValues[key]; - }); + if (this._doAnimateTitle) { + this?._animateScrollWrapper?.addEventListener( + 'scroll', + this._scrollObserver + ); + } else { + this?._sidePanel?.style?.setProperty( + `--${blockClass}--scroll-animation-progress`, + '0' + ); } } - }; - firstUpdated() { - this.checkSetOpen(); - this.adjustPageContent(); - this._setMeasuredCustomProperties('first update'); - } - - async updated(changedProperties) { - this.checkSetOpen(); + if ( + changedProperties.has('_isOpen') || + changedProperties.has('animateTitle') + ) { + /* @state property changed */ + this._checkSetDoAnimateTitle(); + } if ( - changedProperties.has('slide-in') || + changedProperties.has('slideIn') || changedProperties.has('open') || - changedProperties.has('include-overlay') + changedProperties.has('includeOverlay') ) { - this.adjustPageContent(); + this._adjustPageContent(); } + if (changedProperties.has('open')) { + this._checkSetOpen(); + this.disconnectObservers(); if (this.open) { this.connectObservers(); - this._setMeasuredCustomProperties('update'); this._launcher = this.ownerDocument!.activeElement; const focusNode = @@ -992,11 +892,6 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { (this._launcher as HTMLElement).focus(); this._launcher = null; } - - // monitor scroll - if (this._innerContent) { - this._innerContent.addEventListener('scroll', this._scrollObserver); - } } } @@ -1036,7 +931,7 @@ class CDSSidePanel extends HostListenerMixin(LitElement) { * The name of the custom event fired on clicking the navigate back button */ static get eventNavigateBack() { - return `${prefix}-side-panel-header-navigate-back`; + return `${prefix}-side-panel-navigate-back`; } static styles = styles; // `styles` here is a `CSSResult` generated by custom WebPack loader diff --git a/yarn.lock b/yarn.lock index f7f84ebb026..d6d67786d57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3112,16 +3112,16 @@ __metadata: languageName: node linkType: hard -"@carbon/ibm-products-styles@npm:2.20.1": - version: 2.20.1 - resolution: "@carbon/ibm-products-styles@npm:2.20.1" +"@carbon/ibm-products-styles@npm:^2.24.0": + version: 2.24.0 + resolution: "@carbon/ibm-products-styles@npm:2.24.0" peerDependencies: "@carbon/grid": ^11.21.1 "@carbon/layout": ^11.20.1 "@carbon/motion": ^11.16.1 - "@carbon/themes": ^11.28.0 + "@carbon/themes": ^11.30.0 "@carbon/type": ^11.25.1 - checksum: 10/a069cae6b7a4eb23d8b2480ac28bea80660f0893cd810c80d6ad148276d2f9f772c1a965983efcea853bcccdb794039c9c555893b294544b98df218fd14e6fbd + checksum: 10/cd8103d46a014bdcf02e3d5cf320fca61aab106160512c63ac039a2e3560859a4f18bbbf2d0381550a626d4f8e76c6ab419c6d0be464f3f0b32d5a3e8420b2aa languageName: node linkType: hard @@ -3662,7 +3662,7 @@ __metadata: "@babel/runtime": "npm:^7.16.3" "@babel/template": "npm:~7.12.0" "@babel/traverse": "npm:~7.23.7" - "@carbon/ibm-products-styles": "npm:2.20.1" + "@carbon/ibm-products-styles": "npm:^2.24.0" "@carbon/icon-helpers": "npm:10.46.0" "@carbon/icons": "npm:11.36.0" "@carbon/styles": "npm:1.51.0"