diff --git a/src/liquid/components/ld-tabs/ld-tab.css b/src/liquid/components/ld-tabs/ld-tab.css index 34658052ca..9e04eee8d4 100644 --- a/src/liquid/components/ld-tabs/ld-tab.css +++ b/src/liquid/components/ld-tabs/ld-tab.css @@ -4,10 +4,10 @@ --ld-tab-min-height: 2.5rem; --ld-tab-color: var(--ld-col-rblck-default); --ld-tab-bg-color: var(--ld-col-bg-lg); - --ld-tab-focus-color: var(--ld-col-rblck1); - --ld-tab-focus-bg-color: var(--ld-col-rblck4); - --ld-tab-hover-bg-color: var(--ld-col-rblck1); - --ld-tab-active-bg-color: var(--ld-col-rblck2); + --ld-tab-color-focus: var(--ld-col-rblck1); + --ld-tab-bg-color-focus: var(--ld-col-rblck4); + --ld-tab-bg-color-hover: var(--ld-col-rblck1); + --ld-tab-bg-color-active: var(--ld-col-rblck2); --ld-tab-gap: 0.625rem; --ld-tab-icon-size: 1.25rem; position: relative; @@ -35,8 +35,8 @@ background-color: var(--ld-tab-bg-color); &[aria-disabled='true'] { - --ld-tab-focus-bg-color: var(--ld-col-rblck3); - --ld-tab-focus-color: var(--ld-col-wht); + --ld-tab-bg-color-focus: var(--ld-col-rblck3); + --ld-tab-color-focus: var(--ld-col-wht); .ld-tab__content { opacity: 0.25; @@ -49,7 +49,7 @@ position: absolute; inset: auto 0 0 0; height: var(--ld-sp-2); - z-index: 1; + z-index: 3; } &[aria-selected='true'] { @@ -62,11 +62,11 @@ &:focus:focus-visible { outline: none; - background-color: var(--ld-tab-focus-bg-color); + background-color: var(--ld-tab-bg-color-focus); &:not(:active), &[aria-disabled='true'] { - color: var(--ld-tab-focus-color); + color: var(--ld-tab-color-focus); } &[aria-selected='true'] { @@ -89,7 +89,7 @@ @media (hover: hover) { &:hover { - background-color: var(--ld-tab-hover-bg-color); + background-color: var(--ld-tab-bg-color-hover); &:not([aria-selected='true'])::after { background-color: inherit; @@ -98,7 +98,7 @@ } &:active:focus, &:active:focus:focus-visible { - background-color: var(--ld-tab-active-bg-color); + background-color: var(--ld-tab-bg-color-active); &:not([aria-selected='true'])::after { background-color: inherit; @@ -158,21 +158,21 @@ &:not([aria-disabled='true']) { --ld-tab-color: var(--ld-col-wht); - --ld-tab-focus-color: var(--ld-col-wht); + --ld-tab-color-focus: var(--ld-col-wht); } .ld-theme-ocean &, [class*='ld-theme'] .ld-theme-ocean & { --ld-tab-color-selected: var(--ld-thm-ocean-accent); --ld-tab-bg-color: var(--ld-thm-ocean-bg-primary); - --ld-tab-focus-bg-color: var(--ld-col-rb-focus); - --ld-tab-focus-color: var(--ld-col-rb6); - --ld-tab-hover-bg-color: var(--ld-col-rb-hover); - --ld-tab-active-bg-color: var(--ld-col-rb-active); + --ld-tab-bg-color-focus: var(--ld-col-rb-focus); + --ld-tab-color-focus: var(--ld-col-rb6); + --ld-tab-bg-color-hover: var(--ld-col-rb-hover); + --ld-tab-bg-color-active: var(--ld-col-rb-active); &[aria-disabled='true'] { - --ld-tab-focus-color: var(--ld-col-rb5); - --ld-tab-focus-bg-color: var(--ld-col-rb6); + --ld-tab-color-focus: var(--ld-col-rb5); + --ld-tab-bg-color-focus: var(--ld-col-rb6); --ld-tab-color: var(--ld-col-rb3); } } @@ -181,14 +181,14 @@ [class*='ld-theme'] .ld-theme-tea & { --ld-tab-color-selected: var(--ld-thm-tea-accent); --ld-tab-bg-color: var(--ld-thm-tea-bg-primary); - --ld-tab-focus-bg-color: var(--ld-col-rg-focus); - --ld-tab-focus-color: var(--ld-col-rg6); - --ld-tab-hover-bg-color: var(--ld-col-rg-hover); - --ld-tab-active-bg-color: var(--ld-col-rg-active); + --ld-tab-bg-color-focus: var(--ld-col-rg-focus); + --ld-tab-color-focus: var(--ld-col-rg6); + --ld-tab-bg-color-hover: var(--ld-col-rg-hover); + --ld-tab-bg-color-active: var(--ld-col-rg-active); &[aria-disabled='true'] { - --ld-tab-focus-color: var(--ld-col-rg5); - --ld-tab-focus-bg-color: var(--ld-col-rg6); + --ld-tab-color-focus: var(--ld-col-rg5); + --ld-tab-bg-color-focus: var(--ld-col-rg6); --ld-tab-color: var(--ld-col-rg3); } } @@ -197,14 +197,14 @@ [class*='ld-theme'] .ld-theme-bubblegum & { --ld-tab-color-selected: var(--ld-thm-bubblegum-accent); --ld-tab-bg-color: var(--ld-thm-bubblegum-bg-primary); - --ld-tab-focus-bg-color: var(--ld-col-rp-focus); - --ld-tab-focus-color: var(--ld-col-rp6); - --ld-tab-hover-bg-color: var(--ld-col-rp-hover); - --ld-tab-active-bg-color: var(--ld-col-rp-active); + --ld-tab-bg-color-focus: var(--ld-col-rp-focus); + --ld-tab-color-focus: var(--ld-col-rp6); + --ld-tab-bg-color-hover: var(--ld-col-rp-hover); + --ld-tab-bg-color-active: var(--ld-col-rp-active); &[aria-disabled='true'] { - --ld-tab-focus-color: var(--ld-col-rp5); - --ld-tab-focus-bg-color: var(--ld-col-rp6); + --ld-tab-color-focus: var(--ld-col-rp5); + --ld-tab-bg-color-focus: var(--ld-col-rp6); --ld-tab-color: var(--ld-col-rp3); } } @@ -213,14 +213,14 @@ [class*='ld-theme'] .ld-theme-shake & { --ld-tab-color-selected: var(--ld-thm-shake-accent); --ld-tab-bg-color: var(--ld-thm-shake-bg-primary); - --ld-tab-focus-bg-color: var(--ld-col-rp-focus); - --ld-tab-focus-color: var(--ld-col-rp6); - --ld-tab-hover-bg-color: var(--ld-col-rp-hover); - --ld-tab-active-bg-color: var(--ld-col-rp-active); + --ld-tab-bg-color-focus: var(--ld-col-rp-focus); + --ld-tab-color-focus: var(--ld-col-rp6); + --ld-tab-bg-color-hover: var(--ld-col-rp-hover); + --ld-tab-bg-color-active: var(--ld-col-rp-active); &[aria-disabled='true'] { - --ld-tab-focus-color: var(--ld-col-rp5); - --ld-tab-focus-bg-color: var(--ld-col-rp6); + --ld-tab-color-focus: var(--ld-col-rp5); + --ld-tab-bg-color-focus: var(--ld-col-rp6); --ld-tab-color: var(--ld-col-rp3); } } @@ -229,14 +229,14 @@ [class*='ld-theme'] .ld-theme-solvent & { --ld-tab-color-selected: var(--ld-thm-solvent-accent); --ld-tab-bg-color: var(--ld-thm-solvent-bg-primary); - --ld-tab-focus-bg-color: var(--ld-col-rp-focus); - --ld-tab-focus-color: var(--ld-col-rp6); - --ld-tab-hover-bg-color: var(--ld-col-rp-hover); - --ld-tab-active-bg-color: var(--ld-col-rp-active); + --ld-tab-bg-color-focus: var(--ld-col-rp-focus); + --ld-tab-color-focus: var(--ld-col-rp6); + --ld-tab-bg-color-hover: var(--ld-col-rp-hover); + --ld-tab-bg-color-active: var(--ld-col-rp-active); &[aria-disabled='true'] { - --ld-tab-focus-color: var(--ld-col-rp5); - --ld-tab-focus-bg-color: var(--ld-col-rp6); + --ld-tab-color-focus: var(--ld-col-rp5); + --ld-tab-bg-color-focus: var(--ld-col-rp6); --ld-tab-color: var(--ld-col-rp3); } } diff --git a/src/liquid/components/ld-tabs/ld-tablist.css b/src/liquid/components/ld-tabs/ld-tablist.css index 2b3994d16b..c76ab80992 100644 --- a/src/liquid/components/ld-tabs/ld-tablist.css +++ b/src/liquid/components/ld-tabs/ld-tablist.css @@ -1,7 +1,12 @@ .ld-tablist { --ld-tab-indicator-color: var(--ld-col-bg-g); + --ld-tab-btn-scroll-color: var(--ld-col-rblck-default); + --ld-tab-btn-scroll-color-active: var(--ld-col-rblck-default); + --ld-tab-btn-scroll-bg-color: var(--ld-col-bg-lg); + --ld-tab-btn-scroll-bg-color-hover: var(--ld-col-rblck1); + --ld-tab-btn-scroll-bg-color-active: var(--ld-col-rblck2); position: relative; - display: block; + display: flex; overflow: hidden; &::after { @@ -10,6 +15,7 @@ inset: auto 0 0 0; height: var(--ld-sp-2); background-color: var(--ld-tab-indicator-color); + z-index: 2; } .ld-tabs--rounded-all & { @@ -36,39 +42,135 @@ margin-bottom: -4rem; } -/* .ld-theme-ocean -> default */ -:where(.ld-tabs--brand-color) { - .ld-tablist, - :where(.ld-theme-ocean) .ld-tablist, - :where([class*='ld-theme'] .ld-theme-ocean) .ld-tablist { - --ld-tab-indicator-color: var(--ld-thm-ocean-bg-secondary); +.ld-tablist__btn-scroll { + position: relative; + border: 0; + text-decoration: none; + user-select: none; + touch-action: manipulation; + display: none; + justify-content: center; + align-items: center; + -webkit-touch-callout: none; + color: var(--ld-tab-btn-scroll-color); + background-color: var(--ld-tab-btn-scroll-bg-color); + box-shadow: var(--ld-shadow-active); + width: var(--ld-sp-32); + z-index: 2; + + .ld-tablist--scrollable & { + display: inline-flex; } - :where(.ld-theme-tea), - :where([class*='ld-theme'] .ld-theme-tea) { - .ld-tablist { - --ld-tab-indicator-color: var(--ld-thm-tea-bg-secondary); - } + :where(.ld-tabs--brand-color) & { + --ld-tab-btn-scroll-color-active: var(--ld-col-wht); + --ld-tab-btn-scroll-color: var(--ld-col-wht); } - :where(.ld-theme-bubblegum), - :where([class*='ld-theme'] .ld-theme-bubblegum) { - .ld-tablist { - --ld-tab-indicator-color: var(--ld-thm-bubblegum-bg-secondary); - } + &:focus:focus-visible { + outline: none; } - :where(.ld-theme-shake), - :where([class*='ld-theme'] .ld-theme-shake) { - .ld-tablist { - --ld-tab-indicator-color: var(--ld-thm-shake-bg-secondary); + &[aria-disabled='true'] { + svg { + opacity: 0.25; } } - :where(.ld-theme-solvent), - :where([class*='ld-theme'] .ld-theme-solvent) { - .ld-tablist { - --ld-tab-indicator-color: var(--ld-thm-solvent-bg-secondary); + &:where(:not([aria-disabled='true'])) { + cursor: pointer; + + @media (hover: hover) { + &:hover { + background-color: var(--ld-tab-btn-scroll-bg-color-hover); + } } + &:active:focus, + &:active:focus:focus-visible { + color: var(--ld-tab-btn-scroll-color-active); + background-color: var(--ld-tab-btn-scroll-bg-color-active); + } + } + + &--left { + left: 0; + } + &--right { + right: 0; + } +} + +/* .ld-theme-ocean -> default */ +.ld-tablist, +.ld-theme-ocean .ld-tablist, +[class*='ld-theme'] .ld-theme-ocean .ld-tablist { + --ld-tab-color-selected: var(--ld-thm-ocean-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rb2); + + .ld-tabs--brand-color & { + --ld-tab-indicator-color: var(--ld-thm-ocean-bg-secondary); + --ld-tab-btn-scroll-bg-color: var(--ld-thm-ocean-bg-primary); + --ld-tab-btn-scroll-bg-color-hover: var(--ld-col-rb-hover); + --ld-tab-btn-scroll-bg-color-active: var(--ld-col-rb-active); + } +} + +.ld-theme-tea, +[class*='ld-theme'] .ld-theme-tea { + :where(.ld-tablist) { + --ld-tab-color-selected: var(--ld-thm-tea-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rg2); + } + + .ld-tabs--brand-color .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-tea-bg-secondary); + --ld-tab-btn-scroll-bg-color: var(--ld-thm-tea-bg-primary); + --ld-tab-btn-scroll-bg-color-hover: var(--ld-col-rg-hover); + --ld-tab-btn-scroll-bg-color-active: var(--ld-col-rg-active); + } +} + +.ld-theme-bubblegum, +[class*='ld-theme'] .ld-theme-bubblegum { + :where(.ld-tablist) { + --ld-tab-color-selected: var(--ld-thm-bubblegum-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rp2); + } + + .ld-tabs--brand-color .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-bubblegum-bg-secondary); + --ld-tab-btn-scroll-bg-color: var(--ld-thm-bubblegum-bg-primary); + --ld-tab-btn-scroll-bg-color-hover: var(--ld-col-rp-hover); + --ld-tab-btn-scroll-bg-color-active: var(--ld-col-rp-active); + } +} + +.ld-theme-shake, +[class*='ld-theme'] .ld-theme-shake { + :where(.ld-tablist) { + --ld-tab-color-selected: var(--ld-thm-shake-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rp2); + } + + .ld-tabs--brand-color .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-shake-bg-secondary); + --ld-tab-btn-scroll-bg-color: var(--ld-thm-shake-bg-primary); + --ld-tab-btn-scroll-bg-color-hover: var(--ld-col-rp-hover); + --ld-tab-btn-scroll-bg-color-active: var(--ld-col-rp-active); + } +} + +.ld-theme-solvent, +[class*='ld-theme'] .ld-theme-solvent { + :where(.ld-tablist) { + --ld-tab-color-selected: var(--ld-thm-solvent-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rp2); + } + + .ld-tabs--brand-color .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-solvent-bg-secondary); + --ld-tab-btn-scroll-bg-color: var(--ld-thm-solvent-bg-primary); + --ld-tab-btn-scroll-bg-color-hover: var(--ld-col-rp-hover); + --ld-tab-btn-scroll-bg-color-active: var(--ld-col-rp-active); } } diff --git a/src/liquid/components/ld-tabs/ld-tablist.tsx b/src/liquid/components/ld-tabs/ld-tablist.tsx index 2b6957a559..ddbfb5db31 100644 --- a/src/liquid/components/ld-tabs/ld-tablist.tsx +++ b/src/liquid/components/ld-tabs/ld-tablist.tsx @@ -1,5 +1,6 @@ import '../../components' // type definitions for type checks and intelliSense -import { Component, Element, h, Host } from '@stencil/core' +import { Component, Element, h, Host, Listen, State } from '@stencil/core' +import { getClassNames } from '../../utils/getClassNames' /** * @virtualProp ref - reference to component @@ -13,6 +14,54 @@ import { Component, Element, h, Host } from '@stencil/core' export class LdTablist { @Element() el: HTMLElement + private slotContainerRef!: HTMLElement + private btnScrollLeftRef!: HTMLButtonElement + // private btnScrollRightRef!: HTMLButtonElement + + @State() scrollable: boolean + @State() scrollLeftEnabled: boolean + @State() scrollRightEnabled: boolean + + @Listen('resize', { target: 'window', passive: true }) + handleWindowResize() { + this.updateScrollable() + this.updateScrollButtons() + } + + private updateScrollable() { + const scrollButtonsWidth = + 2 * parseFloat(window.getComputedStyle(this.btnScrollLeftRef).width) + const scrollContainerWidth = this.slotContainerRef.getBoundingClientRect() + .width + const contentWidth = Array.from(this.slotContainerRef.children) + .map((child) => child.getBoundingClientRect().width) + .reduce((a, b) => a + b) + this.scrollable = + scrollContainerWidth + (this.scrollable ? scrollButtonsWidth : 0) < + contentWidth + } + + private updateScrollButtons() { + if (!this.scrollable) return + this.scrollLeftEnabled = this.slotContainerRef.scrollLeft > 0 + this.scrollRightEnabled = + this.slotContainerRef.scrollLeft + + this.slotContainerRef.getBoundingClientRect().width - + this.slotContainerRef.scrollWidth < + 0 + } + + private scroll(dir: 'left' | 'right') { + this.slotContainerRef.scrollTo({ + left: + this.slotContainerRef.scrollLeft + + ((dir === 'left' ? -1 : 1) * + this.slotContainerRef.getBoundingClientRect().width) / + 2, + behavior: 'smooth', + }) + } + private focusTab(prevTab: HTMLElement, dir: 'left' | 'right') { const prevLdTab = prevTab.closest('ld-tab') const currentTab = prevLdTab[ @@ -55,16 +104,77 @@ export class LdTablist { } } + componentDidLoad() { + setTimeout(() => { + this.updateScrollable() + this.updateScrollButtons() + }) + } + render() { return ( -
+ +
(this.slotContainerRef = el as HTMLElement)} + onScroll={this.updateScrollButtons.bind(this)} + >
+ ) } diff --git a/src/liquid/components/ld-tabs/readme.md b/src/liquid/components/ld-tabs/readme.md index 444621d079..d483e5a913 100644 --- a/src/liquid/components/ld-tabs/readme.md +++ b/src/liquid/components/ld-tabs/readme.md @@ -26,17 +26,17 @@ Use `ld-tabs` as a container for a list of tabs - the `ld-tablist` which in turn - + Apple, orange, banana - + Potato, cucumber, tomato - + Walnut, chestnut, strawberry @@ -228,21 +228,20 @@ There are two ways to programmatically select a tab: Fruits Vegetables Nuts - Corn - + Apple, orange, banana - + Potato, cucumber, tomato - + Walnut, chestnut, strawberry @@ -266,21 +265,20 @@ document.getElementById('nuts_button_1').addEventListener('click', ev => { Fruits Vegetables Nuts - Corn - + Apple, orange, banana - + Potato, cucumber, tomato - + Walnut, chestnut, strawberry