Skip to content

Repository files navigation

LibreTexts Logo

Davis Design System

An accessibility-first, opinionated design system with full TypeScript support for React and Vue, built on top of HeadlessUI and Tailwind CSS.

Architecture

This is a monorepo containing four packages:

📦 Packages

@libretexts/davis-core

Framework-agnostic package containing:

  • Shared variant definitions (using tailwind-variants)
  • Utility functions (e.g., cn for className merging)
  • Shared TypeScript types
  • Design tokens and constants

@libretexts/davis-react

React implementation using @headlessui/react

@libretexts/davis-vue

Vue 3 implementation using @headlessui/vue

@libretexts/davis-docs

Documentation site built with Next.js, showcasing usage guides and Storybook examples.

Workspace Structure

davis/
├── packages/
│ ├── core/ # Shared variants and utilities
│ ├── react/ # React components
│ ├── vue/ # Vue components
│ └── docs/ # Documentation site
│
├── package.json # Root workspace config
└── tsconfig.base.json # Shared TypeScript config

Design Tokens & Theming

🎨 Single Source of Truth

All Davis design tokens (colors, typography, spacing, shadows, etc.) are defined once in packages/core/src/tokens.ts and automatically generate all configuration files.

tokens.ts (EDIT THIS)
↓ npm run generate:configs
↓
├─→ theme.css (Tailwind v4 theme)
├─→ base.css (Global base styles)
└─→ base.scoped.css (Scoped base styles)

📁 Understanding the Files

FilePurposeProvidesScope
theme.cssTailwind v4 themeUtility classes (bg-primary, etc.)N/A
base.cssGlobal base stylesCSS vars, resets, heading styles, focusGlobal (:root)
base.scoped.cssScoped base stylesCSS vars, resets, heading styles, focusScoped (.davis)

⚠️All CSS files are auto-generated from tokens.ts — Do not edit manually!

What Each File Provides

theme.cssbase.cssbase.scoped.css
Tailwind utilities (bg-primary, text-sm)
CSS custom properties (var(--davis-color-primary))
Heading styles (h1, h2, etc.)✅ Global✅ Scoped to .davis
Typography defaults (html font)✅ Global✅ Scoped to .davis
Focus management✅ Global✅ Scoped to .davis
Reduced motion✅ Global✅ Scoped to .davis

Detailed Descriptions

theme.css - Tailwind v4 Theme
  • For: Tailwind CSS v4 users
  • Purpose: Configures Tailwind v4 utility classes via @theme directive
  • Provides:bg-primary, text-sm, shadow-md, rounded-lg, etc.
  • Does NOT include: Base styles, resets, or heading styles
  • Used by:@libretexts/davis-docs
  • Import:@import '@libretexts/davis-core/theme.css';
base.css - Global Base Styles
  • For: Full integration scenarios
  • Purpose: Global CSS resets and base styles
  • Provides:
    • CSS custom properties at :root (e.g., var(--davis-color-primary))
    • Global typography defaults on html
    • Heading hierarchy styles (h1-h6)
    • Focus ring management
    • Reduced motion support
  • Scope: Global (affects entire page)
  • Import:@import '@libretexts/davis-core/base.css';
base.scoped.css - Scoped Base Styles
  • For: Embedded/standalone scenarios
  • Purpose: Same as base.css but scoped under .davis selector
  • Provides: All of base.css functionality without global scope
  • Prevents: Style leakage when Davis is embedded in other applications or you're perfoming a gradual migration to Davis
  • Use case: Widgets, iframes, or when Davis shares the page with other design systems
  • Requires: Wrapping Davis components in <div class="davis">...</div>
  • Import:@import '@libretexts/davis-core/base.scoped.css';

🔧 For Contributors

Modifying Design Tokens

  1. Editpackages/core/src/tokens.ts
  2. Regenerate configs:
    cd packages/core
    npm run generate:configs
  3. Verify changes in all generated files
  4. Commit both tokens.ts and generated files

See packages/core/scripts/README.md for detailed architecture documentation.

📦 For Consuming Applications

Scenario 1: Full Integration (React)

