# 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 (
{count} results
; } ``` --- ## WCAG 2.2 Compliance Reference Key WCAG 2.2 AA criteria and how Davis addresses them: | Criterion | Level | How Davis addresses it | |-----------|-------|------------------------| | 1.4.3 Contrast (Minimum) | AA | Color tokens verified at 4.5:1 / 3:1 | | 1.4.11 Non-text Contrast | AA | Focus indicators and UI components meet 3:1 | | 2.1.1 Keyboard | A | All components support full keyboard navigation | | 2.4.1 Bypass Blocks | A | `SkipLink` component | | 2.4.7 Focus Visible | AA | `:focus-visible` with 2px ring + offset | | 2.4.11 Focus Not Obscured | AA | `outline-offset` keeps focus rings visible | | 2.5.8 Target Size (Minimum) | AA | All interactive components meet 24×24px minimum | | 4.1.3 Status Messages | AA | `LiveAnnouncerProvider` for dynamic announcements | Safe color pairings on white backgrounds: - Body text: `text-neutral-900` (14.5:1) or `text-neutral-700` (9.5:1) - Secondary text: `text-neutral-500` (4.6:1 — minimum passing) - Avoid: `text-neutral-400` on white (fails AA for normal text) - On colored backgrounds (`bg-primary-500` and darker): use `text-white` - On light tints (`bg-primary-50` to `bg-primary-100`): use `text-primary-700` or darker --- ## Building Custom Components Alongside Davis When you need a component Davis does not provide, use the same conventions to stay visually consistent. **1. Use `tailwind-variants` for style logic:** ```tsx import { tv } from "tailwind-variants"; const chip = tv({ base: [ "inline-flex items-center gap-1.5 rounded-full px-3 py-1", "text-xs font-medium border transition-colors duration-150", "focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2", ].join(" "), variants: { selected: { true: "bg-primary text-white border-primary", false: "bg-white text-neutral-700 border-neutral-300 hover:border-primary hover:text-primary", }, }, defaultVariants: { selected: false as const }, }); ``` **2. Accept and forward `className`:** ```tsx import clsx from "clsx"; export function Chip({ children, selected = false, onClick, className }: ChipProps) { return ( ); } ``` **3. Reference Davis CSS custom properties for tokens not exposed as Tailwind utilities:** ```css .my-component { --ring-color: var(--color-primary-500); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); transition-duration: var(--davis-motion-duration-default); /* 200ms */ } ``` Available token categories in `@libretexts/davis-core/base.css`: - `--color-{palette}-{shade}` (e.g., `--color-primary-500`) - `--color-surface`, `--color-surface-muted`, `--color-surface-hover`, `--color-surface-active` - `--color-text`, `--color-text-neutral`, `--color-text-white` - `--radius-sm/md/lg/xl/2xl/full` - `--shadow-sm/md/lg/xl/2xl` - `--davis-target-size-minimum` (24px) / `--davis-target-size-comfortable` (44px) - `--davis-motion-duration-fast` (150ms) / `--davis-motion-duration-default` (200ms) / `--davis-motion-duration-slow` (300ms) --- ## TypeScript Davis exports full TypeScript types. Import variant types directly for use in your own components and prop tables: ```tsx import type { ButtonVariant, // 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'warning' | 'ghost' | 'outline' BadgeVariant, AlertVariant, InputSize, // 'sm' | 'md' | 'lg' } from "@libretexts/davis-react"; ``` All component props are exported as named types (e.g., `ButtonProps`, `InputProps`, `DialogProps`). ### Next.js / SSR All Davis React components are marked `"use client"` at the source level. When consumed by Next.js App Router, they work in both Server and Client components - the `"use client"` boundary is established inside the Davis package so you do not need to add it in your own code. --- ## Design Tokens All tokens are defined in `packages/core/src/tokens.ts` and exported as CSS custom properties via the generated CSS files. ### Typography Font: **Atkinson Hyperlegible** - designed for low-vision readers; falls back to system-ui. Scale follows a Major Third ratio (1.250) with a 16px base: | Token | rem | px | Use case | |-------|--------|------|------------------------| | xs | 0.640 | 10.2 | Captions | | sm | 0.800 | 12.8 | Labels, helper text | | base | 1.000 | 16 | Body, buttons | | lg | 1.250 | 20 | Lead / intro text | | xl | 1.563 | 25 | h4 | | 2xl | 1.953 | 31.3 | h3 | | 3xl | 2.441 | 39.1 | h2 | | 4xl | 3.052 | 48.8 | h1 | ### Color Palette Seven semantic colors, each with a full 50–950 shade range. All 500-level shades meet WCAG AA contrast against white. | Token | 500 value | Role | |------------|-----------|---------------------------------------| | primary | #127BC4 | Primary actions, links, focus rings | | secondary | #0F67A6 | Secondary actions, accents | | tertiary | #4076a4 | Decorative / supporting elements | | success | #207537 | Confirmations, positive feedback | | warning | #BB5C21 | Caution states | | danger | #DC3838 | Errors, destructive actions | | neutral | #18181B | Text, borders, backgrounds | Interactive state convention: hover → shade 600, active → shade 700. ### Semantic Surface & Text Tokens | Token | Value | Use | |------------------|---------|----------------------------------| | surface | #FFFFFF | Default page background | | surface-muted | #F9FAFB | Subtle section differentiation | | surface-subtle | #F4F4F5 | Sidebars, footers | | surface-hover | #F4F4F5 | Hover state backgrounds | | surface-active | #E4E4E7 | Pressed / active state | | text | #162032 | Primary text (WCAG AAA) | | text-neutral | #71717A | Secondary / muted text | | text-white | #FFFFFF | Text on colored surfaces | ### Spacing 4px base grid. Every spacing value is a multiple of 4px (matches Tailwind defaults). ### Border Radius `sm` (0.125rem), `md` / DEFAULT (0.375rem), `lg` (0.5rem), `xl` (0.75rem), `2xl` (1rem), `full` (9999px). ### Shadows (Elevation) Five levels: none (level 0, flat), sm/DEFAULT (level 1, cards), md (level 2, hovered cards), lg (level 3, dialogs/popovers), xl/2xl (level 4, high-emphasis overlays). --- ## Component Catalog All 48 components are available in both React (`@libretexts/davis-react`) and Vue (`@libretexts/davis-vue`). ### Forms `Input`, `Select`, `Textarea`, `Checkbox`, `Radio` / `RadioGroup`, `Switch`, `Combobox`, `FormSection`, `InputGroup`, `NumberInput` ### Display `Button`, `IconButton`, `Badge`, `Card` (with `Card.Header`, `Card.Body`, `Card.Footer`, `Card.Image`), `Avatar` / `AvatarGroup`, `Heading`, `Text`, `Link`, `StatCard`, `Table` (with `Table.Head`, `Table.Body`, `Table.Row`, `Table.Cell`, `Table.HeaderCell`, `Table.Caption`), `Accordion` (with `Accordion.Item`, `Accordion.Trigger`, `Accordion.Panel`) ### Navigation `Breadcrumb` (with `Breadcrumb.Item`), `Menu` (with `Menu.Button`, `Menu.Items`, `Menu.Item`, `Menu.Divider`, `Menu.Label`), `Pagination`, `Stepper`, `Tabs` (with `Tabs.List`, `Tabs.Tab`, `Tabs.Panels`, `Tabs.Panel`) ### Layout `Stack`, `Grid`, `Container`, `Divider` ### Feedback `Alert`, `Notification` / `Toast` / `ToastContainer`, `Progress`, `Skeleton`, `Spinner`, `EmptyState` ### Overlays `Dialog` (with `Dialog.Header`, `Dialog.Title`, `Dialog.Description`, `Dialog.Footer`, `Dialog.Close`), `Drawer` (with `Drawer.Header`, `Drawer.Title`, `Drawer.Body`, `Drawer.Footer`, `Drawer.Close`), `Popover` (with `Popover.Button`, `Popover.Panel`) ### Accessibility Utilities `SkipLink`, `VisuallyHidden`, `LiveAnnouncerProvider` / `useAnnounce` ### Providers & Context (React) `DavisProvider` / `DavisContext` / `useDavisContext`, `NotificationsProvider` / `NotificationContext` / `useNotifications` --- ## Adding a New Component (Contributors) 1. Define variants in `packages/core/src/variants.ts` using `tv()`. 2. Create `packages/react/src/components/component-name.tsx` (kebab-case filename). 3. Create `packages/react/src/components/component-name.stories.tsx` for Storybook. 4. Export from `packages/react/src/index.ts`. 5. Mirror in `packages/vue/src/components/ComponentName.vue` (PascalCase filename). 6. Export from `packages/vue/src/index.ts`. --- ## Key Conventions (Contributors) - **No manual CSS edits** — all CSS is generated from `tokens.ts`. Run `generate:configs` after token changes. - **tailwind-variants** (`tv()`) is used for all component styles; compound variants handle state combinations. - React components use `forwardRef`, support a polymorphic `as` prop, and preserve `"use client"` directives. - Vue components use `