diff --git a/src/components/admin/CardList.tsx b/src/components/admin/CardList.tsx
new file mode 100644
index 0000000..6484236
--- /dev/null
+++ b/src/components/admin/CardList.tsx
@@ -0,0 +1,61 @@
+import { ReactNode } from "react";
+
+interface CardListProps {
+ children: ReactNode;
+ ariaLabel?: string;
+}
+
+export function CardList({ children, ariaLabel }: CardListProps) {
+ return (
+
+ );
+}
+
+interface CardListItemProps {
+ onClick?: () => void;
+ href?: string;
+ children: ReactNode;
+ as?: "li" | "div";
+}
+
+export function CardListItem({ onClick, href, children, as = "li" }: CardListItemProps) {
+ const content = (
+
+ {children}
+
+ );
+
+ if (href) {
+ return (
+
+
+ {content}
+
+
+ );
+ }
+ if (onClick) {
+ return (
+
+
+
+ );
+ }
+ return {content};
+}
diff --git a/src/components/admin/PageHeader.tsx b/src/components/admin/PageHeader.tsx
new file mode 100644
index 0000000..086e149
--- /dev/null
+++ b/src/components/admin/PageHeader.tsx
@@ -0,0 +1,25 @@
+import { ReactNode } from "react";
+
+interface PageHeaderProps {
+ title: string;
+ subtitle?: string;
+ actions?: ReactNode;
+}
+
+export function PageHeader({ title, subtitle, actions }: PageHeaderProps) {
+ return (
+
+
+
+ {title}
+
+ {subtitle && (
+
{subtitle}
+ )}
+
+ {actions && {actions}
}
+
+ );
+}
+
+export default PageHeader;
diff --git a/src/components/admin/StatusPill.tsx b/src/components/admin/StatusPill.tsx
new file mode 100644
index 0000000..0e00b48
--- /dev/null
+++ b/src/components/admin/StatusPill.tsx
@@ -0,0 +1,35 @@
+export type StatusKind = "placed" | "ready" | "picked-up" | "cancelled" | "scheduled" | "in-transit" | "completed" | "low" | "out" | "in-stock" | "hidden";
+
+const STATUS_MAP: Record = {
+ placed: { bg: "var(--color-info-soft)", fg: "var(--color-info)", label: "Placed" },
+ ready: { bg: "var(--color-warning-soft)", fg: "var(--color-warning)", label: "Ready" },
+ "picked-up": { bg: "var(--color-success-soft)", fg: "var(--color-success)", label: "Picked up" },
+ cancelled: { bg: "var(--color-surface-2)", fg: "var(--color-text-muted)", label: "Cancelled" },
+ scheduled: { bg: "var(--color-info-soft)", fg: "var(--color-info)", label: "Scheduled" },
+ "in-transit": { bg: "var(--color-warning-soft)", fg: "var(--color-warning)", label: "In transit" },
+ completed: { bg: "var(--color-success-soft)", fg: "var(--color-success)", label: "Completed" },
+ low: { bg: "var(--color-warning-soft)", fg: "var(--color-warning)", label: "Low stock" },
+ out: { bg: "var(--color-danger-soft)", fg: "var(--color-danger)", label: "Out" },
+ "in-stock": { bg: "var(--color-success-soft)", fg: "var(--color-success)", label: "In stock" },
+ hidden: { bg: "var(--color-surface-2)", fg: "var(--color-text-muted)", label: "Hidden" },
+};
+
+interface StatusPillProps {
+ status: StatusKind;
+ label?: string;
+}
+
+export function StatusPill({ status, label }: StatusPillProps) {
+ const cfg = STATUS_MAP[status];
+ return (
+
+ {label ?? cfg.label}
+
+ );
+}
+
+export default StatusPill;
diff --git a/src/components/admin/StickyActionBar.tsx b/src/components/admin/StickyActionBar.tsx
new file mode 100644
index 0000000..d4cc3cc
--- /dev/null
+++ b/src/components/admin/StickyActionBar.tsx
@@ -0,0 +1,30 @@
+import { ReactNode } from "react";
+
+interface StickyActionBarProps {
+ children: ReactNode;
+ pendingSync?: boolean;
+}
+
+export function StickyActionBar({ children, pendingSync = false }: StickyActionBarProps) {
+ return (
+
+ {pendingSync && (
+
+
+ Pending sync
+
+ )}
+ {children}
+
+ );
+}
+
+export default StickyActionBar;