UNPKG

simple-tabs-component

Version:

Keyboard accessible Tabs Web Component that changes to an Accordion in small spaces.

139 lines (122 loc) 3.35 kB
/* Scoped Style Sheet (loaded inside the Web Component's <template>) */ :host { --_color: var(--st-color, #0000ff); --_tab-font: var(--st-tab-font, system-ui); --_max-tabs: var(--st-max-tabs, 10); --_color-primary: light-dark( oklch(from var(--_color) 50% c h), oklch(from var(--_color) 85% 75% h) ); --_color-muted: light-dark( oklch(from var(--_color) 90% 10% h), oklch(from var(--_color) 40% 20% h) ); container: tabs / inline-size; display: block; } *, *::before, *::after { box-sizing: border-box; } .simple-tabs { display: grid; gap: 0; align-content: start; grid-template-columns: repeat(var(--_max-tabs), auto) 1fr; grid-template-rows: auto auto; } [role=tab] { grid-row: 1; width: max-content; font-weight: bold; font-family: var(--_tab-font); padding: .5em 1em; margin-block-end: 0; box-shadow: 0 3px 0 var(--_color-muted); z-index: 1; &:has(:checked) { pointer-events: none; box-shadow: 0 3px 0 var(--_color-primary); } &:not(:has(:checked)):hover { cursor: pointer; color: var(--_color-primary); } /* when :focus-visible (on keyboard navigation) */ &:has([type=radio]:focus-visible) { outline: solid 1.5px var(--_color-primary); outline-offset: -3px; border-radius: 8px 8px 0 0; } /* visually hide radio inputs */ input[type=radio] { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; width: 1px; } } [role=tabpanel] { grid-row: 2; grid-column: 1 / -1; transition: opacity 300ms ease-in-out; &:where([role=tab]:has(:checked) + *) { pointer-events: unset; } &:where([role=tab]:not(:has(:checked)) + *) { display: none; } & > :first-child { margin-block-start: 0; border-top: solid 3px var(--_color-muted); padding-block-start: 1rem; } } /* Stack (into an accordion) in small spaces */ @container tabs (width <= 600px) { .simple-tabs { grid-template-columns: unset; grid-template-rows: repeat(auto-fill, auto); [role=tab] { grid-row: unset; width: 100%; padding-inline: 0; display: flex; justify-content: space-between; align-items: center; flex-wrap: nowrap; &:has(:checked) { margin-bottom: -1.5rem; box-shadow: none; box-shadow: 0 3px 0 var(--_color-primary); border: 0; } &:not(:has(:checked)) { box-shadow: 0 2px 0 var(--_color-muted); } &:has(:focus-visible) { margin-block-start: 10px; outline-offset: 1px; padding-inline: 0.5rem; } /* chevrons ▾▿ */ &::after { color: inherit; width: 1em; height: 1em; display: inline-grid; place-content: center; content: "▾"; /** content: ""; background-image: url('data:image/svg+xml,%3Csvg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M7 10l5 5 5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/%3E%3C/svg%3E'); /**/ } &:has(:checked)::after { color: var(--_color-primary); } } [role=tabpanel] { grid-column: unset; grid-row: unset; margin-block-start: 1.5rem; border-bottom: solid 2px var(--_color-muted); box-shadow: none; /* &:last-child { border-bottom-color: transparent; } */ & > div { border-top: solid 2px transparent; border-top: solid 2px var(--_color-primary); } } } }