From acc5964ee770e3627a45a6da4a4149d85acd25b1 Mon Sep 17 00:00:00 2001 From: Boris Diakur Date: Thu, 9 Sep 2021 23:30:13 +0200 Subject: [PATCH] feat(ld-tabs): tabs tablist tab tabpanellist tabpanel --- .../components/docs-example/docs-example.css | 1 + src/liquid/components/ld-tabs/ld-tab.css | 305 +++++++++++++++++ src/liquid/components/ld-tabs/ld-tab.tsx | 79 +++++ src/liquid/components/ld-tabs/ld-tablist.css | 74 ++++ src/liquid/components/ld-tabs/ld-tablist.tsx | 71 ++++ src/liquid/components/ld-tabs/ld-tabpanel.css | 0 src/liquid/components/ld-tabs/ld-tabpanel.tsx | 21 ++ .../components/ld-tabs/ld-tabpanellist.css | 0 .../components/ld-tabs/ld-tabpanellist.tsx | 21 ++ src/liquid/components/ld-tabs/ld-tabs.css | 0 src/liquid/components/ld-tabs/ld-tabs.tsx | 99 ++++++ src/liquid/components/ld-tabs/readme.md | 317 ++++++++++++++++++ 12 files changed, 988 insertions(+) create mode 100644 src/liquid/components/ld-tabs/ld-tab.css create mode 100644 src/liquid/components/ld-tabs/ld-tab.tsx create mode 100644 src/liquid/components/ld-tabs/ld-tablist.css create mode 100644 src/liquid/components/ld-tabs/ld-tablist.tsx create mode 100644 src/liquid/components/ld-tabs/ld-tabpanel.css create mode 100644 src/liquid/components/ld-tabs/ld-tabpanel.tsx create mode 100644 src/liquid/components/ld-tabs/ld-tabpanellist.css create mode 100644 src/liquid/components/ld-tabs/ld-tabpanellist.tsx create mode 100644 src/liquid/components/ld-tabs/ld-tabs.css create mode 100644 src/liquid/components/ld-tabs/ld-tabs.tsx create mode 100644 src/liquid/components/ld-tabs/readme.md diff --git a/src/docs/components/docs-example/docs-example.css b/src/docs/components/docs-example/docs-example.css index 87abfc71c3..452beac5a1 100644 --- a/src/docs/components/docs-example/docs-example.css +++ b/src/docs/components/docs-example/docs-example.css @@ -130,6 +130,7 @@ > * { margin: var(--ld-sp-24) var(--ld-sp-24) 0; + max-width: calc(100% - 2 * var(--ld-sp-24)); } } } diff --git a/src/liquid/components/ld-tabs/ld-tab.css b/src/liquid/components/ld-tabs/ld-tab.css new file mode 100644 index 0000000000..34658052ca --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tab.css @@ -0,0 +1,305 @@ +.ld-tab { + --ld-tab-padding-x: 0.875rem; + --ld-tab-padding-y: 0.75rem; + --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-gap: 0.625rem; + --ld-tab-icon-size: 1.25rem; + position: relative; + font: var(--ld-typo-body-m); + font-weight: 700; + border: 0; + text-decoration: none; + user-select: none; + touch-action: manipulation; + display: grid; + grid-template-columns: minmax(0rem, var(--ld-sp-16)) max-content minmax( + 0rem, + var(--ld-sp-16) + ); + align-items: center; + text-align: center; + justify-content: center; + line-height: 1; + scroll-snap-align: start; + white-space: nowrap; + -webkit-touch-callout: none; + padding: var(--ld-tab-padding-y) var(--ld-tab-padding-x); + min-height: var(--ld-tab-min-height); + color: var(--ld-tab-color); + 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__content { + opacity: 0.25; + } + } + + /* Selection indicator */ + &::after { + content: ''; + position: absolute; + inset: auto 0 0 0; + height: var(--ld-sp-2); + z-index: 1; + } + + &[aria-selected='true'] { + color: var(--ld-tab-color-selected); + + &::after { + background-color: var(--ld-tab-color-selected); + } + } + + &:focus:focus-visible { + outline: none; + background-color: var(--ld-tab-focus-bg-color); + + &:not(:active), + &[aria-disabled='true'] { + color: var(--ld-tab-focus-color); + } + + &[aria-selected='true'] { + &:not(:active) { + color: var(--ld-tab-selected-focus-color); + } + + &::after { + background-color: var(--ld-tab-selected-focus-color); + } + } + + &:not([aria-selected='true'])::after { + background-color: inherit; + } + } + + &:where(:not([aria-disabled='true'])) { + cursor: pointer; + + @media (hover: hover) { + &:hover { + background-color: var(--ld-tab-hover-bg-color); + + &:not([aria-selected='true'])::after { + background-color: inherit; + } + } + } + &:active:focus, + &:active:focus:focus-visible { + background-color: var(--ld-tab-active-bg-color); + + &:not([aria-selected='true'])::after { + background-color: inherit; + } + } + } + + .ld-tabs--sm & { + --ld-tab-padding-x: 0.625rem; + --ld-tab-padding-y: 0.5rem; + --ld-tab-min-height: 2rem; + --ld-tab-gap: 0.375rem; + --ld-tab-icon-size: 1rem; + font: var(--ld-typo-body-s); + } + + .ld-tabs--lg & { + --ld-tab-padding-x: 1.3125rem; + --ld-tab-padding-y: 0.75rem; + --ld-tab-min-height: 3.125rem; + --ld-tab-gap: 0.875rem; + --ld-tab-icon-size: 1.5rem; + font: var(--ld-typo-body-l); + } + + .ld-tabs--sm &, + .ld-tabs--lg & { + line-height: 1; + font-weight: 700; + } + + :where(.ld-tabs--ghost) & { + --ld-tab-bg-color: transparent; + } + + .ld-tabs--brand-color & { + --ld-tab-selected-focus-color: var(--ld-col-wht); + + &[aria-selected='true'] { + color: var(--ld-col-wht); + + &:focus, + &:focus:focus-visible { + &::after { + background-color: var(--ld-tab-color-selected); + } + } + } + + &[aria-disabled='true'] { + opacity: 0.5; + + .ld-tab__content { + opacity: 1; + } + } + + &:not([aria-disabled='true']) { + --ld-tab-color: var(--ld-col-wht); + --ld-tab-focus-color: 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); + + &[aria-disabled='true'] { + --ld-tab-focus-color: var(--ld-col-rb5); + --ld-tab-focus-bg-color: var(--ld-col-rb6); + --ld-tab-color: var(--ld-col-rb3); + } + } + + .ld-theme-tea &, + [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); + + &[aria-disabled='true'] { + --ld-tab-focus-color: var(--ld-col-rg5); + --ld-tab-focus-bg-color: var(--ld-col-rg6); + --ld-tab-color: var(--ld-col-rg3); + } + } + + .ld-theme-bubblegum &, + [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); + + &[aria-disabled='true'] { + --ld-tab-focus-color: var(--ld-col-rp5); + --ld-tab-focus-bg-color: var(--ld-col-rp6); + --ld-tab-color: var(--ld-col-rp3); + } + } + + .ld-theme-shake &, + [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); + + &[aria-disabled='true'] { + --ld-tab-focus-color: var(--ld-col-rp5); + --ld-tab-focus-bg-color: var(--ld-col-rp6); + --ld-tab-color: var(--ld-col-rp3); + } + } + + .ld-theme-solvent &, + [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); + + &[aria-disabled='true'] { + --ld-tab-focus-color: var(--ld-col-rp5); + --ld-tab-focus-bg-color: var(--ld-col-rp6); + --ld-tab-color: var(--ld-col-rp3); + } + } + } +} + +.ld-tab__spacer { + display: inline-flex; + flex-shrink: 1; + width: 1rem; +} + +.ld-tab__content { + display: grid; + grid-auto-flow: column; + gap: var(--ld-tab-gap); + align-items: center; + + ld-icon, + .ld-icon { + svg { + width: var(--ld-tab-icon-size); + height: var(--ld-tab-icon-size); + } + } +} + +/* .ld-theme-ocean -> default */ +.ld-tab, +:where(.ld-theme-ocean) .ld-tab, +:where([class*='ld-theme'] .ld-theme-ocean) .ld-tab { + --ld-tab-color-selected: var(--ld-thm-ocean-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rb2); +} + +:where(.ld-theme-tea), +:where([class*='ld-theme'] .ld-theme-tea) { + .ld-tab { + --ld-tab-color-selected: var(--ld-thm-tea-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rg2); + } +} + +:where(.ld-theme-bubblegum), +:where([class*='ld-theme'] .ld-theme-bubblegum) { + .ld-tab { + --ld-tab-color-selected: var(--ld-thm-bubblegum-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rp2); + } +} + +:where(.ld-theme-shake), +:where([class*='ld-theme'] .ld-theme-shake) { + .ld-tab { + --ld-tab-color-selected: var(--ld-thm-shake-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rp2); + } +} + +:where(.ld-theme-solvent), +:where([class*='ld-theme'] .ld-theme-solvent) { + .ld-tab { + --ld-tab-color-selected: var(--ld-thm-solvent-bg-primary); + --ld-tab-selected-focus-color: var(--ld-col-rp2); + } +} diff --git a/src/liquid/components/ld-tabs/ld-tab.tsx b/src/liquid/components/ld-tabs/ld-tab.tsx new file mode 100644 index 0000000000..7c3cae4c78 --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tab.tsx @@ -0,0 +1,79 @@ +import '../../components' // type definitions for type checks and intelliSense +import { + Component, + Element, + Event, + EventEmitter, + h, + Prop, + Watch, +} from '@stencil/core' + +/** + * @virtualProp ref - reference to component + * @virtualProp {string | number} key - for tracking the node's identity when working with lists + */ +@Component({ + tag: 'ld-tab', + styleUrl: 'ld-tab.css', + shadow: false, +}) +export class LdTab { + @Element() el: HTMLElement + + /** + * If present, this boolean attribute indicates that the tab is selected. + */ + @Prop({ mutable: true, reflect: true }) selected?: boolean + + /** + * Disables the tab. + */ + @Prop() disabled?: boolean + + /** + * Emitted with the id of the selected tab. + */ + @Event() tabChange: EventEmitter + + private handleTabClick(ev) { + ev.preventDefault() + + if (this.disabled) return + + if (ev.currentTarget.getAttribute('aria-selected')) return + + this.selected = true + } + + @Watch('selected') + emitEvent(newSelected: boolean, oldSelected: boolean) { + if (!newSelected || newSelected === oldSelected) return + + const index = Array.prototype.indexOf.call( + this.el.closest('.ld-tablist__scroll-container').children, + this.el + ) + + this.tabChange.emit(index) + } + + render() { + return ( + + ) + } +} diff --git a/src/liquid/components/ld-tabs/ld-tablist.css b/src/liquid/components/ld-tabs/ld-tablist.css new file mode 100644 index 0000000000..2b3994d16b --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tablist.css @@ -0,0 +1,74 @@ +.ld-tablist { + --ld-tab-indicator-color: var(--ld-col-bg-g); + position: relative; + display: block; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + inset: auto 0 0 0; + height: var(--ld-sp-2); + background-color: var(--ld-tab-indicator-color); + } + + .ld-tabs--rounded-all & { + border-radius: var(--ld-br-m); + } + .ld-tabs--rounded-all-lg & { + border-radius: var(--ld-br-l); + } + .ld-tabs--rounded-top & { + border-top-left-radius: var(--ld-br-m); + border-top-right-radius: var(--ld-br-m); + } + .ld-tabs--rounded-top-lg & { + border-top-left-radius: var(--ld-br-l); + border-top-right-radius: var(--ld-br-l); + } +} + +.ld-tablist__scroll-container { + display: flex; + overflow-x: auto; + scroll-snap-type: x mandatory; + padding-bottom: 4rem; + 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); + } + + :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-theme-bubblegum), + :where([class*='ld-theme'] .ld-theme-bubblegum) { + .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-bubblegum-bg-secondary); + } + } + + :where(.ld-theme-shake), + :where([class*='ld-theme'] .ld-theme-shake) { + .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-shake-bg-secondary); + } + } + + :where(.ld-theme-solvent), + :where([class*='ld-theme'] .ld-theme-solvent) { + .ld-tablist { + --ld-tab-indicator-color: var(--ld-thm-solvent-bg-secondary); + } + } +} diff --git a/src/liquid/components/ld-tabs/ld-tablist.tsx b/src/liquid/components/ld-tabs/ld-tablist.tsx new file mode 100644 index 0000000000..2b6957a559 --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tablist.tsx @@ -0,0 +1,71 @@ +import '../../components' // type definitions for type checks and intelliSense +import { Component, Element, h, Host } from '@stencil/core' + +/** + * @virtualProp ref - reference to component + * @virtualProp {string | number} key - for tracking the node's identity when working with lists + */ +@Component({ + tag: 'ld-tablist', + styleUrl: 'ld-tablist.css', + shadow: false, +}) +export class LdTablist { + @Element() el: HTMLElement + + private focusTab(prevTab: HTMLElement, dir: 'left' | 'right') { + const prevLdTab = prevTab.closest('ld-tab') + const currentTab = prevLdTab[ + dir === 'left' ? 'previousElementSibling' : 'nextElementSibling' + ]?.querySelector('[role="tab"]') as HTMLButtonElement + if (currentTab) { + currentTab.focus({ preventScroll: true }) + currentTab.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'center', + }) + } + } + + private setFocusOnSelectedTabpanel() { + ;(this.el + .closest('ld-tabs') + .querySelector( + 'ld-tabpanel:not([hidden]) > [role="tabpanel"]' + ) as HTMLElement)?.focus() + } + + private onKeydown(ev) { + switch (ev.key) { + case 'ArrowLeft': + ev.preventDefault() + this.focusTab(ev.target, 'left') + return + case 'ArrowRight': { + ev.preventDefault() + this.focusTab(ev.target, 'right') + return + } + case 'ArrowDown': { + ev.preventDefault() + this.setFocusOnSelectedTabpanel() + return + } + } + } + + render() { + return ( + +
+ +
+
+ ) + } +} diff --git a/src/liquid/components/ld-tabs/ld-tabpanel.css b/src/liquid/components/ld-tabs/ld-tabpanel.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/liquid/components/ld-tabs/ld-tabpanel.tsx b/src/liquid/components/ld-tabs/ld-tabpanel.tsx new file mode 100644 index 0000000000..bdde0d638e --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tabpanel.tsx @@ -0,0 +1,21 @@ +import '../../components' // type definitions for type checks and intelliSense +import { Component, h } from '@stencil/core' + +/** + * @virtualProp ref - reference to component + * @virtualProp {string | number} key - for tracking the node's identity when working with lists + */ +@Component({ + tag: 'ld-tabpanel', + styleUrl: 'ld-tabpanel.css', + shadow: false, +}) +export class LdTabpanel { + render() { + return ( +
+ +
+ ) + } +} diff --git a/src/liquid/components/ld-tabs/ld-tabpanellist.css b/src/liquid/components/ld-tabs/ld-tabpanellist.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/liquid/components/ld-tabs/ld-tabpanellist.tsx b/src/liquid/components/ld-tabs/ld-tabpanellist.tsx new file mode 100644 index 0000000000..a6edaaac5a --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tabpanellist.tsx @@ -0,0 +1,21 @@ +import '../../components' // type definitions for type checks and intelliSense +import { Component, h, Host } from '@stencil/core' + +/** + * @virtualProp ref - reference to component + * @virtualProp {string | number} key - for tracking the node's identity when working with lists + */ +@Component({ + tag: 'ld-tabpanellist', + styleUrl: 'ld-tabpanellist.css', + shadow: false, +}) +export class LdTabpanellist { + render() { + return ( + + + + ) + } +} diff --git a/src/liquid/components/ld-tabs/ld-tabs.css b/src/liquid/components/ld-tabs/ld-tabs.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/liquid/components/ld-tabs/ld-tabs.tsx b/src/liquid/components/ld-tabs/ld-tabs.tsx new file mode 100644 index 0000000000..69eac7c616 --- /dev/null +++ b/src/liquid/components/ld-tabs/ld-tabs.tsx @@ -0,0 +1,99 @@ +import '../../components' // type definitions for type checks and intelliSense +import { Component, Element, h, Host, Prop } from '@stencil/core' +import { getClassNames } from '../../utils/getClassNames' + +let tabsCount = 0 + +/** + * @virtualProp ref - reference to component + * @virtualProp {string | number} key - for tracking the node's identity when working with lists + */ +@Component({ + tag: 'ld-tabs', + styleUrl: 'ld-tabs.css', + shadow: false, +}) +export class LdTabs { + @Element() el: HTMLElement + + /** Size of the tabs. */ + @Prop() size?: 'sm' | 'lg' + + /** Display mode. */ + @Prop() mode?: 'ghost' | 'brand-color' + + /** Sets border radii. */ + @Prop() rounded?: 'all' | 'all-lg' | 'top' | 'top-lg' + + private idDescriber = `ld-tabs-${tabsCount++}` + + private updateTabs(currentLdTab) { + const prevLdTab = Array.from( + this.el.querySelectorAll('ld-tab[selected]') + ).filter((ldTab) => ldTab !== currentLdTab)[0] + if (prevLdTab) { + prevLdTab.removeAttribute('selected') + } + currentLdTab.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'center', + }) + } + + private updateTabPanels(currentLdTab) { + const tabId = currentLdTab.querySelector('[role="tab"]').id + this.el.querySelectorAll('[role="tabpanel"]').forEach((tabpanel) => { + tabpanel.closest('ld-tabpanel').setAttribute('hidden', 'true') + }) + this.el + .querySelector(`[aria-labelledby="${tabId}"]`) + ?.closest('ld-tabpanel') + .removeAttribute('hidden') + } + + private handleTabChange(ev) { + const currentLdTab = ev.target + this.updateTabs(currentLdTab) + this.updateTabPanels(currentLdTab) + } + + componentDidRender() { + // Assign ids to tabs and use them in aria-describedby attributes of the corresponding tabpanels. + // Memorize the index of the selected tab in order to hide all non-selected tabpanels. + let selectedIndex + this.el.querySelectorAll('[role="tab"]').forEach((tab, index) => { + tab.id = `${this.idDescriber}-tab-${index}` + if (tab.getAttribute('aria-selected')) { + selectedIndex = index + } + }) + this.el.querySelectorAll('[role="tabpanel"]').forEach((tabpanel, index) => { + tabpanel.setAttribute( + 'aria-labelledby', + `${this.idDescriber}-tab-${index}` + ) + if (selectedIndex === index) { + tabpanel.closest('ld-tabpanel').removeAttribute('hidden') + } else { + tabpanel.closest('ld-tabpanel').setAttribute('hidden', 'true') + } + }) + } + + render() { + return ( + + + + ) + } +} diff --git a/src/liquid/components/ld-tabs/readme.md b/src/liquid/components/ld-tabs/readme.md new file mode 100644 index 0000000000..444621d079 --- /dev/null +++ b/src/liquid/components/ld-tabs/readme.md @@ -0,0 +1,317 @@ +--- +eleventyNavigation: + key: Tabs + parent: Components +layout: layout.njk +title: Tabs +permalink: components/ld-tabs/ +--- + +# ld-tabs + +The `ld-tabs` component hides content behind selectable items and thereby helps to place content in a space-saving manner. + +--- + +## Usage + +Use `ld-tabs` as a container for a list of tabs - the `ld-tablist` which in turn contains a number of `ld-tab` items - and a container `ld-tabpanellist` which contains the same number of corresponding `ld-tabpanel` items. + +{% example 'html', false, false, 'light' %} + + + Fruits + Vegetables + Nuts + + + + + Apple, orange, banana + + + + + Potato, cucumber, tomato + + + + + Walnut, chestnut, strawberry + + + + +{% endexample %} + +### Disabled + +{% example 'html', false, false, 'light' %} + + + Fruits + Vegetables + Nuts + + +{% endexample %} + +### Ghost + +{% example %} + + + Fruits + Vegetables + Nuts + + +{% endexample %} + +### Brand color + +{% example %} + + + Fruits + Vegetables + Nuts + + +{% endexample %} + +### Rounded corners + +{% example %} + + + Fruits + Vegetables + Nuts + + + + + + Fruits + Vegetables + Nuts + + + + + + Fruits + Vegetables + Nuts + + + + + + Fruits + Vegetables + Nuts + + +{% endexample %} + +### Size + +{% example 'html', false, false, 'light' %} + + + Fruits + Vegetables + Nuts + + + + + + Fruits + Vegetables + Nuts + + + + + + Fruits + Vegetables + Nuts + + +{% endexample %} + +### With icons + +{% example 'html', false, false, 'light' %} + + + + + + + + + + + Fruits + Vegetables + Nuts + + +{% endexample %} + +### With many tabs + +Try to avoid using tab bars with more than five tab items. + +{% example 'html', false, false, 'light' %} + + + Classical + Rock + Indie + Jazz + Blues + Soul + Gospel + Pop + Hip Hop + Raggea + Raggeaton + R&B + Electric + Country + Punk + Latin + Funk + Ambient + Bossa Nova + Flamenco + + +{% endexample %} + +## Events + +The `ld-tabs` component emits the `tabChange` event which you can use to bind custom event handlers. The event is only emmitted on clicks on non-disabled and non-selected tabs. + +{% example %} + + + Fruits + Vegetables + Nuts + Corn + + + + +{% endexample %} + +## Select a tab programmatically + +There are two ways to programmatically select a tab: + +1. By dispatching a `click` event on the respective element with `role="tab"`: + +{% example %} + + + Fruits + Vegetables + Nuts + Corn + + + + + Apple, orange, banana + + + + + Potato, cucumber, tomato + + + + + Walnut, chestnut, strawberry + + + + + +Select nuts + + +{% endexample %} + +2. By updating the `selected` prop on the `ld-tab` components: + +{% example %} + + + Fruits + Vegetables + Nuts + Corn + + + + + Apple, orange, banana + + + + + Potato, cucumber, tomato + + + + + Walnut, chestnut, strawberry + + + + + +Select nuts + + +{% endexample %} + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| --------- | --------- | -------------------------------------------------------- | ---------------------------------------- | ----------- | +| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` | +| `mode` | `mode` | Display mode. | `"brand-color" \| "ghost"` | `undefined` | +| `ref` | `ref` | reference to component | `any` | `undefined` | +| `rounded` | `rounded` | Sets border radii. | `"all" \| "all-lg" \| "top" \| "top-lg"` | `undefined` | +| `size` | `size` | Size of the tabs. | `"lg" \| "sm"` | `undefined` | + + +---------------------------------------------- + +