Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions .agents/skills/add-new-component/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,10 @@ packages/raystack/
├── <name>.module.css # Styles
└── __tests__/<name>.test.tsx # Tests

apps/www/src/
├── content/docs/components/<name>/
│ ├── index.mdx # Docs page
│ ├── demo.ts # Code demos
│ └── props.ts # Prop interfaces
└── components/playground/
├── <name>-examples.tsx # Playground example
└── index.ts # Register export
apps/www/src/content/docs/components/<name>/
├── index.mdx # Docs page
├── demo.ts # Code demos + playground
└── props.ts # Prop interfaces
```

## Step 1: Create the Component Source
Expand Down Expand Up @@ -453,39 +449,47 @@ export interface ComponentProps {
- Keep descriptions concise
- Include `className` prop on all sub-component interfaces

## Step 7: Add Playground Example
## Step 7: Add the Interactive Playground

Create `apps/www/src/components/playground/<name>-examples.tsx`:
The playground is a permanent, user-facing feature on the component's docs page — not a dev-time scratch file. It opens a dialog with a live preview of the component, a controls panel, and a live code editor. A reader flips the controls, and both the preview and the code update from `getCode(props)`. Control state is written to the URL, so a configured example is a shareable link. It is rendered by `apps/www/src/components/demo/demo-playground.tsx`; you only supply the `playground` export.

```tsx
Any component with configurable props should have a real playground covering its main props — one control per prop that matters. Add the `playground` export to `demo.ts`:

```ts
'use client';

import { Component, Flex, Text } from '@raystack/apsara';
import PlaygroundLayout from './playground-layout';

export function ComponentExamples() {
return (
<PlaygroundLayout title='Component'>
<Flex direction='column' gap='large'>
<Text>Default:</Text>
<Component>
<Component.Trigger>Toggle</Component.Trigger>
<Component.Panel>Content</Component.Panel>
</Component>
</Flex>
</PlaygroundLayout>
);
}
import type { ComponentPropsType } from '@/components/demo/types';
import { getPropsString } from '@/lib/utils';

export const getCode = (props: ComponentPropsType) =>
`<Component${getPropsString(props)} />`;

export const playground = {
type: 'playground',
controls: {
variant: { type: 'select', options: ['solid', 'outline'], defaultValue: 'solid' },
size: { type: 'select', options: ['small', 'normal'], defaultValue: 'normal' },
disabled: { type: 'checkbox', defaultValue: false },
children: { type: 'text', initialValue: 'Click me' }
},
getCode
};
```

Register in `apps/www/src/components/playground/index.ts` (alphabetical order):
Reference it from `index.mdx`:

```ts
export * from './code-block-examples';
export * from './<name>-examples'; // <-- new
export * from './combobox-examples';
```mdx
import { playground } from "./demo.ts";

<Demo data={playground} />
```

Notes:
- Control types: `select` (`options` + `defaultValue`), `checkbox` (`defaultValue`), `text` (`initialValue`), `icon`.
- One control per prop that changes the component's look or behavior. Cover the real API, not a token subset.
- `getCode` receives the changed props (values that differ from their default) and must return the JSX string for the current setup. Use `getPropsString` to serialize them; pull `children` out and place it between the tags.
- See `button/demo.ts` for a full, real example.

## Step 8: Verify

```bash
Expand All @@ -502,4 +506,4 @@ Checklist:
- [ ] Every rendered element has a `data-slot`, with a `data-slots.test.tsx` covering them
- [ ] CSS uses `--rs-*` tokens only
- [ ] Export in `packages/raystack/index.tsx` in alphabetical order
- [ ] Playground example added and registered
- [ ] Interactive `playground` added to `demo.ts`, covering the component's main props
20 changes: 14 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`
Comment on lines +96 to +108

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language identifier to the directory-tree fence.

markdownlint-cli2 reports MD040 at Line 98. Use a text fence for the directory tree.

Proposed fix
-   ```
+   ```text
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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`
1. Create components in `packages/raystack/components/`
2. Follow the existing component structure:
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 98-98: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.md` around lines 96 - 108, Update the directory-tree code fence
in the contributing guide to specify the text language identifier, changing the
opening fence before the component structure example while leaving the example
content unchanged.

Source: Linters/SAST tools


## Documentation Development

Expand Down Expand Up @@ -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@<commit-sha>
```

## 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:
Expand Down
22 changes: 12 additions & 10 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'
Expand Down Expand Up @@ -253,11 +253,13 @@ 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`)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- CSS files (`dist/style.css`, `dist/normalize.css`)

The package also exports a `./v1` entry point. It is a legacy alias that maps to the same root `dist` files, kept so older `@raystack/apsara/v1` imports keep working.

### Build Configuration

The build process uses:
Expand Down
Loading
Loading