ark-uiにtailwind-animationを組み合わせる
Ark UIはReact等で利用できるコンポーネントライブラリだ。
特徴としてボタンのような単純な機能ではなく、Date PickerやDialogなど、状態を保有するような少し複雑なコンポーネントを中心によく使うものが揃っている点や、styleを付与してない事が挙げられる。
styleが無いのでtailwindなどのライブラリと相性が良い。一方でアニメーション等もデフォルトでは付与されていないので、このあたりは面倒を見る必要がある。
この対処としてCSSのattributeを記載してアニメーションを付与する方法が提案されている
[data-scope='tooltip'][data-part='content'][data-state='open'] {
animation: fadeIn 300ms ease-out;
}
[data-scope='tooltip'][data-part='content'][data-state='closed'] {
animation: fadeOut 300ms ease-in;
}
とはいえCSSを書く量をなるべく怠けたいのでtailwind-animation
と組み合わせる方法を考えた。
tailwind-animationと組み合わせる
今回はToast
の例を利用する。
Tailwind側の機能としてはgroup
とData Attribute
を利用する。
const [Toaster, toast] = createToaster({
placement: 'bottom',
duration: 3000,
removeDelay: 100000,
max: 1,
// count: 10,
render(toast) {
return (
<Toast.Root className='group'>
<div className='
group-data-[state=open]:animate-duration-500
group-data-[state=open]:animate-fade-up
group-data-[state=open]:animate-normal
'>
<div className='
group-data-[state=closed]:animate-duration-500
group-data-[state=closed]:animate-reverse
group-data-[state=closed]:animate-fade-up
group-data-[state=closed]:animate-ease-in
'>
<div className='alert alert-success'>
<Toast.Title>{toast.title}</Toast.Title>
<Toast.Description>{toast.description}</Toast.Description>
<Toast.CloseTrigger>Close</Toast.CloseTrigger>
</div>
</div>
</div>
</Toast.Root>
)
},
})
group-data-[state=open]
のような複雑な指定がちょっと組み合わせになってて難しくなっているが、これはgroup
とdata-state
の組み合わせになる。
ark-ui
はdata stateという形で、data-
のattributeにstateを付与してくれる。
Toastの場合はdata-state=open
やdata-state=closed
が付与される。
group-
のprefixについてはgroup
のclass指定された親の状態によって子要素に適用したりしなかったりを切り替えられる。
これが組み合わされてgroup-data-[state=open]
のような指定になっている。
今回はわかりやすくバラバラに構成したが、Toast.Root
にopenの場合のアニメーションを指定することも出来る。
<Toast.Root className='
group
data-[state=open]:animate-duration-500
data-[state=open]:animate-fade-up
data-[state=open]:animate-normal
'>
<div className='
group-data-[state=closed]:animate-duration-500
group-data-[state=closed]:animate-reverse
group-data-[state=closed]:animate-fade-up
group-data-[state=closed]:animate-ease-in
'>
ただし、OpenとCloseで同名のアニメーションを付与すると終了時がうまく動かないケースがあるので、下記のような記載はうまくいかなかった
// ❌ うまく動かなかった例
<Toast.Root className='
group
data-[state=open]:animate-duration-500
data-[state=open]:animate-fade-up
data-[state=open]:animate-normal
data-[state=closed]:animate-duration-500
data-[state=closed]:animate-reverse
data-[state=closed]:animate-fade-up
data-[state=closed]:animate-ease-in
'>
Discussion