Behive Tech Registry

Sidebar

v0.4.0

A dumb, styled sidebar shell — sticky, full-height, scrollable flex container. It renders an `<aside>` and applies no internal structure; the consumer is responsible for composing whatever goes inside (logo, nav, `NavItem`s, etc.).

pnpm add @behivetech/atoms.sidebar

registry/behivetech/atoms/sidebar · depends on @behivetech/get-class-name

sidebar.tsx
1import { type HTMLAttributes, type ReactNode } from "react";
2import { getClassName } from "@behivetech/get-class-name";
3import styles from "./sidebar.module.scss";
4
5export interface SidebarProps extends HTMLAttributes<HTMLElement> {
6 /** Additional class names to merge with the component root element */
7 className?: string;
8 /** Content to render inside the sidebar */
9 children?: ReactNode;
10}
11
12/**
13 * Dumb, styled sidebar shell — sticky, full-height, scrollable container.
14 * Composition of logo, nav, links, etc. is left entirely to the consumer.
15 */
16export const Sidebar = ({ className, children, ...rest }: SidebarProps) => {
17 const [rootClass] = getClassName({
18 className,
19 rootClass: "BHT__Sidebar",
20 styles,
21 });
22
23 return (
24 <aside {...rest} className={rootClass}>
25 {children}
26 </aside>
27 );
28};
sidebar.module.scss
1// Material Design 3 standard navigation drawer container. The background
2// previously came from `--admin-sidebar-bg`, which only the CMS admin app
3// defined.
4
5.BHT__Sidebar {
6 display: flex;
7 flex-direction: column;
8 position: sticky;
9 top: 0;
10 height: 100vh;
11 overflow-y: auto;
12 background: var(--md-sys-color-surface-container-low, var(--color-surface));
13 color: var(--md-sys-color-on-surface-variant, var(--color-text-muted));
14}
index.ts
1export { Sidebar } from "./sidebar.js";
2export type { SidebarProps } from "./sidebar.js";
sidebar.composition.tsx
1import { Sidebar } from "./sidebar.js";
2
3export const BasicSidebar = () => <Sidebar>Sidebar content</Sidebar>;
sidebar.spec.tsx
1import { render, screen } from "@testing-library/react";
2import { Sidebar } from "./sidebar.js";
3
4describe("Sidebar", () => {
5 it("renders children", () => {
6 render(<Sidebar>Hello</Sidebar>);
7 expect(screen.getByText("Hello")).toBeTruthy();
8 });
9
10 it("applies additional className", () => {
11 render(<Sidebar className="custom">Content</Sidebar>);
12 expect(screen.getByText("Content").className).toContain("custom");
13 });
14});