StackCard.tsx

1.8 KB · raw

1import type { JSX } from "solid-js";2import { CardIcon } from "./CardIcon";3import type { StackCardSpec } from "./types";45interface StackCardProps {6  spec: StackCardSpec;7  active: boolean;8  focused?: boolean;9  concealed?: boolean;10  top: number;11  zIndex: number;12  height: number;13  onClick: () => void;14  children: JSX.Element;15}1617export function StackCard(props: StackCardProps) {18  return (19    <article20      class={`stk-card ${props.active ? "is-active" : "is-tab"} ${props.focused ? "is-focused" : ""} ${props.concealed ? "is-concealed" : ""}`}21      data-settings-card-id={props.spec.id}22      data-active={props.active ? "true" : "false"}23      role={props.active || props.concealed ? undefined : "button"}24      aria-hidden={props.concealed ? "true" : undefined}25      aria-label={props.active || props.concealed ? undefined : `Open ${props.spec.title}`}26      tabIndex={props.active || props.concealed ? -1 : 0}27      onClick={() => {28        if (!props.active && !props.concealed) props.onClick();29      }}30      onKeyDown={(e) => {31        if (props.active) return;32        if (e.key === "Enter" || e.key === " ") {33          e.preventDefault();34          props.onClick();35        }36      }}37      style={{38        background: `var(${props.spec.bgVar})`,39        color: `var(${props.spec.fgVar})`,40        transform: `translateY(${props.top}px)`,41        "z-index": props.zIndex,42        height: `${props.height}px`,43      }}44    >45      <div class="stk-card-top">46        <span class="stk-card-num">{props.spec.num}</span>47        <span class="stk-card-icon">48          <CardIcon kind={props.spec.icon} />49        </span>50      </div>51      <h2 class="stk-card-title">{props.spec.title}</h2>52      <p class="stk-card-lede">{props.spec.lede}</p>53      <div class="stk-card-body">{props.children}</div>54    </article>55  );56}