feat: establish shared Ekklesia design system
This commit is contained in:
@@ -1,9 +1,63 @@
|
||||
import { type ReactElement, type ReactNode, useEffect, useId, useRef } from "react";
|
||||
import {
|
||||
type HTMLAttributes,
|
||||
type ReactElement,
|
||||
type ReactNode,
|
||||
useEffect,
|
||||
useId,
|
||||
useRef,
|
||||
} from "react";
|
||||
import { classNames } from "./class-names.js";
|
||||
|
||||
/** Containers: the panel a screen is built from, the dialog that interrupts it, and the tab strip
|
||||
* that divides it. */
|
||||
|
||||
export interface PageHeaderProps {
|
||||
readonly title: ReactNode;
|
||||
readonly description?: ReactNode;
|
||||
readonly actions?: ReactNode;
|
||||
readonly eyebrow?: ReactNode;
|
||||
readonly className?: string;
|
||||
}
|
||||
|
||||
/** The consistent top-level identity and primary-action region for an Ekklesia screen. */
|
||||
export function PageHeader(props: PageHeaderProps): ReactElement {
|
||||
return (
|
||||
<header className={classNames("ek-page-header", props.className)}>
|
||||
<div className="ek-page-header__copy">
|
||||
{props.eyebrow === undefined ? undefined : (
|
||||
<span className="ek-page-header__eyebrow">{props.eyebrow}</span>
|
||||
)}
|
||||
<h1 className="ek-page-header__title">{props.title}</h1>
|
||||
{props.description === undefined ? undefined : (
|
||||
<p className="ek-page-header__description">{props.description}</p>
|
||||
)}
|
||||
</div>
|
||||
{props.actions === undefined ? undefined : (
|
||||
<div className="ek-page-header__actions">{props.actions}</div>
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export interface ActionBarProps extends HTMLAttributes<HTMLDivElement> {
|
||||
readonly children?: ReactNode;
|
||||
readonly label?: string;
|
||||
}
|
||||
|
||||
/** A wrapping row of related controls with predictable spacing and alignment. */
|
||||
export function ActionBar(props: ActionBarProps): ReactElement {
|
||||
const { children, className, label, ...rest } = props;
|
||||
return (
|
||||
<div
|
||||
{...rest}
|
||||
{...(label === undefined ? {} : { "aria-label": label })}
|
||||
className={classNames("ek-action-bar", className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export interface PanelProps {
|
||||
readonly title?: ReactNode;
|
||||
readonly description?: ReactNode;
|
||||
@@ -26,7 +80,7 @@ export function Panel(props: PanelProps): ReactElement {
|
||||
>
|
||||
{hasHeader ? (
|
||||
<header className="ek-panel__header">
|
||||
<div>
|
||||
<div className="ek-panel__heading">
|
||||
{props.title === undefined ? undefined : (
|
||||
<h2 className="ek-panel__title">{props.title}</h2>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user