Accordion
アコーディオン要素を作成できるUIコンポーネントです。
Accordion Example
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Accordion Example
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Accordion.Root p='15'> <Accordion.Header> <Accordion.Label>Accordion Example</Accordion.Label> <Accordion.Icon /> </Accordion.Header> <Accordion.Body my-s='15'> <Dummy length='l' /> </Accordion.Body></Accordion.Root>基本構造
details.d--accordion summary.d--accordion_header span.d--accordion_label Accordion Label span.d--accordion_icon svg.a--icon div.d--accordion_body div.d--accordion_inner(.l--flow) ...Contents...ソースコード
@layer lism.modules {
.d--accordion {
--duration: var(--acc-duration, 0.25s);
}
.d--accordion[data-opened] {
--_notOpen: ;
}
.d--accordion:not([data-opened]) {
--_isOpen: ;
}
.d--accordion_header {
display: grid;
grid: auto / 1fr auto;
gap: 0.5em;
align-items: center;
--focus-offset: -1px; /* overflow:hidden; で見えなくなってしまいがちなので内側に寄せておく */
/* Safariで表示されるデフォルトの三角形アイコンを消す */
&::-webkit-details-marker {
display: none;
}
}
.d--accordion_body {
display: grid;
grid: 1fr / auto;
transition-property: margin-block, padding-block, opacity, grid-template;
transition-duration: var(--duration);
}
/* ※ 正常な animation には必須 */
.d--accordion_inner {
overflow: hidden;
}
/* 閉じている時 */
.d--accordion:not([data-opened]) > .d--accordion_body {
grid: 0fr / auto;
padding-block: 0 !important;
margin-block: 0 !important;
}
/* アコーディオンブロックのネスト時、別のアイコンタイプにすると表示が崩れるがそこまでは考慮しない。 */
.d--accordion_icon {
display: grid;
}
/* .d--accordion_icon 自体にborderつけたりすると回転が見えてしまうので、中にある .a--icon を回転させる。 */
.d--accordion_icon > .a--icon {
transition: transform var(--duration);
transform: var(--_isOpen, scaleY(-1));
}
} Import
@lism-css/ui パッケージで提供しています。
import { Accordion } from '@lism-css/ui/react'; 以下のコンポーネントが利用できます。
<Accordion.Root><Accordion.Header><Accordion.Label><Accordion.Icon><Accordion.Body>
さらに、.HeaderLabel を使うと、.Header, .Label, .Icon をまとめて配置できるようになっています。
<Accordion.HeaderLabel {...props}>Text</Accordion.HeaderLabel>
↓ これは以下のように内部で展開されます
<Accordion.Header {...props}> <Accordion.Label>Text</Accordion.Label> <Accordion.Icon/></Accordion.Header>Props
| プロパティ | 説明 |
|---|---|
<Accordion.Icon> icon | 内部で呼び出される<Icon> に渡す icon を指定できます。ただし、<Accordion.Icon>に子要素が配置されている場合は無視されます。 |
<Accordion.Icon> isTrigger | アイコンが buttonタグでの出力となり[data-role="trigger"]が付与されます。 |
<Accordion.Body> flow | __innerに渡されます。 |
Examples
ラベルのHTMLタグとアイコンを変更する
ラベルをh3タグに、アイコンを x に変える例を紹介します。
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Stack bd-y> <Accordion.Root> <Accordion.Header p="15"> <Accordion.Label tag='h3' f='inherit' fw='bold'>Accordion Label</Accordion.Label> <Accordion.Icon> <Icon viewBox="0 0 256 256" style={{transform: 'var(--_isOpen, rotate(45deg))'}}> <path d="M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z"></path> </Icon> </Accordion.Icon> </Accordion.Header> <Accordion.Body p='15' py-s='5'> <Dummy length='l' /> </Accordion.Body> </Accordion.Root> <Accordion.Root bd-t> <Accordion.Header p="15"> <Accordion.Label tag='h3' f='inherit' fw='bold'>Accordion Label</Accordion.Label> <Accordion.Icon> <Icon viewBox="0 0 256 256" style={{transform: 'var(--_isOpen, rotate(45deg))'}}> <path d="M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z"></path> </Icon> </Accordion.Icon> </Accordion.Header> <Accordion.Body p='15' py-s='5'> <Dummy length='l' /> </Accordion.Body> </Accordion.Root></Stack>summary 内の hタグは、スクリーンリーダーで読み上げる際に見出しとして認識されないという問題があります。
アニメーション時間を変更し、アコーディオンの複数同時展開を禁止する
アコーディオンの開閉アニメーションの時間は--acc-durationで管理できるようになっており、親要素に変数をセットすると、複数のアコーディオンに対して一括管理できます。
:rootの--acc-durationを上書きすると、サイト全体でデフォルトの開閉速度を変更できます。
また、複数の<Accordion.Root>(.d--accordion)を含む親要素に [data-multiple="disallow"]を指定することで、アコーディオンを複数同時に開くことを禁止することが可能です。
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint. Occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis undeomnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Stack g='1px' data-multiple='disallow' style={{'--acc-duration': '.2s'}}> <Accordion.Root> <Accordion.HeaderLabel p='20' bgc='text' c='base' hov="neutral">Accordion Label</Accordion.HeaderLabel> <Accordion.Body p='20'> <Dummy length='l' /> </Accordion.Body> </Accordion.Root> <Accordion.Root> <Accordion.HeaderLabel p='20' bgc='text' c='base' hov="neutral">Accordion Label</Accordion.HeaderLabel> <Accordion.Body p='20'> <Dummy length='xl' /> </Accordion.Body> </Accordion.Root> <Accordion.Root> <Accordion.HeaderLabel p='20' bgc='text' c='base' hov="neutral">Accordion Label</Accordion.HeaderLabel> <Accordion.Body p='20'> <Dummy length='l' /> </Accordion.Body> </Accordion.Root> ...</Stack>Opt-in 機能
追加でCSSが必要な機能
開閉時にアイコンを切り替える方法
追加で少しCSSを加える必要がありますが、開閉時にアイコンを切り替える例も紹介します。
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Accordion Label
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Stack g='15'> <Accordion.Root bgc='base' bxsh='10' bdrs='10' ov='hidden'> <Accordion.Header p='20' bgc='base-2' hov='neutral'> <Accordion.Label>Accordion Label</Accordion.Label> <Accordion.Icon> <Icon setTransition ga='1/1' viewBox="0 0 256 256"> <path d="M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z"></path> </Icon> <Icon setTransition ga='1/1' viewBox="0 0 256 256"> <path d="M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z"></path> </Icon> </Accordion.Icon> </Accordion.Header> <Accordion.Body p='20'> <Dummy length='l' /> </Accordion.Body> </Accordion.Root> <Accordion.Root bgc='base' bxsh='10' bdrs='10' ov='hidden'> <Accordion.Header p='20' bgc='base-2' hov='neutral'> <Accordion.Label>Accordion Label</Accordion.Label> <Accordion.Icon> <Icon setTransition ga='1/1' viewBox="0 0 256 256"> <path d="M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z"></path> </Icon> <Icon setTransition ga='1/1' viewBox="0 0 256 256"> <path d="M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z"></path> </Icon> </Accordion.Icon> </Accordion.Header> <Accordion.Body p='20'> <Dummy length='l' /> </Accordion.Body> </Accordion.Root></Stack>