package webui import "kjol/vdom" // Port of web/kit/Cards.tsx. The `ui-card`/`no-flex` marker classes are kept so // any page CSS targeting them still applies; baseline styling is Tailwind. const cardBase = "ui-card bg-surface shadow-sm rounded-default w-full" const cardWithPadding = cardBase + " p-5 flex-1" const cardNoFlex = cardBase + " no-flex p-5" const cardNoPaddingNoFlex = cardBase + " no-padding no-flex" const borderCard = "border border-line-strong rounded-default p-5 w-full" // cutCornerCard uses two clip-path pseudo-elements to notch opposite corners. const cutCornerCard = "relative isolate p-5 w-full " + "before:content-[''] before:absolute before:inset-0 before:bg-surface-strong before:-z-20 " + "before:[clip-path:polygon(16px_0,100%_0,100%_calc(100%_-_16px),calc(100%_-_16px)_100%,0_100%,0_16px)] " + "after:content-[''] after:absolute after:inset-[1px] after:bg-white after:-z-10 " + "after:[clip-path:polygon(15px_0,100%_0,100%_calc(100%_-_15px),calc(100%_-_15px)_100%,0_100%,0_15px)]" func cardDiv(base, class string, children []*vdom.VNode) *vdom.VNode { return vdom.Div(kids([]vdom.Mod{vdom.Attr("class", cx(base, class))}, children)...) } // Card is the standard padded, flex-grow card. func Card(class string, children ...*vdom.VNode) *vdom.VNode { return cardDiv(cardWithPadding, class, children) } // CardNoPadding is a card with no padding and no flex-grow. func CardNoPadding(class string, children ...*vdom.VNode) *vdom.VNode { return cardDiv(cardNoPaddingNoFlex, class, children) } // CardNoFlexGrow is a padded card that does not flex-grow. func CardNoFlexGrow(class string, children ...*vdom.VNode) *vdom.VNode { return cardDiv(cardNoFlex, class, children) } // BorderCard is a bordered (shadowless) card. func BorderCard(class string, children ...*vdom.VNode) *vdom.VNode { return cardDiv(borderCard, class, children) } // BorderCutCornerCard is a card with two notched corners (clip-path). func BorderCutCornerCard(class string, children ...*vdom.VNode) *vdom.VNode { return cardDiv(cutCornerCard, class, children) } const cardHeader = "text-xl tracking-tight text-ink mb-5" const cardHeaderHR = "text-neutral-200 mt-1 mb-3" // CardHeader renders a card title followed by a divider. func CardHeader(class string, children ...*vdom.VNode) *vdom.VNode { mods := kids([]vdom.Mod{vdom.Attr("class", cx(cardHeader, class))}, children) mods = append(mods, vdom.Hr(vdom.Attr("class", cardHeaderHR))) return vdom.Div(mods...) } // CardHeaderTextCenter is CardHeader, centered. func CardHeaderTextCenter(class string, children ...*vdom.VNode) *vdom.VNode { mods := kids([]vdom.Mod{vdom.Attr("class", cx(cardHeader, "text-center", class))}, children) mods = append(mods, vdom.Hr(vdom.Attr("class", cardHeaderHR))) return vdom.Div(mods...) } // CardSubheader renders a smaller secondary heading. func CardSubheader(class string, children ...*vdom.VNode) *vdom.VNode { return vdom.Div(kids([]vdom.Mod{vdom.Attr("class", cx("text-lg tracking-tight text-ink mb-2", class))}, children)...) } // CardSpacer is vertical spacing between cards. func CardSpacer() *vdom.VNode { return vdom.Div(vdom.Attr("class", "mb-6")) }