UNPKG

vira

Version:

A simple and highly versatile design system using element-vir.

175 lines (159 loc) 5.58 kB
import { css, defineElementEvent, html, listen, nothing, testId } from 'element-vir'; import { ChevronUp16Icon } from '../icons/index.js'; import { viraFontCssVars } from '../styles/font.js'; import { viraFormCssVars } from '../styles/form-styles.js'; import { defineViraElement } from '../util/define-vira-element.js'; import { ViraCollapsibleWrapper } from './vira-collapsible-wrapper.element.js'; import { ViraIcon } from './vira-icon.element.js'; /** * A combination ViraCard and ViraCollapsibleWrapper with a collapse caret. * * @category Elements * @see https://electrovir.github.io/vira/book/elements/vira-checkbox */ export const ViraCollapsibleCard = defineViraElement()({ tagName: 'vira-collapsible-card', testIds: ['openCaret'], events: { expandToggle: defineElementEvent(), }, state({ inputs }) { return { isExpanded: !!inputs.startExpanded, }; }, hostClasses: { 'vira-collapsible-card-expanded': ({ state }) => state.isExpanded, 'vira-collapsible-card-expansion-blocked': ({ inputs }) => !!inputs.blockExpansion, 'vira-collapsible-card-card-styles': ({ inputs }) => !inputs.rawCollapsible, }, cssVars: { 'vira-collapsible-card-content-gap': '16px', }, styles: ({ hostClasses, cssVars }) => css ` :host { display: inline-flex; max-width: 100%; box-sizing: border-box; overflow: hidden; } ${hostClasses['vira-collapsible-card-expanded'].selector} .open-caret { transform: rotate(180deg); } ${ViraCollapsibleWrapper} { flex-grow: 1; max-width: 100%; } ${hostClasses['vira-collapsible-card-card-styles'].selector} { border-radius: ${viraFormCssVars['vira-form-wrapper-radius'].value}; & ${ViraCollapsibleWrapper} { border: 1px solid ${viraFormCssVars['vira-form-border-color'].value}; border-radius: ${viraFormCssVars['vira-form-wrapper-radius'].value}; } & .card-header { padding: 8px 16px; } & .card-content { padding: 8px 16px 8px 16px; } } ${hostClasses['vira-collapsible-card-expansion-blocked'].selector} { & .header-wrapper { cursor: default; } } .card-header { font-weight: ${viraFontCssVars['vira-font-weight-bold'].value}; display: flex; align-items: center; justify-content: space-between; gap: 8px; & .header-filler { flex-grow: 1; } } .card-content { display: flex; flex-direction: column; align-items: stretch; gap: ${cssVars['vira-collapsible-card-content-gap'].value}; overflow-x: auto; overflow-y: hidden; } @media print { ${ViraCollapsibleWrapper} { border: none !important; } .card-header { padding: 8px 0 !important; } .card-content { overflow: visible !important; padding: 8px 0 16px 0 !important; } .open-caret { display: none; } } `, slotNames: [ 'vira-collapsible-card-header', ], render({ inputs, slotNames, state, updateState, testIds, dispatch, events }) { if (inputs.blockExpansion) { updateState({ isExpanded: true, }); } const wrapperContentTemplate = html ` <div class="card-content"> <slot></slot> </div> `; const wrapperHeaderTemplate = inputs.hideHeader ? nothing : html ` <div class="card-header"> <slot name=${slotNames['vira-collapsible-card-header']}> <div class="header-filler"></div> </slot> ${inputs.blockExpansion ? nothing : html ` <${ViraIcon.assign({ icon: ChevronUp16Icon, fitContainer: true, })} ${testId(testIds.openCaret)} class="open-caret" ></${ViraIcon}> `} </div> `; return html ` <${ViraCollapsibleWrapper.assign({ expanded: state.isExpanded, expandOnPrint: inputs.expandOnPrint ?? false, })} ${listen(ViraCollapsibleWrapper.events.expandChange, (event) => { event.stopImmediatePropagation(); if (inputs.blockExpansion) { return; } updateState({ isExpanded: event.detail, }); dispatch(new events.expandToggle(event.detail)); })} > <div class="header-wrapper" slot=${ViraCollapsibleWrapper.slotNames['vira-collapsible-wrapper-header']} > ${wrapperHeaderTemplate} </div> ${wrapperContentTemplate} </${ViraCollapsibleWrapper}> `; }, });