# Davis Design System > Davis is an accessibility-first design system built by LibreTexts for education technology. It provides a framework-agnostic core (design tokens + CSS) with React 18+ and Vue 3 component libraries on top of Tailwind CSS v4, Headless UI, and tailwind-variants. All 48+ components meet WCAG 2.2 AA contrast and interaction requirements out of the box. --- ## Choosing a Package ``` Do you need pre-built components? - No -> npm install @libretexts/davis-core (design tokens, CSS variables, Tailwind preset only) - Yes -> Which framework? - React -> npm install @libretexts/davis-react (includes davis-core automatically) - Vue -> npm install @libretexts/davis-vue (includes davis-core automatically — in active development) - Other -> npm install @libretexts/davis-core (build your own components using the design tokens) ``` Installing `@libretexts/davis-react` or `@libretexts/davis-vue` automatically installs `@libretexts/davis-core` as a dependency. You do not need to install core separately. --- ## Quick Start ### React **1. Install** ```bash npm install @libretexts/davis-react ``` Peer dependencies (install alongside Davis): ```bash npm install @headlessui/react react react-dom tailwindcss ``` **2. Import styles** In your app's entry point or root layout: ```ts import "@libretexts/davis-react/styles.css"; ``` **3. Wrap with DavisProvider** ```tsx import { DavisProvider } from "@libretexts/davis-react"; export default function RootLayout({ children }) { return ( {children} ); } ``` **4. Use components** ```tsx import { Button, Input, Card } from "@libretexts/davis-react"; export default function Page() { return ( ); } ``` ### Vue **1. Install** ```bash npm install @libretexts/davis-vue ``` Peer dependencies: ```bash npm install @headlessui/vue vue tailwindcss ``` **2. Import styles and use components** ```ts // main.ts import { createApp } from "vue"; import App from "./App.vue"; import "@libretexts/davis-vue/styles.css"; createApp(App).mount("#app"); ``` ```vue ``` ### Tokens Only (Svelte, Angular, vanilla, etc.) ```bash npm install @libretexts/davis-core ``` ```css /* your global stylesheet */ @import "@libretexts/davis-core/theme.css"; /* Tailwind @theme block */ @import "@libretexts/davis-core/base.v4.css"; /* global base styles */ ``` Then reference CSS custom properties in your own styles: ```css .my-button { background: var(--color-primary-500); color: var(--color-text-white); border-radius: var(--radius-md); } ``` --- ## CSS Setup Davis ships one primary stylesheet per component package. Import **one** of these at your app's entry point -- do not import multiple: | Import | When to use | |--------|-------------| | `@libretexts/davis-react/styles.css` | Standard: new React app built on Davis | | `@libretexts/davis-core/base.v4.css` | Tailwind v4 projects using tokens only | | `@libretexts/davis-core/base.css` | Tailwind v3 / CSS-in-JS projects | | `@libretexts/davis-core/base.scoped.css` | Embedded widget: styles scoped under `.davis` | `styles.css` contains everything: the Tailwind `@theme` block (CSS variables), base reset, typography, and component safelist. It is the recommended import for React apps. --- ## DavisProvider `DavisProvider` is a lightweight wrapper that renders `
` and sets a React context. It is required for standalone/scoped mode and optional (but recommended) in standard mode. ```tsx import { DavisProvider } from "@libretexts/davis-react"; // Props type DavisProviderProps = { children: ReactNode; className?: string; // forwarded to the wrapper div }; ``` **What it does:** - Renders `
` which activates scoped CSS custom properties and Tailwind utilities. - Provides `DavisContext` (`{ standalone: true }`) to all descendant components. **When you need it:** - Always in standalone/existing-project mode (the `.davis` class is the style boundary). - Recommended in new projects for consistency and in case you later adopt standalone mode. **Using `className`:** ```tsx {/* content */} ``` --- ## Standalone Mode (Existing Projects) If you are adding Davis components to an app that already has its own CSS, use standalone mode to prevent Davis's global styles (font family, heading scale, focus rings, Preflight resets) from affecting your existing UI. **How it works:** all Davis styles are scoped under `.davis`. `DavisProvider` creates that boundary by rendering `
`. Styles do not leak outside it. **Setup:** ```bash npm install @libretexts/davis-react @headlessui/react tailwindcss ``` ```ts import "@libretexts/davis-react/styles.css"; ``` **Page-section pattern** — wrap only the Davis-powered parts: ```tsx import { DavisProvider, Card, Input, Button } from "@libretexts/davis-react"; function Dashboard() { return (
{/* Your existing header — untouched */}

Dashboard

{/* Davis-powered section */}
); } ``` **Full-app wrapper** — for gradual migration: ```tsx function App() { return ( ); } ``` Multiple `DavisProvider` instances on the same page are supported. Each is an independent `.davis` scope. There is no performance penalty - `DavisProvider` is a thin `
` + React context. **Headless UI portals:** `Dialog`, `Menu`, `Popover`, and `Drawer` use Headless UI portals. Ensure `DavisProvider` is high enough in the tree to contain the trigger element -- Headless UI resolves the portal context from the nearest parent. --- ## Component API Patterns ### Dot notation for compound components Composite components expose sub-components via dot notation in React: ```tsx setOpen(false)}> Confirm deletion

This action cannot be undone.

``` In Vue, sub-components are imported individually (no dot notation): ```vue ``` Compound components: `Dialog`, `Drawer`, `Card`, `Tabs`, `Accordion`, `Menu`, `Breadcrumb`, `Table`. ### Polymorphic `as` prop Most interactive components accept an `as` prop to render as a different HTML element or router component while keeping Davis styling: ```tsx {/* Render a button as a native anchor */} {/* Render as a Next.js Link */} import NextLink from "next/link"; ``` ### `className` override Every component forwards `className` to its root element. Use it to apply layout, spacing, or one-off overrides: ```tsx ... ``` ### Form input error state All form inputs accept `error` (boolean) and `errorMessage` (string) props: ```tsx ``` ### Controlled vs uncontrolled form components Most inputs work uncontrolled (spread `register()` from react-hook-form directly): - **Uncontrolled** (use `register()`): `Input`, `Textarea`, `Select`, `Checkbox`, `Switch` - **Controlled** (require `Controller`): `Combobox`, `NumberInput`, `RadioGroup` --- ## Forms with react-hook-form Install react-hook-form separately — it is not bundled with Davis: ```bash npm install react-hook-form ``` ### Uncontrolled inputs (spread `register`) ```tsx import { useForm } from "react-hook-form"; import { Input, Select, Textarea, Checkbox, Switch, Button } from "@libretexts/davis-react"; type FormValues = { name: string; email: string; role: string; }; export default function ProfileForm() { const { register, handleSubmit, formState: { errors } } = useForm(); return (
); } ``` ### FormSection for long forms ```tsx import { FormSection, Stack, Input, Textarea, Button } from "@libretexts/davis-react";