Stacks and InlineCode

This commit is contained in:
Gregory Schier
2026-03-12 19:45:19 -07:00
parent 4d792c7f9f
commit 77ec87ea17
74 changed files with 293 additions and 324 deletions

View File

@@ -0,0 +1,22 @@
import classNames from 'classnames';
import type { HTMLAttributes } from 'react';
interface Props extends HTMLAttributes<HTMLHeadingElement> {
level?: 1 | 2 | 3;
}
export function Heading({ className, level = 1, ...props }: Props) {
const Component = level === 1 ? 'h1' : level === 2 ? 'h2' : 'h3';
return (
<Component
className={classNames(
className,
'font-semibold text-text',
level === 1 && 'text-2xl',
level === 2 && 'text-xl',
level === 3 && 'text-lg',
)}
{...props}
/>
);
}

View File

@@ -0,0 +1,93 @@
import classNames from 'classnames';
import type { ComponentType, ForwardedRef, HTMLAttributes, ReactNode } from 'react';
import { forwardRef } from 'react';
const gapClasses = {
0: 'gap-0',
0.5: 'gap-0.5',
1: 'gap-1',
1.5: 'gap-1.5',
2: 'gap-2',
3: 'gap-3',
4: 'gap-4',
5: 'gap-5',
6: 'gap-6',
};
interface HStackProps extends BaseStackProps {
children?: ReactNode;
}
export const HStack = forwardRef(function HStack(
{ className, space, children, alignItems = 'center', ...props }: HStackProps,
// biome-ignore lint/suspicious/noExplicitAny: none
ref: ForwardedRef<any>,
) {
return (
<BaseStack
ref={ref}
className={classNames(className, 'flex-row', space != null && gapClasses[space])}
alignItems={alignItems}
{...props}
>
{children}
</BaseStack>
);
});
export type VStackProps = BaseStackProps & {
children: ReactNode;
};
export const VStack = forwardRef(function VStack(
{ className, space, children, ...props }: VStackProps,
// biome-ignore lint/suspicious/noExplicitAny: none
ref: ForwardedRef<any>,
) {
return (
<BaseStack
ref={ref}
className={classNames(className, 'flex-col', space != null && gapClasses[space])}
{...props}
>
{children}
</BaseStack>
);
});
type BaseStackProps = HTMLAttributes<HTMLElement> & {
as?: ComponentType | 'ul' | 'label' | 'form' | 'p';
space?: keyof typeof gapClasses;
alignItems?: 'start' | 'center' | 'stretch' | 'end';
justifyContent?: 'start' | 'center' | 'end' | 'between';
wrap?: boolean;
};
const BaseStack = forwardRef(function BaseStack(
{ className, alignItems, justifyContent, wrap, children, as, ...props }: BaseStackProps,
// biome-ignore lint/suspicious/noExplicitAny: none
ref: ForwardedRef<any>,
) {
const Component = as ?? 'div';
return (
<Component
ref={ref}
className={classNames(
className,
'flex',
wrap && 'flex-wrap',
alignItems === 'center' && 'items-center',
alignItems === 'start' && 'items-start',
alignItems === 'stretch' && 'items-stretch',
alignItems === 'end' && 'items-end',
justifyContent === 'start' && 'justify-start',
justifyContent === 'center' && 'justify-center',
justifyContent === 'end' && 'justify-end',
justifyContent === 'between' && 'justify-between',
)}
{...props}
>
{children}
</Component>
);
});

View File

