From 7763452467ecd184402fdf64838aec605f891231 Mon Sep 17 00:00:00 2001 From: Ravi Suhag Date: Sat, 8 Aug 2026 15:27:28 +0530 Subject: [PATCH 1/6] docs: fix inaccuracies, dead links, and stale references across docs Correct wrong information users would hit, repair broken links, align repo docs with the real codebase, and fill documentation gaps. Docs site: - getting-started: fix useTheme import (main entry, not /hooks), correct prerequisites to Node >=22 / React 19, note React peer deps, point Next Steps to DataView instead of the deprecated DataTable - fix 14 internal links missing the /docs base path (overview + theme pages) - select props: variant is 'outline' | 'text' (was 'default' | 'filter'), drop non-existent aria props, add nativeButton - datatable props: replace non-existent columnType with dataType, add loadingRowCount and onRowClick - table props: colSpan is required - add missing Box and ThemeProvider pages (both deprecated aliases, noted) - add missing Accessibility/Examples sections and source frontmatter, rename stray "Usage" headings to "Anatomy" - enrich thin pages and rewrite weak descriptions; drop Lorem Ipsum demo text Repo docs: - add Apache-2.0 LICENSE (was missing); align raystack package license from ISC; copy LICENSE into published packages - README: fix pnpm test -> pnpm test:apsara; drop deprecated DataTable - DEVELOPMENT.md: fix directory layout, build outputs, and hook example - CONTRIBUTING.md: fix docs path and barrel filename; link migration guide and RFCs - agents.md: test-utils is a directory - RFC 003 marked Completed; remove dead ANALYSIS.md links in RFC 002/003 - V1-migration: drop unshipped "1.0.0" framing - apps/www: replace create-next-app boilerplate README --- CONTRIBUTING.md | 20 +- DEVELOPMENT.md | 20 +- LICENSE | 201 ++++++++++++++++++ agents.md | 2 +- apps/www/README.md | 45 ++-- .../docs/(overview)/getting-started.mdx | 32 ++- .../www/src/content/docs/(overview)/index.mdx | 16 +- .../src/content/docs/(overview)/styling.mdx | 2 +- .../content/docs/components/amount/index.mdx | 2 +- .../docs/components/announcement-bar/demo.ts | 22 ++ .../components/announcement-bar/index.mdx | 20 +- .../content/docs/components/badge/index.mdx | 2 +- .../src/content/docs/components/box/demo.ts | 52 +++++ .../src/content/docs/components/box/index.mdx | 64 ++++++ .../src/content/docs/components/box/props.ts | 10 + .../docs/components/checkbox/index.mdx | 2 +- .../docs/components/combobox/index.mdx | 17 ++ .../content/docs/components/container/demo.ts | 16 +- .../docs/components/container/index.mdx | 8 +- .../docs/components/context-menu/index.mdx | 26 ++- .../docs/components/copy-button/index.mdx | 8 +- .../docs/components/datatable/props.ts | 10 +- .../docs/components/dataview/index.mdx | 21 ++ .../docs/components/empty-state/index.mdx | 24 ++- .../content/docs/components/flex/index.mdx | 17 +- .../content/docs/components/grid/index.mdx | 17 +- .../docs/components/headline/index.mdx | 10 + .../content/docs/components/link/index.mdx | 2 +- .../content/docs/components/menu/index.mdx | 27 ++- .../content/docs/components/menubar/index.mdx | 4 +- .../docs/components/scroll-area/index.mdx | 1 + .../content/docs/components/select/props.ts | 27 +-- .../content/docs/components/table/props.ts | 4 +- .../content/docs/components/text/index.mdx | 2 +- .../docs/components/theme-provider/demo.ts | 29 +++ .../docs/components/theme-provider/index.mdx | 101 +++++++++ .../docs/components/theme-provider/props.ts | 124 +++++++++++ .../src/content/docs/theme/overview/index.mdx | 10 +- docs/V1-migration.md | 6 +- docs/rfcs/002-unified-dataview-component.md | 1 - docs/rfcs/003-guided-tour-component.md | 3 +- packages/raystack/LICENSE | 201 ++++++++++++++++++ packages/raystack/README.md | 8 +- packages/raystack/package.json | 2 +- packages/tools-config/LICENSE | 201 ++++++++++++++++++ 45 files changed, 1313 insertions(+), 126 deletions(-) create mode 100644 LICENSE create mode 100644 apps/www/src/content/docs/components/box/demo.ts create mode 100644 apps/www/src/content/docs/components/box/index.mdx create mode 100644 apps/www/src/content/docs/components/box/props.ts create mode 100644 apps/www/src/content/docs/components/theme-provider/demo.ts create mode 100644 apps/www/src/content/docs/components/theme-provider/index.mdx create mode 100644 apps/www/src/content/docs/components/theme-provider/props.ts create mode 100644 packages/raystack/LICENSE create mode 100644 packages/tools-config/LICENSE diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2c647f93e..e0126ef35 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,7 @@ Thank you for your interest in contributing to Apsara! This guide will help you - [Release Workflow Details](#release-workflow-details) - [NPM Publishing](#npm-publishing) - [Canary Releases](#canary-releases) + - [Project Documentation](#project-documentation) - [Getting Help](#getting-help) - [Code of Conduct](#code-of-conduct) @@ -57,8 +58,8 @@ pnpm dev ``` 3. **Make your changes** in the appropriate directories: - - **Components**: `packages/raystack/` - - **Documentation**: `apps/www/` + - **Components**: `packages/raystack/components/` + - **Documentation**: `apps/www/src/content/docs/` 4. **Test your changes**: ```bash @@ -92,19 +93,19 @@ pnpm dev ## Component Development -1. Create components in `packages/raystack/` +1. Create components in `packages/raystack/components/` 2. Follow the existing component structure: ``` component-name/ - ├── index.ts # Export barrel file + ├── index.tsx # Export barrel file ├── component-name.tsx # Main component ├── component-name.module.css # Styles └── __tests__/ # Tests └── component-name.test.tsx ``` -3. Export new components from `packages/raystack/index.ts` -4. Update the component documentation in `apps/www/content/docs` +3. Export new components from `packages/raystack/index.tsx` +4. Update the component documentation in `apps/www/src/content/docs` ## Documentation Development @@ -293,6 +294,13 @@ Pushes to `main` are published the same way but don't have a PR to comment on. I pnpm add https://pkg.pr.new/raystack/apsara/@raystack/apsara@ ``` +## Project Documentation + +Beyond this guide, the repo keeps deeper docs under `docs/`: + +- [Migration Guide](./docs/V1-migration.md) — breaking changes and how to move from the Radix-based release to the current Base UI-based version. +- [RFCs](./docs/rfcs/) — design proposals and decisions behind major features (Base UI migration, unified DataView, guided Tour). + ## Getting Help If you encounter issues: diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f51f2f845..5d77f1cf1 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -96,12 +96,12 @@ apsara/ ### Key Directories - **`packages/raystack/`**: Contains the main Apsara component library - - `accordion/`, `avatar/`, `badge/`, `button/`, etc.: React components (at root level) - - `v1/`: Legacy structure for backward compatibility - - `v1/components/`: Legacy component structure - - `v1/hooks/`: Custom React hooks - - `v1/icons/`: Icon components - - `style.css`: Main stylesheet + - `components/`: React components, one folder each (`accordion/`, `avatar/`, `button/`, etc.) + - `hooks/`: Custom React hooks + - `icons/`: Icon components + - `styles/`: Shared styles and theme tokens + - `types/`: Shared TypeScript types + - `test-utils/`: Test helpers - `dist/`: Built output - **`apps/www/`**: Documentation website built with Next.js and Fumadocs @@ -125,7 +125,7 @@ import { Button, Flex } from '@raystack/apsara' // Specific feature imports import { ChevronDownIcon } from '@raystack/apsara/icons' -import { useLocalStorage } from '@raystack/apsara/hooks' +import { useCopyToClipboard } from '@raystack/apsara/hooks' // Styles import '@raystack/apsara/style.css' @@ -253,9 +253,9 @@ pnpm build:apsara ``` This creates optimized builds in the `dist/` directory with: -- ESM modules (`dist/index.js`, `dist/v1/index.js`) -- CommonJS modules (`dist/index.cjs`, `dist/v1/index.cjs`) -- TypeScript declarations (`dist/index.d.ts`, `dist/v1/index.d.ts`) +- ESM modules (`dist/index.js`) +- CommonJS modules (`dist/index.cjs`) +- TypeScript declarations (`dist/index.d.ts`) - CSS files (`dist/style.css`, `dist/normalize.css`) ### Build Configuration diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..b4b594f72 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative + Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, excluding + those notices that do not pertain to any part of the Derivative + Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and do + not modify the License. You may add Your own attribution notices + within Derivative Works that You distribute, alongside or as an + addendum to the NOTICE text from the Work, provided that such + additional attribution notices cannot be construed as modifying + the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Raystack + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/agents.md b/agents.md index dedd45ad3..7683265b6 100644 --- a/agents.md +++ b/agents.md @@ -21,7 +21,7 @@ packages/raystack/ # Main component library ├── icons/ # Icon components ├── styles/ # Global styles ├── types/ # Type definitions -└── test-utils.tsx # Testing utilities +└── test-utils/ # Testing utilities apps/www/ # Documentation site ├── src/content/docs/ # Component documentation diff --git a/apps/www/README.md b/apps/www/README.md index e215bc4cc..69677777a 100644 --- a/apps/www/README.md +++ b/apps/www/README.md @@ -1,36 +1,39 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Apsara Documentation Site + +The documentation site for [Apsara](https://apsara.raystack.org), built with [Next.js](https://nextjs.org) and [Fumadocs](https://fumadocs.dev). ## Getting Started -First, run the development server: +From the repo root, `pnpm start` runs both the component library and this docs site together. To run only the docs site, from this folder: -```bash -npm run dev -# or -yarn dev -# or +```sh pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +Open [http://localhost:3000](http://localhost:3000) to see it. -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +The site reads the local `@raystack/apsara` package, so a build of the library runs automatically before `pnpm build`. When you change a component, restart the library dev server (or `pnpm start` from the root) to pick it up. -## Learn More +## Content -To learn more about Next.js, take a look at the following resources: +Documentation lives in `src/content/docs/` as `.mdx` files. Each component has its own folder: -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +``` +src/content/docs/components// +├── index.mdx # the page: overview, anatomy, examples, accessibility +├── props.ts # prop tables, rendered by +└── demo.ts # live code examples shown by the component +``` -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +Navigation for sections like `theme` and `ai-elements` is set by their `meta.json`. The `components/` folder has no `meta.json`, so its pages are picked up automatically in alphabetical order. -## Deploy on Vercel +To add or edit a component page, see the [Documentation Development](../../CONTRIBUTING.md#documentation-development) section in the contributing guide. -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +## Scripts -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +```sh +pnpm dev # start the dev server +pnpm build # build the static site (builds the library first) +pnpm start # serve the production build +pnpm lint # check formatting and lint rules with Biome +``` diff --git a/apps/www/src/content/docs/(overview)/getting-started.mdx b/apps/www/src/content/docs/(overview)/getting-started.mdx index edcacef16..e25e4e6a4 100644 --- a/apps/www/src/content/docs/(overview)/getting-started.mdx +++ b/apps/www/src/content/docs/(overview)/getting-started.mdx @@ -9,8 +9,14 @@ This guide walks you through installing Apsara and building your first component Apsara requires: -- **Node.js** 18 or later -- **React** 18 or 19 +- **Node.js** 22 or later +- **React** 19 + +React and React DOM are peer dependencies. Make sure your project has them installed: + +```package-install +react react-dom +``` ## Installation @@ -149,11 +155,23 @@ import { MagnifyingGlassIcon, Cross2Icon } from "@raystack/apsara/icons"; ## Importing Hooks -Utility hooks are available from a dedicated export: +Utility hooks such as `useCopyToClipboard`, `useDebouncedState`, and `useMouse` are available from a dedicated export: ```tsx import { Button } from "@raystack/apsara"; -import { useTheme } from "@raystack/apsara/hooks"; +import { useCopyToClipboard } from "@raystack/apsara/hooks"; + +function CopyButton({ value }: { value: string }) { + const { copy } = useCopyToClipboard(); + + return ; +} +``` + +To read or change the active theme, use `useTheme` from the main entry: + +```tsx +import { Button, useTheme } from "@raystack/apsara"; function ThemeToggle() { const { resolvedTheme, setTheme } = useTheme(); @@ -168,6 +186,6 @@ function ThemeToggle() { ## Next Steps -- [Theme Overview](/theme/overview) — Configure colors, spacing, and style variants -- [Button](/components/button) — Start with a common component -- [DataTable](/components/datatable) — Build data-rich interfaces +- [Theme Overview](/docs/theme/overview) — Configure colors, spacing, and style variants +- [Button](/docs/components/button) — Start with a common component +- [DataView](/docs/components/dataview) — Build data-rich interfaces diff --git a/apps/www/src/content/docs/(overview)/index.mdx b/apps/www/src/content/docs/(overview)/index.mdx index 5a8d9b185..869ff9393 100644 --- a/apps/www/src/content/docs/(overview)/index.mdx +++ b/apps/www/src/content/docs/(overview)/index.mdx @@ -17,13 +17,13 @@ Apsara is an open-source React component library that provides enterprise-grade, ## Components -Apsara provides over 50 components organized by function: +Apsara provides over 60 components organized by function: | Category | Components | |----------|------------| -| **Layout** | Flex, Grid, Container, Separator | +| **Layout** | Flex, Grid, Container, Box, Separator | | **Navigation** | Navbar, Sidebar, Breadcrumb, Tabs, Link | -| **Data Display** | DataTable, Table, List, Avatar, Badge, Chip, Indicator | +| **Data Display** | DataView, Table, List, Avatar, Badge, Chip, Indicator | | **Forms** | Button, Input, TextArea, Select, Combobox, Checkbox, Radio, Switch, Slider, ColorPicker, Calendar | | **Feedback** | Dialog, Drawer, Popover, Tooltip, Toast, Callout, EmptyState, Skeleton, Spinner | | **Utilities** | Command, Search, CopyButton, CodeBlock, ScrollArea | @@ -51,7 +51,7 @@ Tokens follow a consistent naming convention: } ``` -See the [Theme Overview](/theme/overview) for complete documentation. +See the [Theme Overview](/docs/theme/overview) for complete documentation. ## Technology @@ -64,7 +64,7 @@ Apsara is built with: ## Next Steps -- [Getting Started](/getting-started) — Install Apsara and build your first component -- [Styling](/styling) — Learn how to style and customize components -- [Theme Overview](/theme/overview) — Learn about the theming system -- [Components](/components/button) — Explore the component library +- [Getting Started](/docs/getting-started) — Install Apsara and build your first component +- [Styling](/docs/styling) — Learn how to style and customize components +- [Theme Overview](/docs/theme/overview) — Learn about the theming system +- [Components](/docs/components/button) — Explore the component library diff --git a/apps/www/src/content/docs/(overview)/styling.mdx b/apps/www/src/content/docs/(overview)/styling.mdx index 22ccc77b0..880ca9df7 100644 --- a/apps/www/src/content/docs/(overview)/styling.mdx +++ b/apps/www/src/content/docs/(overview)/styling.mdx @@ -21,7 +21,7 @@ Design tokens are CSS custom properties that adapt automatically to the active t } ``` -See the [Theme](/theme/overview) section for the complete token reference. +See the [Theme](/docs/theme/overview) section for the complete token reference. ## Customizing Components diff --git a/apps/www/src/content/docs/components/amount/index.mdx b/apps/www/src/content/docs/components/amount/index.mdx index dafce4576..d70411759 100644 --- a/apps/www/src/content/docs/components/amount/index.mdx +++ b/apps/www/src/content/docs/components/amount/index.mdx @@ -1,6 +1,6 @@ --- title: Amount -description: Component for displaying monetary values +description: Formats and displays monetary values with the correct currency symbol, separators, and decimal places for a given locale. source: packages/raystack/components/amount --- diff --git a/apps/www/src/content/docs/components/announcement-bar/demo.ts b/apps/www/src/content/docs/components/announcement-bar/demo.ts index 600f86be1..1428e2b28 100644 --- a/apps/www/src/content/docs/components/announcement-bar/demo.ts +++ b/apps/www/src/content/docs/components/announcement-bar/demo.ts @@ -25,3 +25,25 @@ export const playground = { padding: 0 } }; + +export const variantsDemo = { + type: 'code', + code: ` + + + + + ` +}; diff --git a/apps/www/src/content/docs/components/announcement-bar/index.mdx b/apps/www/src/content/docs/components/announcement-bar/index.mdx index 034793fda..4d4d6692f 100644 --- a/apps/www/src/content/docs/components/announcement-bar/index.mdx +++ b/apps/www/src/content/docs/components/announcement-bar/index.mdx @@ -1,18 +1,10 @@ --- title: Announcement Bar -description: AnnouncementBar component to display message +description: A banner that displays a short site-wide message with an optional action, such as a product update, promotion, or warning. source: packages/raystack/components/announcement-bar --- -import { - playground, - variantsDemo, - sizesDemo, - colorsDemo, - disabledDemo, - loadingDemo, - iconsDemo, -} from "./demo.ts"; +import { playground, variantsDemo } from "./demo.ts"; @@ -45,6 +37,14 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test | `announcement-bar-action-label` | The action button's text label | | `announcement-bar-action-icon` | Wrapper around the action icon (when `actionIcon` is set) | +## Examples + +### Variant + +Variants convey the tone of the announcement. Default is `normal`; use `error` for urgent notices and `gradient` for promotional messages. + + + ## Accessibility - The action (when `actionLabel` or `actionIcon` is provided) is rendered diff --git a/apps/www/src/content/docs/components/badge/index.mdx b/apps/www/src/content/docs/components/badge/index.mdx index b1844dbe2..12da73a7b 100644 --- a/apps/www/src/content/docs/components/badge/index.mdx +++ b/apps/www/src/content/docs/components/badge/index.mdx @@ -1,6 +1,6 @@ --- title: Badge -description: Badge component to display concise information. +description: A small label for highlighting status, counts, or categories at a glance, such as marking an item as new or showing its state. source: packages/raystack/components/badge --- diff --git a/apps/www/src/content/docs/components/box/demo.ts b/apps/www/src/content/docs/components/box/demo.ts new file mode 100644 index 000000000..eff1de1ff --- /dev/null +++ b/apps/www/src/content/docs/components/box/demo.ts @@ -0,0 +1,52 @@ +'use client'; + +export const preview = { + type: 'code', + code: ` + + Box renders a plain div. + ` +}; + +export const basicDemo = { + type: 'code', + code: ` + + A simple container with custom styles. + ` +}; + +export const nestedDemo = { + type: 'code', + code: ` + + + Prefer Flex for layout + + Box adds no layout behavior — combine it with Flex or Grid when you + need alignment, gaps, or columns. + + + ` +}; diff --git a/apps/www/src/content/docs/components/box/index.mdx b/apps/www/src/content/docs/components/box/index.mdx new file mode 100644 index 000000000..35ccb7906 --- /dev/null +++ b/apps/www/src/content/docs/components/box/index.mdx @@ -0,0 +1,64 @@ +--- +title: Box +description: A generic container that renders a plain div element. +source: packages/raystack/components/box +--- + +import { preview, basicDemo, nestedDemo } from "./demo.ts"; + + + Box is deprecated and will be removed in a future major version. Use [Flex](/docs/components/flex) instead. + + + + +Box is the most basic layout primitive. It renders a plain `
` and passes through every standard div prop — `className`, `style`, event handlers, and so on. It adds no styling and no layout behavior of its own. + +Choosing between the layout primitives: + +- **Box** — a bare container with no built-in layout. Use it only when you need a plain wrapper element. +- **[Flex](/docs/components/flex)** — a flexbox container with `direction`, `gap`, `align`, and `justify` props. Use it for one-dimensional layouts (rows or columns). +- **[Grid](/docs/components/grid)** — a CSS grid container with `columns`, `rows`, and `gap` props. Use it for two-dimensional layouts. + +## Anatomy + +Import and assemble the component: + +```tsx +import { Box } from "@raystack/apsara"; + + +``` + +## API Reference + +Renders a plain `
` element. All standard div props (attributes, event handlers, `ref`) are passed through to the underlying element. + + + +### Slots + +Every rendered part carries a stable `data-slot` attribute for [styling and testing](/docs/styling#with-data-slot): + +| Slot | Element | +|------|---------| +| `box` | The root `
` element | + +## Examples + +### Basic Usage + +Style a Box directly with inline styles or a class. + + + +### Composing with Flex + +Box has no layout props. Nest a Flex (or Grid) inside when you need alignment or spacing. + + + +## Accessibility + +- Box is a primitive: it renders a plain `
` and adds no semantics, roles, or keyboard behavior. +- Add ARIA attributes yourself when the container has a semantic purpose, or use a semantic element instead. diff --git a/apps/www/src/content/docs/components/box/props.ts b/apps/www/src/content/docs/components/box/props.ts new file mode 100644 index 000000000..21f1440a8 --- /dev/null +++ b/apps/www/src/content/docs/components/box/props.ts @@ -0,0 +1,10 @@ +export interface BoxProps { + /** Content rendered inside the box */ + children?: React.ReactNode; + + /** Custom CSS class names */ + className?: string; + + /** Inline styles applied to the underlying `
` */ + style?: React.CSSProperties; +} diff --git a/apps/www/src/content/docs/components/checkbox/index.mdx b/apps/www/src/content/docs/components/checkbox/index.mdx index 011548caa..487dc2062 100644 --- a/apps/www/src/content/docs/components/checkbox/index.mdx +++ b/apps/www/src/content/docs/components/checkbox/index.mdx @@ -1,6 +1,6 @@ --- title: Checkbox -description: Checkbox is a user interface control that enables users to toggle between checked, unchecked, and indeterminate states +description: Checkbox is a user interface control that enables users to toggle between checked, unchecked, and indeterminate states. source: packages/raystack/components/checkbox --- diff --git a/apps/www/src/content/docs/components/combobox/index.mdx b/apps/www/src/content/docs/components/combobox/index.mdx index c1fe3c8f8..85710c5c0 100644 --- a/apps/www/src/content/docs/components/combobox/index.mdx +++ b/apps/www/src/content/docs/components/combobox/index.mdx @@ -1,6 +1,7 @@ --- title: Combobox description: An input field with an attached dropdown that allows users to search and select from a list of options. +source: packages/raystack/components/combobox tag: new --- @@ -131,3 +132,19 @@ Pass the `multiple` prop to enable multi-select. Selected values appear as chips Use `value` and `onValueChange` for controlled behavior. + +## Accessibility + +- Follows the [WAI-ARIA Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) + via [Base UI Combobox](https://base-ui.com/react/components/combobox): the input + is a `role="combobox"` with `aria-expanded` and `aria-controls`, the popup list + is a `listbox`, and each item is an `option` with `aria-selected`. +- Arrow keys move the highlight through visible options, Enter selects the + highlighted option, and Escape closes the popup — focus stays in the input + the whole time, so typing to filter never loses the user's place. +- In multiple mode, each item renders a checkbox that mirrors its selected + state, and selected values appear in the input as removable chips. +- Group labels use Base UI's `Combobox.GroupLabel`, which links the label to + its group via `aria-labelledby` — wrap `Combobox.Label` in `Combobox.Group`. +- Wrap the Combobox with [Field](/docs/components/field) to associate a + visible label, description, and error message with the input. diff --git a/apps/www/src/content/docs/components/container/demo.ts b/apps/www/src/content/docs/components/container/demo.ts index 730d40d36..83a875606 100644 --- a/apps/www/src/content/docs/components/container/demo.ts +++ b/apps/www/src/content/docs/components/container/demo.ts @@ -25,7 +25,7 @@ export const playground = { children: { type: 'text', initialValue: - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book." + 'Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them.' } }, getCode @@ -39,7 +39,7 @@ export const alignDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` }, @@ -48,7 +48,7 @@ export const alignDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` }, @@ -57,7 +57,7 @@ export const alignDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` } @@ -71,7 +71,7 @@ export const sizeDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` }, @@ -80,7 +80,7 @@ export const sizeDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` }, @@ -89,7 +89,7 @@ export const sizeDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` }, @@ -98,7 +98,7 @@ export const sizeDemo = { code: ` - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + Workspace settings control how members join, what they can access, and how billing works. Changes apply to everyone in your organization as soon as you save them. ` } diff --git a/apps/www/src/content/docs/components/container/index.mdx b/apps/www/src/content/docs/components/container/index.mdx index 691d0d5f9..0c0b13534 100644 --- a/apps/www/src/content/docs/components/container/index.mdx +++ b/apps/www/src/content/docs/components/container/index.mdx @@ -8,6 +8,10 @@ import { playground, alignDemo, sizeDemo } from "./demo.ts"; +## Overview + +`Container` constrains content to a readable width. It renders a `div` with a `size`-based max-width (`small`, `medium`, `large`, or the default `none`, which adds no limit) and an `align` prop that positions it within its parent (default `center`). Use it as the outer wrapper for pages, articles, and settings forms; lay out the content inside it with [Flex](/docs/components/flex) or [Grid](/docs/components/grid). + ## Anatomy Import and assemble the component: @@ -36,13 +40,13 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test ### Size -Containers can have multiple size. +The `size` prop caps the container's max-width. The default is `none`, which lets content span the full width of the parent. ### Align -Containers can be aligned to the left, center, or right of their parent element. +The `align` prop positions the container within its parent — left, center, or right. Default is `center`. diff --git a/apps/www/src/content/docs/components/context-menu/index.mdx b/apps/www/src/content/docs/components/context-menu/index.mdx index be0e69feb..3b20dbe73 100644 --- a/apps/www/src/content/docs/components/context-menu/index.mdx +++ b/apps/www/src/content/docs/components/context-menu/index.mdx @@ -16,10 +16,19 @@ import { -## Usage +## Anatomy + +Import and assemble the component: ```tsx import { ContextMenu } from '@raystack/apsara' + + + + + + + ``` ## API Reference @@ -153,3 +162,18 @@ By default (`autocompleteMode="auto"`), items are automatically filtered as the For submenus, you can independently enable autocomplete by passing `autocomplete` to `ContextMenu.Submenu`. + +## Accessibility + +- Built on [Base UI Context Menu](https://base-ui.com/react/components/context-menu): + the popup uses `role="menu"` and items use `role="menuitem"`, following the + [WAI-ARIA Menu pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu/). +- Opens on right-click or long press (touch); focus moves into the menu when + it opens and returns to the page when it closes with Escape. +- Arrow keys move through items, Enter activates the highlighted item, and + ArrowRight/ArrowLeft open and close submenus. +- With `autocomplete`, the popup becomes a `role="dialog"` containing a search + input, items render as `role="option"`, and focus stays in the input while + arrow keys move the highlight — Escape first closes an open submenu. +- `ContextMenu.Label` must be wrapped in `ContextMenu.Group` so the group is + labelled via `aria-labelledby`. diff --git a/apps/www/src/content/docs/components/copy-button/index.mdx b/apps/www/src/content/docs/components/copy-button/index.mdx index 10a241ddc..13fd1218a 100644 --- a/apps/www/src/content/docs/components/copy-button/index.mdx +++ b/apps/www/src/content/docs/components/copy-button/index.mdx @@ -8,6 +8,10 @@ import { playground, sizesDemo, stateDemo } from "./demo.ts"; +## Overview + +`CopyButton` is an [IconButton](/docs/components/icon-button) wired to the clipboard: pass the `text` to copy and it handles the click, swaps the copy icon for a check, and announces "Copied" to screen readers. The check icon reverts after `resetTimeout` (default 1000ms); set `resetIcon={false}` to keep it. Drop it next to code snippets, API keys, and IDs. If you need copy behavior with your own UI, use the `useCopyToClipboard` hook from `@raystack/apsara/hooks` instead. + ## Anatomy Import and assemble the component: @@ -42,13 +46,13 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test ### Size -Like IconButton, CopyButton supports different sizes: +Like IconButton, CopyButton supports sizes 1 through 4. Default is `2`. ### States -The CopyButton inherits all states from IconButton +CopyButton inherits all IconButton states. A disabled button ignores clicks and never triggers a copy. diff --git a/apps/www/src/content/docs/components/datatable/props.ts b/apps/www/src/content/docs/components/datatable/props.ts index 5895f2b5c..5ffc5480f 100644 --- a/apps/www/src/content/docs/components/datatable/props.ts +++ b/apps/www/src/content/docs/components/datatable/props.ts @@ -25,6 +25,12 @@ export interface DataTableProps { */ isLoading?: boolean; + /** Number of skeleton rows to render while loading. */ + loadingRowCount?: number; + + /** Callback fired when a row is clicked. */ + onRowClick?: (row: T) => void; + /** Default sort configuration */ defaultSort?: Sort; @@ -77,8 +83,8 @@ export interface DataTableColumnDef { /** Column header text */ header: string; - /** Data type */ - columnType: 'text' | 'number' | 'date' | 'select'; + /** Data type used for sorting and filter value coercion */ + dataType?: 'string' | 'number' | 'boolean'; /** Enable sorting */ enableSorting?: boolean; diff --git a/apps/www/src/content/docs/components/dataview/index.mdx b/apps/www/src/content/docs/components/dataview/index.mdx index 8e2e20864..bf642aeab 100644 --- a/apps/www/src/content/docs/components/dataview/index.mdx +++ b/apps/www/src/content/docs/components/dataview/index.mdx @@ -32,6 +32,8 @@ In scope today: `DataView.List` (table + list presentations), `DataView.Timeline ## Anatomy +Import and assemble the component: + ```tsx import { DataView, @@ -555,3 +557,22 @@ Start with `isLoading={true}` and fire an initial fetch on mount: with no data a - **Vertical space is not virtualized.** `virtualized` culls horizontally only, so a grouped timeline renders every section's cards that fall in the visible time window. Deep grouping over thousands of rows will render a tall canvas. - **`virtualized`** enables horizontal culling: only cards and gridlines near the viewport render. Recommended whenever the domain is long or rows are numerous. - **Interaction** — cards receive row clicks via the root's `onRowClick`; the background supports mouse drag-to-pan with a momentum glide; scrolling past the domain edge won't trigger browser back-swipe. The pane is a focusable, labelled region (`aria-label`, default "Timeline"), so keyboard users can Tab to it and scroll with the arrow keys. + +## Accessibility + +- `DataView.List` with `variant="table"` renders real table semantics: + `role="table"` on the grid with `rowgroup`, `row`, `columnheader`, and + `cell` on its parts. `variant="list"` uses `role="list"` with `listitem` + rows instead. +- When `onRowClick` is set, each row gets `tabIndex={0}` and activates with + Enter or Space, matching a native button. Rows keep their structural role + (`row`/`listitem`) so cells stay associated with their row, and key presses + bubbling up from interactive children (buttons, links in cells) are ignored + so they don't also trigger row activation. +- Skeleton loader rows are marked `aria-busy="true"`; the infinite-scroll + sentinel and the duplicate sticky group-header anchor are `aria-hidden` so + screen readers don't announce them. +- The Timeline pane is a focusable, labelled `role="region"` (`aria-label`, + default "Timeline") that keyboard users can Tab to and scroll with arrow + keys; the card canvas is a `role="list"` with each card as a `listitem`, + and decorative gridlines, markers, and the axis are `aria-hidden`. diff --git a/apps/www/src/content/docs/components/empty-state/index.mdx b/apps/www/src/content/docs/components/empty-state/index.mdx index fb9706498..f6bca2614 100644 --- a/apps/www/src/content/docs/components/empty-state/index.mdx +++ b/apps/www/src/content/docs/components/empty-state/index.mdx @@ -1,6 +1,6 @@ --- title: Empty State -description: Displays an empty state +description: A placeholder for views with nothing to show yet — pairs an icon and message with optional actions to help users take the next step. source: packages/raystack/components/empty-state --- @@ -8,6 +8,10 @@ import { playground, variantsDemo } from "./demo.ts"; +## Overview + +`EmptyState` fills a view that has no content yet — an empty inbox, zero search results, a feature that needs setup. It pairs a required `icon` with an optional `heading`, `subHeading`, and up to two action slots (`primaryAction`, `secondaryAction`) so users always have a next step. Use the default `empty1` variant for compact, centered placeholders inside panels and lists, and `empty2` for full-page states with left-aligned content and a side-by-side action row. + ## Anatomy Import and assemble the component: @@ -38,7 +42,21 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test | `empty-state-subheading` | The subheading text (when `subHeading` is set) | | `empty-state-actions` | Wrapper around the action buttons (`empty2` variant only) | +## Examples + +### Variants + +`empty1` (the default) centers everything and stacks the actions vertically — suited to panels, tables, and lists. `empty2` left-aligns the content, uses a larger icon, and places both actions in a row — suited to full-page states. + + + ## Accessibility -- Uses semantic HTML elements for proper content structure -- Heading and description are accessible to screen readers +- The heading and subheading render as styled `Text` spans, not real + heading elements, so they don't join the document outline. If the empty + state is the main content of a page, consider passing a real heading + (e.g. `heading={

}`) to keep the outline intact. +- The icon is decorative by default. If it carries meaning on its own, + give it an accessible name; otherwise mark it `aria-hidden`. +- Actions are whatever you pass in — use real `Button`s so keyboard and + screen reader users can reach them. diff --git a/apps/www/src/content/docs/components/flex/index.mdx b/apps/www/src/content/docs/components/flex/index.mdx index deb7c97df..b9a860090 100644 --- a/apps/www/src/content/docs/components/flex/index.mdx +++ b/apps/www/src/content/docs/components/flex/index.mdx @@ -1,6 +1,6 @@ --- title: Flex -description: Component for flexbox +description: A layout primitive that arranges children in a row or column, with props for alignment, spacing, and wrapping. source: packages/raystack/components/flex --- @@ -8,6 +8,10 @@ import { playground, basicDemo } from "./demo.ts"; +## Overview + +`Flex` is the workhorse layout primitive: a `div` with `display: flex` and props for `direction`, `align`, `justify`, `wrap`, and `gap`, so you rarely write flexbox CSS by hand. By default it lays children out in a row (`direction="row"`, `align="stretch"`, `justify="start"`, `wrap="noWrap"`). Reach for it whenever you're stacking or spacing things along one axis — toolbars, form rows, sidebars. For two-dimensional layouts use [Grid](/docs/components/grid), and for a page-width wrapper use [Container](/docs/components/container). + ## Anatomy Import and assemble the component: @@ -36,9 +40,16 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test ### Basic Usage +Nest Flex containers to compose layouts: here an outer row (the default direction) holds two columns, each spaced with `gap`. + ## Accessibility -- Uses semantic HTML for proper document structure -- Supports standard content accessibility patterns +- Renders a plain `
` and adds no roles or ARIA attributes — purely + visual layout with no semantic meaning. +- Screen readers read children in DOM order, so `rowReverse` and + `columnReverse` change only the visual order. Don't rely on them to + convey sequence. +- Use the `render` prop to swap in a semantic element (`