Skip to content

Commit

Permalink
tabs animation change
Browse files Browse the repository at this point in the history
  • Loading branch information
svenvoskamp committed Sep 6, 2023
1 parent 6840421 commit d349dd8
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 45 deletions.
67 changes: 55 additions & 12 deletions packages/ui/src/composites/wui-tabs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { customElement, property, state } from 'lit/decorators.js'
import { elementStyles, resetStyles } from '../../utils/ThemeUtil.js'
import type { IconType } from '../../utils/TypesUtil.js'
import styles from './styles.js'
import { animate } from 'motion'

@customElement('wui-tabs')
export class WuiTabs extends LitElement {
Expand All @@ -13,47 +14,89 @@ export class WuiTabs extends LitElement {

@property() public onTabChange: (index: number) => void = () => null

@property({ type: Array }) public buttons: HTMLButtonElement[] = []

@state() public activeTab = 0

@state() public localTabWidth = '100px'

@state() public isDense = false

// -- Render -------------------------------------------- //
public override render() {
const isDense = this.tabs.length > 3
this.isDense = this.tabs.length > 3

this.style.cssText = `
--local-tab: ${this.activeTab};
--local-tab-width: 100px;
--local-tab-width: ${this.localTabWidth};
--local-dense-tab-width: max-content;
`

this.dataset['type'] = isDense ? 'flex' : 'block'
this.dataset['type'] = this.isDense ? 'flex' : 'block'

return this.tabs.map((tab, index) => {
const isActive = index === this.activeTab

return html`
<button @click=${() => this.onTabClick(index)} data-active=${isActive}>
<button
style="{{width:
20px}}"
@click=${() => this.onTabClick(index)}
data-active=${isActive}
>
<wui-icon size="sm" color="inherit" name=${tab.icon}></wui-icon>
${this.showLabel(tab, isDense, isActive)}
<wui-text variant="small-600" color="inherit"> ${tab.label}</wui-text>
</button>
`
})
}

override firstUpdated() {
if (this.shadowRoot && this.isDense) {
this.buttons = [...this.shadowRoot.querySelectorAll('button')]
setTimeout(() => {
this.animateTabs(0, true)
}, 1)
}
}

// -- Private ------------------------------------------- //
private onTabClick(index: number) {
if (this.buttons) {
this.animateTabs(index, false)
}
this.activeTab = index
this.onTabChange(index)
}

private showLabel(tab: { icon: IconType; label: string }, isDense: boolean, isActive: boolean) {
if (!isDense) {
return html`<wui-text variant="small-600" color="inherit"> ${tab.label}</wui-text>`
}
if (isDense && isActive) {
return html`<wui-text variant="small-600" color="inherit"> ${tab.label}</wui-text>`
private animateTabs(index: number, initialAnimation: boolean) {
const passiveBtn = this.buttons[this.activeTab]
const activeBtn = this.buttons[index]

const passiveBtnText = passiveBtn?.querySelector('wui-text')
const activeBtnText = activeBtn?.querySelector('wui-text')

const activeBtnBounds = activeBtn?.getBoundingClientRect()
const activeBtnTextBounds = activeBtnText?.getBoundingClientRect()

if (passiveBtn && passiveBtnText && !initialAnimation) {
animate(passiveBtnText, { opacity: 0 }, { duration: 0.25 })
animate(passiveBtn, { width: `20px` }, { duration: 0.25, delay: 0.05 })
}

return null
if (activeBtn && activeBtnBounds && activeBtnTextBounds && activeBtnText) {
this.localTabWidth = `${Math.round(
activeBtnBounds.width + activeBtnTextBounds.width + 6 + 12
)}px`

animate(
activeBtn,
{ width: `${activeBtnBounds.width + activeBtnTextBounds.width + 6}px` },
{ duration: 0.5, delay: 0.1 }
)

animate(activeBtnText, { opacity: 1 }, { duration: 0.25, delay: 0.15 })
}
}
}

Expand Down
44 changes: 11 additions & 33 deletions packages/ui/src/composites/wui-tabs/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,19 @@ export default css`
}
:host([data-type='flex'])::before {
transform: translateX(calc(var(--local-tab) * var(--local-tab-width) / 2.02));
transform: translateX(calc(var(--local-tab) * var(--local-tab-width) / 1.85));
}
:host([data-type='flex']) {
display: flex;
padding: 0px 4px;
padding: 0px 12px;
gap: 28px;
}
:host([data-type='flex']) > button[data-active='true'] > wui-text {
animation-name: fadein;
animation-duration: 0.5s;
:host([data-type='flex']) > button > wui-text {
position: absolute;
left: 18px;
opacity: 0;
}
button[data-active='true'] > wui-icon,
Expand All @@ -62,12 +64,10 @@ export default css`
}
:host([data-type='flex']) > button {
width: var(--local-dense-tab-width);
padding: 0px 16px;
}
:host([data-type='flex']) > button[data-active='true'] {
min-width: 105px;
width: 20px;
position: relative;
display: flex;
justify-content: flex-start;
}
button:hover:enabled,
Expand All @@ -84,26 +84,4 @@ export default css`
button:active > wui-text {
color: var(--wui-color-fg-125);
}
@keyframes fadein {
from {
opacity: 0;
transform: translateX(10px);
}
to {
opacity: 1;
transform: translateX(0px);
}
}
@keyframes fadeout {
from {
opacity: 1;
transform: translateX(0px);
}
to {
opacity: 0;
transform: translateX(-10px);
}
}
`

0 comments on commit d349dd8

Please sign in to comment.