@@ -1,36 +1,47 @@
export { Button } from "./components/Button";
export type { ButtonProps } from "./components/Button";
export { HeaderSize } from "./components/HeaderSize";
export { Icon } from "./components/Icon";
export type { IconProps } from "./components/Icon";
export { IconButton } from "./components/IconButton";
export type { IconButtonProps } from "./components/IconButton";
export { LoadingIcon } from "./components/LoadingIcon";
export { useTimedBoolean } from "./hooks/useTimedBoolean";
export { WindowControls } from "./components/WindowControls";
export { useIsFullscreen } from "./hooks/useIsFullscreen";
export { useDebouncedValue } from "./hooks/useDebouncedValue";
export { useDebouncedState } from "./hooks/useDebouncedState";
export { HEADER_SIZE_MD, HEADER_SIZE_LG, WINDOW_CONTROLS_WIDTH } from "./lib/constants";
export { DropMarker } from "./components/DropMarker";
export { computeSideForDragMove } from "./lib/dnd";
export { Tree } from "./components/tree/Tree";
export type { TreeHandle, TreeProps } from "./components/tree/Tree";
export type { TreeNode } from "./components/tree/common";
export type { TreeItemProps } from "./components/tree/TreeItem";
export { isSelectedFamily, selectedIdsFamily } from "./components/tree/atoms";
export { minPromiseMillis } from "./lib/minPromiseMillis";
export { ResizeHandle } from "./components/ResizeHandle";
export { SidebarLayout } from "./components/SidebarLayout";
export type { ResizeHandleEvent } from "./components/ResizeHandle";
export { SplitLayout } from "./components/SplitLayout";
export type { SplitLayoutLayout, SlotProps } from "./components/SplitLayout";
export { Table, TableBody, TableHead, TableRow, TableCell, TruncatedWideTableCell, TableHeaderCell } from "./components/Table";
export { clamp } from "./lib/clamp";
export { useContainerSize } from "./hooks/useContainerSize";
export { Overlay } from "./components/Overlay";
export { Portal } from "./components/Portal";
export { usePortal } from "./hooks/usePortal";
export { Banner } from "./components/Banner";
export type { BannerProps } from "./components/Banner";
export { InlineCode } from "./components/InlineCode";
export type { BannerProps } from './components/Banner';
export { Banner } from './components/Banner';
export type { ButtonProps } from './components/Button';
export { Button } from './components/Button';
export { DropMarker } from './components/DropMarker';
export { HeaderSize } from './components/HeaderSize';
export { Heading } from './components/Heading';
export type { IconProps } from './components/Icon';
export { Icon } from './components/Icon';
export type { IconButtonProps } from './components/IconButton';
export { IconButton } from './components/IconButton';
export { InlineCode } from './components/InlineCode';
export { LoadingIcon } from './components/LoadingIcon';
export { Overlay } from './components/Overlay';
export { Portal } from './components/Portal';
export type { ResizeHandleEvent } from './components/ResizeHandle';
export { ResizeHandle } from './components/ResizeHandle';
export { SidebarLayout } from './components/SidebarLayout';
export type { SlotProps, SplitLayoutLayout } from './components/SplitLayout';
export { SplitLayout } from './components/SplitLayout';
export type { VStackProps } from './components/Stacks';
export { HStack, VStack } from './components/Stacks';
export {
Table,
TableBody,
TableCell,
TableHead,
TableHeaderCell,
TableRow,
TruncatedWideTableCell,
} from './components/Table';
export { isSelectedFamily, selectedIdsFamily } from './components/tree/atoms';
export type { TreeNode } from './components/tree/common';
export type { TreeHandle, TreeProps } from './components/tree/Tree';
export { Tree } from './components/tree/Tree';
export type { TreeItemProps } from './components/tree/TreeItem';
export { WindowControls } from './components/WindowControls';
export { useContainerSize } from './hooks/useContainerSize';
export { useDebouncedState } from './hooks/useDebouncedState';
export { useDebouncedValue } from './hooks/useDebouncedValue';
export { useIsFullscreen } from './hooks/useIsFullscreen';
export { usePortal } from './hooks/usePortal';
export { useTimedBoolean } from './hooks/useTimedBoolean';
export { clamp } from './lib/clamp';
export { HEADER_SIZE_LG, HEADER_SIZE_MD, WINDOW_CONTROLS_WIDTH } from './lib/constants';
export { computeSideForDragMove } from './lib/dnd';
export { minPromiseMillis } from './lib/minPromiseMillis';