# @xingxingmofashu/ui — Full documentation > React components with a CSS-only Liquid Glass visual style, built with Tailwind CSS 4 and Tailwind Variants. This file contains every English documentation page. Use the URL line above each section to cite the canonical page. ## Introduction URL: https://xingxingmofashu.github.io/ui/docs/en/get-started/introduction @xingxingmofashu/ui is a collection of typed React components with a Liquid Glass visual style for React 19 and Tailwind CSS 4. @xingxingmofashu/ui is at 0.2.x. APIs may change before 1.0; pin a version and review the [release notes](https://github.com/xingxingmofashu/ui/releases) when upgrading. ## What is @xingxingmofashu/ui? `@xingxingmofashu/ui` is a React component library for building interfaces with a CSS-only Liquid Glass visual style. It ships twenty-five components across elements, forms, overlays, and feedback, and works in any React 19 application with Tailwind CSS 4. Glass surfaces, rim highlights, inner shadows, and pressed states are drawn entirely with CSS. Interactive behavior is built into the components, while Tailwind Variants keeps the styling typed and composable. If you are building a React project with Tailwind CSS and want a distinctive monochrome Liquid Glass aesthetic, `@xingxingmofashu/ui` is a good default choice. It provides high-level components such as Button, Card, Dialog, Drawer, and Toast while still allowing customization through `className`, `ui` slots keyed by `data-slot`, and the shared `--ui-*` tokens. - Developer experience first: Intuitive component APIs, typed props, deep imports, and bilingual documentation. - Beautiful by default: A monochrome Liquid Glass material that stays consistent across light and dark themes. - Typed slots: Slot names and sizes derive from the Tailwind Variants recipe, so overrides stay checked. - Focused surface area: Twenty-five carefully styled components instead of a sprawling catalog, with consistent sizing, naming, and visual language. ## Core technologies `@xingxingmofashu/ui` is built on two foundations: Tailwind CSS for styling and Tailwind Variants for typed variants. Interactive behavior is built into each component. - **CSS-first configuration**: theme tokens live in CSS - **Modern web features**: `color-mix`, container units, `:has`, and individual transforms - **Source scanning**: the package stylesheet scans its own component files, so no extra `@source` is required - **Dynamic styling**: typed size and state variants - **Type safety**: component props derive from the theme recipes - **Conflict resolution**: `cn` merges Tailwind classes predictably ## Key features ### CSS-only glass material The glass surface, rim highlight, inner shadow, and pressed thumb are all regular CSS. There is no canvas, WebGL, or image asset behind the material. ### Light and dark themes Tokens switch through `.light` / `.dark` or `data-theme="light"` / `data-theme="dark"`. A nested light subtree can switch back even inside a dark application. ### Typed APIs Component props, size variants, controlled state, and event details are typed. Deep imports are available for each component, composable, and theme recipe. ### Server-safe Card `Card` is a native layout primitive that can render from a React Server Component. The interactive components are client components. ## FAQ ### Is the package free to use? Yes. It is open source under the MIT license. ### Does it work with React 18? No. The package targets React 19 and React DOM 19. ### Is Tailwind CSS required? Yes. Tailwind CSS 4 is a peer dependency; the package stylesheet contains tokens and material classes, not a precompiled utility sheet. ### Is it production-ready? The package is at 0.2.x. The components are tested and documented, but APIs may still change before 1.0. Pin a version and review the [release notes](https://github.com/xingxingmofashu/ui/releases) when upgrading. ### Does it include data tables, date pickers, or a command palette? Not yet. The current release focuses on twenty-five core components: elements, form controls, overlays, and feedback. Additional components will ship in later releases. ### How does it handle accessibility? Interactive components provide WAI-ARIA semantics, keyboard support, and focus management. Always test the complete interaction in your own application. ### Where can I get help? Open an issue on [GitHub](https://github.com/xingxingmofashu/ui/issues) with a reproduction. ## Explore - [Installation](/docs/en/get-started/installation): Add the package to a React project. - [Button](/docs/en/components/button): Start with the core action component. - [Toggle](/docs/en/components/toggle): See the pressed glass state. --- ## Installation URL: https://xingxingmofashu.github.io/ui/docs/en/get-started/installation Learn how to install and configure @xingxingmofashu/ui in a React application. Requires React 19, React DOM 19, Tailwind CSS 4, and Node.js 22+. ## Setup ### Add to a React project #### Install the package pnpm yarn npm bun ```bash pnpm add @xingxingmofashu/ui ``` ```bash yarn add @xingxingmofashu/ui ``` ```bash npm install @xingxingmofashu/ui ``` ```bash bun add @xingxingmofashu/ui ``` #### Add the package styles ```css [app.css] @import "tailwindcss"; @import "@xingxingmofashu/ui"; ``` The package root resolves to `dist/index.css` through its `style` export. The stylesheet includes its own Tailwind source scan, so no extra `@source` directive is needed. #### Import a component ```tsx import { Button } from "@xingxingmofashu/ui"; export function Example() { return ; } ``` The recipe returns slot classes, so a custom component can reuse the same geometry and material without copying Tailwind classes. ## Motion and browser support Transitions and pressed effects include `motion-reduce` variants. Users who set `prefers-reduced-motion: reduce` keep the layout and state changes but lose the decorative motion. The visual material relies on modern CSS: `backdrop-filter`, `color-mix`, container units, individual `translate` / `scale` properties, and `:has`. Provide a sensible fallback background for browsers that do not support `backdrop-filter`, or limit support to current evergreen browsers. ## Checklist - Import the package stylesheet exactly once, before your own overrides. - Set `.dark` or `data-theme="dark"` before first paint. - Use the optional [glass preset plugin](/docs/en/plugins/glass-preset) for `data-glass` materials. - Override tokens in an unlayered `:root` and `.dark` block for custom material. - Test glass contrast over the busiest background in the app. - Prefer `ui` for internal slots, `className` and `style` for layout, and tokens for material changes. --- ## Forms URL: https://xingxingmofashu.github.io/ui/docs/en/guides/forms Submit values, validate fields, and compose accessible React forms with the Liquid Glass controls. The form controls are designed to work with native `
` behavior first. `Form` renders a native `` and adds consolidated errors and form-level validation. `Input` renders a native ``, while `Checkbox`, `CheckboxGroup`, `Switch`, `Select`, `Slider`, and `RadioGroup` render an internal native input for submission. That means `FormData`, server actions, and progressive-enhancement patterns keep working without a custom state container. ## Form container `Form` renders a native `` with the library's vertical layout. Use `errors` to send server errors back to named `Field` controls, and `validationMode` to set the default validation timing for the fields inside it. `Form` does not replace `FormData`: native `onSubmit` still receives the browser's values, while `onFormSubmit` gives you an object for controls registered through `Field`. ```tsx
))} ); } ``` Without the provider, set the attribute directly: ```tsx document.documentElement.dataset.glass = "thick"; ``` ## Controlled state Pass `preset` and `onPresetChange` to own the value. In controlled mode, `setPreset` only calls `onPresetChange`; update the `preset` prop in that callback or the material will not change: ```tsx "use client"; import { useState, type ReactNode } from "react"; import { GlassPresetProvider, type GlassPreset, } from "@xingxingmofashu/ui/plugins/glass-preset"; export function AppShell({ children }: { children: ReactNode }) { const [preset, setPreset] = useState("thin"); return ( {children} ); } ``` The provider still writes the active value to `data-glass`, but in controlled mode `storageKey` only persists the value. It does not restore the value into the `preset` prop. Use the uncontrolled `defaultPreset` + `storageKey` setup when storage should restore the preset automatically. If you need both, initialize the controlled state from storage yourself. `GlassPresetScript` is independent: it can still read `storageKey` and set the attribute before hydration even when the provider is controlled. If the script resolves a different value than the controlled `preset`, the first paint uses the script value until the provider writes the controlled value after hydration. To avoid that flash, make the script resolve the same value as the controlled `preset`, or render the matching `data-glass` value on the server. The script only changes the DOM attribute; it does not change the value returned by `useGlassPreset` before hydration. ## Scope a preset to a container `GlassPresetScope` applies a preset to one container without changing the global value. It renders a `div` with `data-glass` and accepts normal `div` props: ```tsx import { Card } from "@xingxingmofashu/ui"; import { GlassPresetScope } from "@xingxingmofashu/ui/plugins/glass-preset"; ``` The preset's color veils inherit into descendants until another `data-glass` value or a nested `.light` / `.dark` boundary; `--ui-glass-blur` and `--ui-glass-saturate` continue to inherit across that boundary. Add `data-glass` at the boundary if you need the full preset there. The scope does not read or write the provider state or `localStorage`. ## Script-only setup If you do not need the React provider, use `GlassPresetScript` on its own or generate the script with `getGlassPresetScript`: ```tsx import { GlassPresetScript, getGlassPresetScript, } from "@xingxingmofashu/ui/plugins/glass-preset"; ; const script = getGlassPresetScript({ storageKey: "app-glass", defaultPreset: "thin", }); ``` `getGlassPresetScript` returns a plain string for frameworks that inject scripts through their own API. `GlassPresetScript` accepts a CSP `nonce` prop. The generated inline script escapes `<`, U+2028, and U+2029 in its string literals, so a runtime-provided `storageKey` cannot close the script element. The script resolves a preset in the same order as the provider: a valid stored value, then a valid `data-glass` attribute already on ``, then `defaultPreset`. ## API reference ### `GlassPresetProvider` | Prop | Type | Default | Description | | --- | --- | --- | --- | | `preset` | `GlassPreset` | — | Controlled preset. When provided, the provider does not update its internal value; update this prop from `onPresetChange`. | | `defaultPreset` | `GlassPreset` | `"thin"` | Initial value for uncontrolled mode, including the server render and the first client render before persisted state is read. Ignored when `preset` is provided. | | `storageKey` | `string` | — | `localStorage` key used to persist the preset. In uncontrolled mode it also restores the value after hydration. Omit to let the application manage persistence. | | `onPresetChange` | `(preset: GlassPreset) => void` | — | Called when `setPreset` requests a change, in both controlled and uncontrolled mode. | | `children` | `ReactNode` | — | Subtree that can read the preset with `useGlassPreset`. | | Attribute | Description | | --- | --- | | `data-glass` | Written to `` after hydration with the active preset. `GlassPresetScript` may set it earlier. | ### `useGlassPreset` Returns the provider state. It throws when called outside `GlassPresetProvider`. | Field | Type | Description | | --- | --- | --- | | `preset` | `GlassPreset` | The active preset. | | `setPreset` | `(preset: GlassPreset) => void` | Requests a change. In controlled mode, update the `preset` prop from `onPresetChange`. | ### `GlassPresetScope` | Prop | Type | Default | Description | | --- | --- | --- | --- | | `preset` | `GlassPreset` | — | Preset applied as `data-glass` to the container. Required. | | `...props` | `React.ComponentProps<"div">` | — | Passed to the rendered `div`. `data-glass` is omitted from the type. | | Attribute | Description | | --- | --- | | `data-glass` | The preset applied to the container and inherited by its descendants. | ### `GlassPresetScript` | Prop | Type | Default | Description | | --- | --- | --- | --- | | `storageKey` | `string` | — | `localStorage` key read before React hydrates. | | `defaultPreset` | `GlassPreset` | `"thin"` | Preset used when storage and the existing attribute are empty or invalid. | | `nonce` | `string` | — | CSP nonce for the inline script. | ### `getGlassPresetScript` Returns the inline script as a string. It accepts the same `storageKey` and `defaultPreset` options as `GlassPresetScript`, without `nonce`. ### `GlassPreset` ```ts type GlassPreset = "thin" | "soft" | "regular" | "thick"; ``` ## Behavior ### Hydration When the provider is uncontrolled, `GlassPresetProvider` renders its children with `defaultPreset` on the server and on the first client render. After hydration it reads `localStorage` or the existing `data-glass` attribute and updates the context. This keeps server HTML and the first client render identical when a component calls `useGlassPreset`. Without `GlassPresetScript`, a persisted value is applied after hydration, so the first paint can briefly show the default material. Controlled mode uses the `preset` prop on both server and client; it does not replace that value with persisted state. ### Persistence - Values are stored in `localStorage` under `storageKey`. - Invalid stored values are ignored. - Storage access is wrapped in `try` / `catch`; private mode and sandboxed frames fall back to in-memory state. - The provider writes the active value after hydration, including in controlled mode when `storageKey` is set. ## Checklist - Import the plugin `index.css` after the core stylesheet. - Put `GlassPresetScript` in the document head and `GlassPresetProvider` at the application root. - Use the same `storageKey` and `defaultPreset` for the script and provider, and keep both stable. - Use `GlassPresetScope` for local overrides instead of changing the global value. - Test the selected preset over the busiest background in the application.