diff --git a/README.md b/README.md index d2aae0f..6cb5023 100644 --- a/README.md +++ b/README.md @@ -67,12 +67,12 @@ This library now ships with dedicated documentation files for each component in - [IconButton](docs/IconButton.md) - [List](docs/List.md) (covers List and ListItem) - [Modal](docs/Modal.md) -- [Odometer](docs/Odometer.md) (component + useOdometer hook) +- [Odometer](docs/Odometer.md) (component + `useOdometer` hook) - [ScrollArea](docs/ScrollArea.md) - [Select](docs/Select.md) - [SvgSprite](docs/SvgSprite.md) - [Switch](docs/Switch.md) -- [Tabs](docs/Tabs.md) (includes Tabs, TabsList, TabsTrigger, TabsContent) +- [Tabs](docs/Tabs.md) (includes `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`) - [Tag](docs/Tag.md) - [TextArea](docs/TextArea.md) - [TextField](docs/TextField.md) @@ -83,7 +83,7 @@ This library now ships with dedicated documentation files for each component in - [View](docs/View.md) - [ViewDrawer](docs/ViewDrawer.md) - [ViewModal](docs/ViewModal.md) -- [Viewport](docs/Viewport.md) (ViewportProvider + useViewport) +- [Viewport](docs/Viewport.md) (`ViewportProvider` + `useViewport`) Notes: @@ -134,15 +134,40 @@ export default defineConfig({ plugins: [ ui({ themeDir: "./theme", // Directory for theme files - configFileName: "ui.config", // Name of config files - styleFileName: "ui.style", // Name of style files + configName: "ui.config", // Name of config files + styleName: "ui.style", // Name of style files mergeConfig: true, // Merge configs from different directories mergeStyles: true, // Merge styles from different directories + splitChunks: true, // Enable automatic chunk splitting for components }), ], }); ``` +### Plugin Options + +| Option | Type | Default | Description | +| :------------ | :------------------------------------------------- | :------------ | :----------------------------------------------------------------------------------------------------- | +| `themeDir` | `string` | `"."` | Directory path where plugin configuration and style files are located. | +| `configName` | `string` | `"config.ui"` | Name of the configuration file. | +| `styleName` | `string` | `"style.ui"` | Name of the SCSS style file. | +| `mergeConfig` | `boolean` | `true` | Whether to merge configuration files from different directories. | +| `mergeStyles` | `boolean` | `true` | Whether to merge style files from different directories. | +| `splitChunks` | `boolean \| (name: string) => string \| undefined` | `true` | Enables automatic chunk splitting. If a function is provided, it can be used to customize chunk names. | + +#### Customizing Chunk Names + +You can pass a callback function to `splitChunks` to customize the generated chunk names: + +```ts +ui({ + splitChunks: name => { + if (name === "button") return "ui-core-button"; + return `ui-${name}`; + }, +}); +``` + ### Configuration Files The `addon-ui` configuration is designed to retrieve configuration from each extension separately, allowing for @@ -271,7 +296,7 @@ extensions with the same functionality but different visual appearances. ### Global Theme Customization -You can customize the theme globally by passing props to the UIProvider: +You can customize the theme globally by passing props to the `UIProvider`: ```jsx import {UIProvider} from "addon-ui"; @@ -289,6 +314,8 @@ const customTheme = { icons: { // Custom icons }, + // Specify the DOM element to set theme/view/browser attributes on + container: "#app-root", }; function App() { @@ -296,6 +323,17 @@ function App() { } ``` +### UIProvider Props + +| Prop | Type | Default | Description | +| :----------- | :----------------------------- | :---------- | :-------------------------------------------------------- | +| `components` | `ComponentsProps` | `{}` | Component-specific configuration overrides. | +| `icons` | `Icons` | `{}` | Custom SVG icons registration. | +| `extra` | `ExtraProps` | `{}` | App-wide extra properties. | +| `storage` | `ThemeStorageContract \| true` | `undefined` | Persistence storage for theme settings. | +| `container` | `string \| Element \| false` | `"html"` | Target element for attributes. Set to `false` to disable. | +| `view` | `string` | `undefined` | Custom view identifier for specific styling. | + ### Using Extra Props Extra Props is a powerful feature that allows you to extend component props with custom properties. This is particularly @@ -438,12 +476,13 @@ function App() { ## Theming and style reuse -- Global theme tokens (colors, typography, spacing, transitions) live in your ui.style.scss. Components consume them - through fallbacks. -- Each component also exposes its own `--component-*` variables. See the CSS variables tables in the docs to know - exactly what you can override. -- Light/dark modes: use `@import "addon-ui/theme";` and the provided `@include light { ... }` / `@include dark { ... }` - mixins in your theme SCSS to scope tokens per color scheme. +- Global theme tokens (colors, typography, spacing, transitions) live in your `ui.style.scss`. +- Each component also exposes its own `--component-*` variables. See the CSS variables tables in the docs to know exactly what you can override. +- **Theme Mixins**: Use `@import "addon-ui/theme";` to access `@include light { ... }` and `@include dark { ... }` mixins. +- **Universal Targeting**: These mixins are container-agnostic. They work correctly whether the `theme` attribute is on a parent element or directly on the component itself. +- **Context-Aware**: + - When used at the top level, they generate global selectors: `[theme="dark"] { ... }`. + - When used inside a component, they generate scoped selectors: `[theme="dark"] .my-comp, .my-comp[theme="dark"] { ... }`. ## Radix UI and third-party integrations diff --git a/docs/TextField.md b/docs/TextField.md index 574968c..d4f3cc6 100644 --- a/docs/TextField.md +++ b/docs/TextField.md @@ -46,6 +46,9 @@ export function Example() { + {/* Strict numeric input */} + + {/* Full width and content slots */} +1} after={USD} placeholder="With addons" /> @@ -80,6 +83,7 @@ Only the prop name, type, and default are listed below. | `afterClassName` | `string` | — | | `beforeClassName` | `string` | — | | `type` | `ComponentProps<'input'>['type']` | `'text'` | +| `strict` | `boolean` | `false` | | HTML input attrs | all standard `input` attributes (e.g., `value`, `defaultValue`, `onChange`, `placeholder`, `name`, `id`, etc.) | — | Note: Defaults may also be provided globally via theme/config (`UIProvider`, `ui.config.ts`). Local props take precedence over global config. @@ -123,9 +127,14 @@ Only variables actually referenced in `src/components/TextField/text-field.modul | `--text-field-line-height` | `var(--text-field-line-height, var(--line-height, 1 rem))` | | `--text-field-padding` | `var(--text-field-padding, 8px 12px)` | | `--text-field-border-radius` | `var(--text-field-border-radius, 8px)` | +| `--text-field-speed-border-color` | `var(--text-field-speed-border-color, var(--speed-color))` | +| `--text-field-speed-box-shadow` | `var(--text-field-speed-box-shadow, var(--speed-color))` | +| `--text-field-speed-bg` | `var(--text-field-speed-bg, var(--speed-color))` | | `--text-field-focus-border-color` | `var(--text-field-focus-border-color, color-mix(in srgb, white 40%, var(--primary-color)))` | | `--text-field-focus-shadow` | `var(--text-field-focus-shadow, 0 0 4px var(--primary-color))` | | `--text-field-disabled-opacity` | `var(--text-field-disabled-opacity, 0.7)` | +| `--text-field-speed-color` | `var(--text-field-speed-color, var(--speed-color))` | +| `--text-field-placeholder-color` | `var(--text-field-placeholder-color, var(--text-secondary-color))` | | `--text-field-regular-color` | `var(--text-field-regular-color, var(--text-field-color, var(--text-primary-color)))` | | `--text-field-color` | `var(--text-field-color)` (none) | | `--text-field-regular-bg-color` | `var(--text-field-regular-bg-color, var(--text-field-bg-color, var(--bg-secondary-color)))` | @@ -146,7 +155,9 @@ Only variables actually referenced in `src/components/TextField/text-field.modul | `--text-field-padding-sm` | `var(--text-field-padding-sm, 6px 10px)` | | `--text-field-padding-md` | `var(--text-field-padding-md, 10px 14px)` | | `--text-field-padding-lg` | `var(--text-field-padding-lg, 12px 16px)` | -| `--text-field-font-size-sm` | Contextual defaults: `12px` (small), `16px` (medium), `18px` (large) | +| `--text-field-font-size-sm` | `var(--text-field-font-size-sm, 12px)` | +| `--text-field-font-size-md` | `var(--text-field-font-size-md, 16px)` | +| `--text-field-font-size-lg` | `var(--text-field-font-size-lg, 18px)` | | `--text-field-success-color` | `var(--text-field-success-color, var(--success-color))` | | `--text-field-accent-border-width` | `var(--text-field-accent-border-width, 2px)` | | `--text-field-error-color` | `var(--text-field-error-color, var(--error-color))` | @@ -154,7 +165,7 @@ Only variables actually referenced in `src/components/TextField/text-field.modul Notes: - Accents add a stronger border (`--text-field-accent-border-width`) and shadow using success/error colors. If the component variables aren’t defined, they fall back to theme tokens like `--success-color` and `--error-color`. -- The `--text-field-font-size-sm` variable is reused across all three size modifiers with contextual defaults. Define it once to override all sizes at once. +- Size variants use their own font-size variables (`--text-field-font-size-sm`, `--text-field-font-size-md`, `--text-field-font-size-lg`) for more granular control. ### Theming and global configuration @@ -206,3 +217,9 @@ import {UIProvider} from "addon-ui"; - The component renders a native `` inside a wrapper; provide a programmatic label. The `label` prop maps to `aria-label` on both wrapper and input. - For a visible label, associate a `