99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
import { JSXElement } from "solid-js";
|
|
|
|
interface CardProps {
|
|
class?: string;
|
|
children?: JSXElement;
|
|
}
|
|
|
|
// `ui-card` / `no-flex` class names are kept so page-specific CSS (e.g.
|
|
// support.css) that targets them can keep overriding. All baseline
|
|
// styling is Tailwind.
|
|
const CARD_BASE = "ui-card bg-white shadow-sm rounded-default w-full";
|
|
const CARD_WITH_PADDING = CARD_BASE + " p-5 flex-1";
|
|
const CARD_NO_FLEX = CARD_BASE + " no-flex p-5";
|
|
const CARD_NO_PADDING_NO_FLEX = CARD_BASE + " no-padding no-flex";
|
|
|
|
const BORDER_CARD = "border border-neutral-300 rounded-default p-5 w-full";
|
|
|
|
// Cut-corner card uses two pseudo-elements with clip-paths to create the
|
|
// notched corners. Tailwind supports arbitrary clip-path values.
|
|
const CUT_CORNER_CARD =
|
|
"relative isolate p-5 w-full " +
|
|
"before:content-[''] before:absolute before:inset-0 before:bg-neutral-300 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)]";
|
|
|
|
export function Card(props: CardProps) {
|
|
return (
|
|
<div class={CARD_WITH_PADDING + " " + (props.class || "")}>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function CardNoPadding(props: CardProps) {
|
|
return (
|
|
<div class={CARD_NO_PADDING_NO_FLEX + " " + (props.class || "")}>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function CardNoFlexGrow(props: CardProps) {
|
|
return (
|
|
<div class={CARD_NO_FLEX + " " + (props.class || "")}>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function BorderCard(props: CardProps) {
|
|
return (
|
|
<div class={BORDER_CARD + " " + (props.class || "")}>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function BorderCutCornerCard(props: CardProps) {
|
|
return (
|
|
<div class={CUT_CORNER_CARD + " " + (props.class || "")}>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const CARD_HEADER = "text-xl tracking-tight text-black mb-5";
|
|
const CARD_HEADER_HR = "text-neutral-200 mt-1 mb-3";
|
|
|
|
export function CardHeader(props: CardProps) {
|
|
return (
|
|
<div class={CARD_HEADER + " " + (props.class || "")}>
|
|
{props.children}
|
|
<hr class={CARD_HEADER_HR}/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function CardHeaderTextCenter(props: CardProps) {
|
|
return (
|
|
<div class={CARD_HEADER + " text-center " + (props.class || "")}>
|
|
{props.children}
|
|
<hr class={CARD_HEADER_HR}/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function CardSubheader(props: CardProps) {
|
|
return (
|
|
<div class={"text-lg tracking-tight text-black mb-2 " + (props.class || "")}>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function CardSpacer() {
|
|
return <div class="mb-6"></div>;
|
|
}
|