/* Your app's CSS entry file (e.g. globals.css) */@import'tailwindcss';
@import'@libretexts/davis-react/styles.css';
@plugin'@tailwindcss/typography'; /* Optional: for Markdown/dynamic HTML content */
// Now use Tailwind utilities powered by Davis tokens<divclassName="bg-primary text-white shadow-lg rounded-lg"><h1>Using Davis theme!</h1></div>

Scenario 2: Tokens Only (no React components)

/* Your app's CSS entry file */@import'tailwindcss';
@import'@libretexts/davis-core/theme.css'; /* ← Tailwind utilities */@import'@libretexts/davis-core/base.v4.css'; /* ← Base styles */

Scenario 3: Embedded/Widget Mode

<!-- Host app with its own styles --><divclass="host-app"><h1>Host App Heading</h1><!-- Davis component isolated in .davis scope --><divclass="davis"><h1>Davis Heading</h1><!-- Davis styles only apply here --></div></div>
/* Widget CSS */@import'@libretexts/davis-core/base.scoped.css';
/* All Davis styles scoped under .davis */

Scenario 4: CSS Custom Properties Only

If you just need access to design tokens via CSS custom properties:

@import'@libretexts/davis-core/base.css';
/* or */@import'@libretexts/davis-core/base.scoped.css';
/* Now use CSS variables */
.my-component {
color:var(--davis-color-primary);
font-family:var(--davis-font-family);
border-radius:var(--davis-radius);
}

Scenario 5: Gradual Migration

Use scoped mode to run both systems side-by-side during the transition.

Step 1: Install Davis
npm install @libretexts/davis-core @libretexts/davis-react
Step 2: Import Scoped Styles
/* app.css or global styles */@import'@libretexts/davis-core/base.scoped.css';
/* Keep your existing design system imports */@import'@mantine/core/styles.css'; /* Example: Mantine */
Step 3: Wrap New Davis Components
// App.tsximport{MantineProvider}from'@mantine/core';// Existingimport{Button}from'@libretexts/davis-react';// New Davis componentexportfunctionApp(){return(<MantineProvider><divclassName="app">{/* Existing Mantine components work as-is */}<Header><MantineButton>Old Button</MantineButton></Header>{/* New Davis components wrapped in .davis scope */}<mainclassName="davis"><Buttonvariant="primary">New Davis Button</Button><h1>This heading uses Davis styles</h1></main>{/* Mix both as needed during migration */}<aside><MantineCard>Still using Mantine here</MantineCard></aside></div></MantineProvider>);}
Step 4: Migrate Page-by-Page or Component-by-Component

Option A: Migrate entire pages

// Old page (still using Mantine)exportfunctionSettingsPage(){return(<div><MantineButton>Save</MantineButton></div>);}// New page (fully Davis)exportfunctionDashboardPage(){return(<divclassName="davis"><Button>Save</Button><Card>Dashboard content</Card></div>);}

Option B: Migrate individual components

// Wrapper component for gradual migrationexportfunctionNavigationBar(){return(<nav>{/* Old Mantine menu */}<MantineMenu>...</MantineMenu>{/* New Davis user menu */}<divclassName="davis"><Menu><MenuButton>Account</MenuButton><MenuItems>...</MenuItems></Menu></div></nav>);}
Step 5: Eventually Switch to Full Integration

Once migration is complete, switch from scoped to global mode:

  1. Remove the old design system:

    npm uninstall @mantine/core @mantine/hooks
  2. Replace scoped imports with full integration:

    /* Before: Scoped mode */@import'@libretexts/davis-core/base.scoped.css';
    /* After: Full integration (React) */@import'tailwindcss';
    @import'@libretexts/davis-react/styles.css';
  3. Remove.davis wrapper divs:

    // Before: Scoped<divclassName="davis"><Button>Click me</Button></div>// After: Global<Button>Clickme</Button>
Migration Checklist
  • Install Davis packages
  • Import base.scoped.css in global styles
  • Create migration plan (page-by-page or component-by-component)
  • Wrap new Davis components in .davis containers
  • Test for style conflicts between systems
  • Gradually replace old components with Davis equivalents
  • Monitor bundle size (remove old dependencies as you go)
  • Switch to full integration CSS when migration is complete
  • Remove .davis wrapper divs
  • Uninstall old design system packages
Tips for Smooth Migration

