@baramjk/design-system
v0.1.1
Published
Reusable internal UI package for Baram Next.js apps. It ships theme-aware components, curated icons, a shared stylesheet, and a Tailwind preset for downstream consumers.
Downloads
51
Readme
@baramjk/design-system
Reusable internal UI package for Baram Next.js apps. It ships theme-aware components, curated icons, a shared stylesheet, and a Tailwind preset for downstream consumers.
Repo commands
npm run dev
npm run build:package
npm run test:run
npm run storybook
npm run verify:consumerInstall in a consumer app
Authenticate your app to the private registry that publishes the @baramjk scope, then install the package:
@baramjk:registry=https://registry.example.com
//registry.example.com/:_authToken=${NPM_TOKEN}npm install @baramjk/design-systemRecommended for brand fidelity: load Geist, Geist Mono, and Manrope in the consuming app. The package now includes safe font fallbacks, so it still renders correctly if those fonts are unavailable.
Tailwind setup
Add the package preset and scan the installed package output:
// tailwind.config.js
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./node_modules/@baramjk/design-system/dist/**/*.{js,mjs}",
],
presets: [require("@baramjk/design-system/tailwind-preset")],
};Root layout setup
Import the package stylesheet once from your app globals, then wire the theme helpers into the App Router root layout. Next 16's App Router still requires app/layout.tsx to define the root <html> and <body> tags.
/* app/globals.css */
@import "@baramjk/design-system/styles.css";
.app-shell {
min-height: 100vh;
}// app/layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono, Manrope } from "next/font/google";
import {
ThemeProvider,
ThemeScript,
ThemeStyles,
} from "@baramjk/design-system";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
const manrope = Manrope({
variable: "--font-manrope",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "My App",
description: "Consumer of @baramjk/design-system",
};
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} ${manrope.variable}`}
>
<body>
<ThemeStyles />
<ThemeScript defaultTheme="neutral" />
<ThemeProvider defaultTheme="neutral">{children}</ThemeProvider>
</body>
</html>
);
}Tiny usage example
import { Button, CheckIcon, ThemeToggle } from "@baramjk/design-system";
export default function Page() {
return (
<main className="app-shell flex flex-col gap-4 p-6">
<ThemeToggle />
<Button startIcon={<CheckIcon className="size-4" />}>
Save changes
</Button>
</main>
);
}Custom themes
Pass a themes map when you want to add app-specific theme entries. For a Next consumer, keep the theme definitions in a plain local module and import that module into app/layout.tsx.
// app/app-theme.ts
import type { ThemeMap } from "@baramjk/design-system";
export const appThemes = {
acme: {
label: "Acme",
colorScheme: "light",
colors: {
background: "0 0% 100%",
foreground: "222.2 84% 4.9%",
card: "0 0% 100%",
cardForeground: "222.2 84% 4.9%",
popover: "0 0% 100%",
popoverForeground: "222.2 84% 4.9%",
primary: "142 72% 29%",
primaryForeground: "210 40% 98%",
secondary: "210 40% 96.1%",
secondaryForeground: "222.2 47.4% 11.2%",
muted: "210 40% 96.1%",
mutedForeground: "215.4 16.3% 46.9%",
accent: "210 40% 96.1%",
accentForeground: "222.2 47.4% 11.2%",
destructive: "0 84.2% 60.2%",
destructiveForeground: "210 40% 98%",
border: "214.3 31.8% 91.4%",
input: "214.3 31.8% 91.4%",
ring: "142 72% 29%",
},
radius: {
sm: "0.375rem",
md: "0.5rem",
lg: "0.75rem",
xl: "1rem",
pill: "9999px",
},
spacing: {
1: "0.25rem",
2: "0.5rem",
3: "0.75rem",
4: "1rem",
5: "1.25rem",
6: "1.5rem",
8: "2rem",
10: "2.5rem",
12: "3rem",
},
typography: {
body: "var(--font-geist-sans), sans-serif",
display: "var(--font-manrope), sans-serif",
mono: "var(--font-geist-mono), monospace",
textSm: "0.875rem",
textBase: "1rem",
textLg: "1.125rem",
textXl: "1.25rem",
leadingSm: "1.25rem",
leadingBase: "1.5rem",
leadingLg: "1.75rem",
weightMedium: "500",
weightSemibold: "600",
weightBold: "700",
},
shadows: {
sm: "0 1px 2px 0 hsl(222.2 84% 4.9% / 0.05)",
md: "0 4px 6px -1px hsl(222.2 84% 4.9% / 0.1)",
lg: "0 10px 15px -3px hsl(222.2 84% 4.9% / 0.1)",
},
tokens: {
"sidebar-background": "222 40% 12%",
"sidebar-foreground": "210 40% 96%",
},
},
} satisfies ThemeMap;Use themeStrategy="extend" to keep the package themes and append your own entries:
import {
ThemeProvider,
ThemeScript,
ThemeStyles,
} from "@baramjk/design-system";
import { appThemes } from "./app-theme";
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="en">
<body>
<ThemeStyles themes={appThemes} themeStrategy="extend" />
<ThemeScript
themes={appThemes}
themeStrategy="extend"
defaultTheme="neutral"
/>
<ThemeProvider
themes={appThemes}
themeStrategy="extend"
defaultTheme="neutral"
>
{children}
</ThemeProvider>
</body>
</html>
);
}Use themeStrategy="replace" when you want the consumer app to provide the full registry and omit the built-in package themes:
<ThemeStyles themes={appThemes} themeStrategy="replace" />
<ThemeScript
themes={appThemes}
themeStrategy="replace"
defaultTheme="acme"
/>
<ThemeProvider
themes={appThemes}
themeStrategy="replace"
defaultTheme="acme"
>
{children}
</ThemeProvider>Any extra tokens you add become CSS custom properties alongside the built-in theme variables. That makes it easy to map app-specific values into Tailwind:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
sidebar: "hsl(var(--sidebar-background))",
sidebarForeground: "hsl(var(--sidebar-foreground))",
},
},
},
};Local consumer verification
Run the packed-consumer smoke test from this repo:
npm run verify:consumerThat command builds the package, creates an npm pack tarball, installs that tarball into the smoke-tests/next-consumer fixture, and runs a production next build there from a temporary directory outside the repo.
