@loke/design-system
Version:
A design system with individually importable components
168 lines (155 loc) • 7.98 kB
JavaScript
var AGENTS_default=`<h1>lib</h1>
<!-- Parent: ../CLAUDE.md -->
<!-- Generated: 2026-04-07 | Updated: 2026-04-07 -->
<h2>Purpose</h2>
<p>Utility functions for the design system: className merging, macro helpers, and responsive component patterns. These are shared, low-level utilities used throughout the design system and consuming applications.</p>
<h2>For AI Agents</h2>
<h3>Organization</h3>
<p>Utilities are organized by purpose in subdirectories:</p>
<pre><code>lib/
├── cn/ (className merging)
├── macros/ (size/color variant generators)
├── responsive/ (responsive component helpers)
└── AGENTS.md
</code></pre>
<p>Each utility exports both functions and types.</p>
<h2>Existing Utilities</h2>
<h3>cn (className merge)</h3>
<p><strong>Location</strong>: <code>cn/</code></p>
<p><strong>Purpose</strong>: Merge class names with Tailwind CSS conflict resolution.</p>
<p><strong>Usage</strong>:</p>
<pre><code class="language-ts">import { cn } from "@loke/design-system/cn";
// Merge multiple class strings
const classes = cn("px-4 py-2", "px-6", "text-lg"); // → "px-6 py-2 text-lg"
// Conditional classes
const buttonClasses = cn(
"px-4 py-2",
isDisabled && "opacity-50",
isLarge && "text-lg"
);
</code></pre>
<p><strong>Implementation</strong>:</p>
<ul>
<li>Uses <code>clsx()</code> to combine classes</li>
<li>Uses <code>twMerge()</code> to resolve Tailwind conflicts (e.g., <code>px-4 px-6</code> → <code>px-6</code>)</li>
<li>Accepts <code>ClassValue[]</code> (strings, objects, arrays, null, undefined)</li>
</ul>
<p><strong>Types</strong>:</p>
<pre><code class="language-ts">function cn(...inputs: ClassValue[]): string;
</code></pre>
<h3>macros (Size & Color Variants)</h3>
<p><strong>Location</strong>: <code>macros/</code></p>
<p><strong>Purpose</strong>: Generate type-safe size and color variant mappings for design macros.</p>
<p><strong>Exports</strong>:</p>
<pre><code class="language-ts">// Functions
getSizeVariants<T>(type: T): { [K in Size]: \`\${T}-\${K}\` }
getNegativeSizeVariants<T>(type: T): { [K in \`-\${Size}\`]: \`-\${T}-\${K}\` }
getSizeFractionVariants<T>(type: T): { [K in SizeFraction]: \`\${T}-\${K}\` }
getSizeSpecialVariants<T>(type: T): { [K in SizeSpecial]: \`\${T}-\${K}\` }
getDimensionVariants<T>(type: T): { [K in Size | SizeFraction | SizeSpecial]: ... }
getColorVariants<T>(type: T): { [K in Color]: \`\${T}-\${K}\` }
// Types
type Size = keyof typeof sizeMap | (typeof numericSizes)[number]
type Color = BaseColor | \`neutral-\${ColorShade}\`
type ColorShade = "50" | "100" | ... | "950"
type SizeFraction = "1/2" | "1/3" | ... | "11/12"
type SizeSpecial = "auto" | "full" | "screen" | ... | "5xl"
</code></pre>
<p><strong>Usage</strong> (in component variants):</p>
<pre><code class="language-ts">import { getDimensionVariants, getColorVariants } from "@loke/design-system/macros";
import { cva } from "class-variance-authority";
const dimensions = getDimensionVariants("gap");
const colors = getColorVariants("bg");
const buttonVariants = cva("button", {
variants: {
gap: dimensions, // { "1/2": "gap-1/2", "8": "gap-8", ... }
background: colors, // { "primary": "bg-primary", "neutral-500": "bg-zinc-500", ... }
},
});
</code></pre>
<p><strong>Size Map</strong>:</p>
<p>Supported named sizes: <code>xxsmall</code> (1), <code>xsmall</code> (2), <code>small</code> (3), <code>medium</code> (5), <code>large</code> (8), <code>xlarge</code> (12), <code>xxlarge</code> (24), and numeric sizes 0–32.</p>
<p><strong>Base Colors</strong>:</p>
<p><code>primary</code>, <code>secondary</code>, <code>accent</code>, <code>background</code>, <code>foreground</code>, <code>destructive</code>, <code>card</code>, <code>white</code>, <code>sidebar</code>, <code>sidebar-accent</code></p>
<p><strong>Neutral Shades</strong>:</p>
<p><code>neutral-50</code> through <code>neutral-950</code> (mapped to Tailwind's <code>zinc-*</code> classes)</p>
<h3>responsive (Responsive Components)</h3>
<p><strong>Location</strong>: <code>responsive/</code></p>
<p><strong>Purpose</strong>: Create responsive components that change variant props across breakpoints.</p>
<p><strong>Exports</strong>:</p>
<pre><code class="language-ts">// Functions
createResponsiveVariants<T>(
variants: ReturnType<typeof cva>,
props: ResponsiveProps<T>,
): string
createResponsiveComponent<T>(variants: T): {
createResponsive: (props: ResponsiveProps<ComponentVariants>) => string
}
// Types
type ResponsiveValue<T> = T | [T, T] | [T, T, T] | [T, T, T, T]
type ResponsiveProps<T> = { [K in keyof T]: ResponsiveValue<T[K]> }
</code></pre>
<p><strong>Usage</strong>:</p>
<p>Define variant props as single values or arrays of values (one per breakpoint):</p>
<pre><code class="language-ts">import { createResponsiveComponent } from "@loke/design-system/responsive";
import { buttonVariants } from "./button-variants";
const { createResponsive } = createResponsiveComponent(buttonVariants);
// Single value: applies to all breakpoints
const classes1 = createResponsive({ size: "lg" });
// → "text-lg"
// Array: applies per breakpoint (mobile, sm:, md:, lg:)
const classes2 = createResponsive({ size: ["sm", "md", "lg", "xl"] });
// → "text-sm sm:text-md md:text-lg lg:text-xl"
// Mixed: single for some, array for others
const classes3 = createResponsive({
size: ["sm", "md", "lg"],
variant: "primary", // applies to all
});
</code></pre>
<p><strong>Breakpoints</strong>:</p>
<p>Four breakpoints: base (mobile), <code>sm:</code> (640px), <code>md:</code> (768px), <code>lg:</code> (1024px)</p>
<p><strong>Class Deduplication</strong>:</p>
<p>The function automatically removes redundant responsive classes:</p>
<ul>
<li>If <code>text-lg</code> exists, <code>sm:text-lg</code> is removed</li>
<li>If <code>md:text-lg</code> exists, <code>sm:text-lg</code> is removed</li>
<li>Prevents bloated class strings</li>
</ul>
<h2>Creating New Utilities</h2>
<ol>
<li>Create a subdirectory: <code>lib/utility-name/</code></li>
<li>Implement in <code>utility-name.ts</code> (or multiple files)</li>
<li>Export from <code>index.ts</code></li>
<li>Add JSDoc comments and types</li>
<li>Update this AGENTS.md with usage examples</li>
</ol>
<p>Example structure:</p>
<pre><code class="language-ts">// lib/my-util/my-util.ts
export function myUtil(input: string): string {
// Implementation
}
// lib/my-util/index.ts
export { myUtil } from "./my-util";
export type { MyUtilOptions } from "./my-util";
</code></pre>
<h2>MANUAL</h2>
<p><strong>Design System Lib Patterns</strong></p>
<ul>
<li>Utilities are low-level, reusable functions</li>
<li>Prefer pure functions (no side effects)</li>
<li>All utilities are exported from design system subpaths (e.g., <code>@loke/design-system/cn</code>)</li>
<li>Export entries for utilities are defined in <code>packages/design-system/package.json</code> <code>exports</code></li>
<li>Add comprehensive JSDoc comments and type definitions</li>
</ul>
<p><strong>When to Add a Utility</strong></p>
<ul>
<li>If used in 2+ design system components</li>
<li>If used in 2+ consuming applications</li>
<li>If it's a general-purpose helper</li>
</ul>
<p><strong>When NOT to Add</strong></p>
<ul>
<li>One-off component-specific logic (keep in the component)</li>
<li>Complex business logic (belongs in the app, not design system)</li>
</ul>
`;export{AGENTS_default as default};