Avoid Conflicts:

  • Use .davis scope consistently for all Davis components
  • Don't mix Davis and old design system components in the same container without scoping
  • Test heading styles carefully (both systems style h1-h6)

Performance:

  • Remove old design system CSS imports from pages/components as you migrate them
  • Don't wait until the end to remove dependencies—clean up incrementally

🎯 Quick Reference

Your SetupImport
React app (Next.js, Remix, etc.)@libretexts/davis-react/styles.css
Tokens only (any framework)@libretexts/davis-core/theme.css + @libretexts/davis-core/base.v4.css
Embedded widget / scoped mode@libretexts/davis-core/base.scoped.css
CSS custom properties only@libretexts/davis-core/base.css or base.scoped.css
Migrating from another design systembase.scoped.css (during migration) → @libretexts/davis-react/styles.css (when complete)

Development

Prerequisites

  • Node.js 20+
  • npm 9+ (for workspace protocol support)

Installation

npm install

Building

# Build all packages
npm run build
# Build in watch mode
npm run dev
# Type check all packages
npm run typecheck

Package-specific commands

# Build only React package
npm run build -w @libretexts/davis-react
# Build only Vue package
npm run build -w @libretexts/davis-vue
# Build only core package
npm run build -w @libretexts/davis-core
# Build only docs
npm run build -w @libretexts/davis-docs

⚠️ Common Issues

"bg-primary is not defined" or colors not working

Problem: Tailwind utilities like bg-primary, text-secondary-500 are not being imported.

Solution: Import @libretexts/davis-react/styles.css (or @libretexts/davis-core/theme.css for tokens-only) in your CSS entry file:

@import'tailwindcss';
@import'@libretexts/davis-react/styles.css';

Headings look wrong or unstyled

Problem:<h1>, <h2>, etc. don't have Davis typography.

Solution: Import base.css (or base.scoped.css for scoped mode)

@import'@libretexts/davis-core/base.css';

Davis styles leaking into host application

Problem: When embedding Davis components, styles affect the host app.

Solution: Use base.scoped.css instead of base.css and wrap Davis components in .davis container

<divclass="davis"><!-- Davis components here --></div>

Design Principles

  1. Accessibility First: Built on HeadlessUI for rock-solid a11y foundations
  2. Opinionated Defaults: A well-curated set of components and variants to reduce decision fatigue and promote consistency
  3. Type-safe: Full TypeScript support across all packages
  4. Framework Agnostic Core: Share variant definitions between React and Vue
  5. Tree-shakeable: Optimized bundle size with ESM and proper exports

Adding New Components

1. Define variants in @libretexts/davis-core

// packages/core/src/variants/my-component.tsimport{tv,typeVariantProps}from"tailwind-variants";exportconstmyComponentVariants=tv({base: "...",variants: {// variant classes},defaultVariants: {// defaults},});exporttypeMyComponentVariantProps=VariantProps<typeofmyComponentVariants>;

2. Export from core

// packages/core/src/index.tsexport{myComponentVariants}from"./variants/my-component";exporttype{MyComponentVariantProps}from"./variants/my-component";

3. Implement in React

// packages/react/src/components/MyComponent.tsximport{cn,myComponentVariants,typeMyComponentVariantProps,}from"@libretexts/davis-core";exportinterfaceMyComponentPropsextendsMyComponentVariantProps{// component-specific props}exportconstMyComponent=({
variant,
size,
className,
...props}: MyComponentProps)=>{return(<divclassName={cn(myComponentVariants({ variant, size }),className)}>{/* implementation */}</div>);};

4. Implement in Vue

<!-- packages/vue/src/components/MyComponent.vue -->
<script setup lang="ts">import {cn,myComponentVariants,typeMyComponentVariantProps,} from"@libretexts/davis-core";interfaceMyComponentPropsextendsMyComponentVariantProps {// component-specific props}const props =defineProps<MyComponentProps>();</script>
<template>
<div:class=" cn( myComponentVariants({ variant: props.variant, size: props.size }), props.className, )"
>
<!-- implementation -->
</div>
</template>

License

MIT © LibreTexts, Inc.

About

An accessibility-first UI component library for React and Vue, built on top of HeadlessUI with opinionated styling using Tailwind CSS.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages