Skip to content
Open
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
2 changes: 1 addition & 1 deletion .agents/skills/apsara/references/composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ import { Select } from "@raystack/apsara";
```

- Put `placeholder` on `Select.Value`, not the trigger.
- `Select.Item` supports `leadingIcon`; `disabled` marks unavailable rows.
- `Select.Item` supports `leadingIcon` and `trailingIcon`; `disabled` marks unavailable rows.
- Sub-parts: `Select.Trigger`, `Select.Value`, `Select.Content`, `Select.Item`, `Select.Group`, `Select.Label`, `Select.Separator`, `Select.List`.

## Menu / ContextMenu
Expand Down
41 changes: 41 additions & 0 deletions apps/www/src/content/docs/(overview)/upgrading.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,47 @@ One section per release, newest first, with only the changes that need action
from you. The full record of every release, features and fixes included, is
on [GitHub releases](https://github.com/raystack/apsara/releases).

## Unreleased: icon props are `leadingIcon` and `trailingIcon`

An icon before or after the content is set with `leadingIcon` or
`trailingIcon`, and each leading icon has a `<part>-leading-icon` slot.

### 1. Rename the icon props

| Component | Before | After |
| --- | --- | --- |
| `Badge` | `icon` | `leadingIcon` |
| `Callout` | `icon` | `leadingIcon` |
| `SidePanel.Header` | `icon` | `leadingIcon` |
| `DataView` fields (`DataViewField`) | `icon` | `leadingIcon` |
| `Editor.SlashMenu` items (`EditorSlashItem`) | `icon` | `leadingIcon` |
| `Editor.Mentions` and `PromptInput.Mentions` items | `icon`, `trailing` | `leadingIcon`, `trailingIcon` |

```tsx
// Before
<Badge icon={<StarIcon />}>New</Badge>
<Callout icon={null}>Saved</Callout>
const items = [{ id: 'ada', label: 'Ada', icon: <Avatar />, trailing: <Badge>Agent</Badge> }];

// After
<Badge leadingIcon={<StarIcon />}>New</Badge>
<Callout leadingIcon={null}>Saved</Callout>
const items = [{ id: 'ada', label: 'Ada', leadingIcon: <Avatar />, trailingIcon: <Badge>Agent</Badge> }];
```

### 2. Update `data-slot` selectors

| Before | After |
| --- | --- |
| `announcement-bar-icon` | `announcement-bar-leading-icon` |
| `badge-icon` | `badge-leading-icon` |
| `callout-icon` | `callout-leading-icon` |
| `chat-jump-button-icon` | `chat-jump-button-leading-icon` |
| `combobox-item-icon` | `combobox-item-leading-icon` |
| `select-item-icon` | `select-item-leading-icon` |
| `select-value-icon` | `select-value-leading-icon` |
| `tabs-tab-icon` | `tabs-tab-leading-icon` |

## Unreleased: date filters compare whole days

`DataView`, `DataTable` and `FilterChip` read and compare dates as calendar
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/ai-elements/chat/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| `chat-separator` | Divider between messages |
| `chat-composer` | The input area below the list |
| `chat-jump-button` | "Jump to latest" button |
| `chat-jump-button-icon` | Icon inside that button |
| `chat-jump-button-leading-icon` | Leading icon inside that button (unless `leadingIcon` is `null`) |
| `chat-attachment` | An attachment card |
| `chat-attachment-media` | Its thumbnail or preview |
| `chat-attachment-body` | Its text column |
Expand Down
22 changes: 11 additions & 11 deletions apps/www/src/content/docs/ai-elements/prompt-input/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,54 +138,54 @@ export const editorCapabilitiesDemo = {
id: 'page',
label: 'This page',
type: 'page',
icon: <FileTextIcon />,
leadingIcon: <FileTextIcon />,
data: { path: '/docs/ai-elements/prompt-input' }
},
{
id: 'button',
label: 'Button',
type: 'component',
group: 'Components',
icon: <Component size={16} strokeWidth={1.5} />,
leadingIcon: <Component size={16} strokeWidth={1.5} />,
data: { status: 'stable' }
},
{
id: 'data-table',
label: 'DataTable',
type: 'component',
group: 'Components',
icon: <Component size={16} strokeWidth={1.5} />,
leadingIcon: <Component size={16} strokeWidth={1.5} />,
data: { status: 'stable' }
},
{
id: 'prompt-input',
label: 'PromptInput',
type: 'component',
group: 'Components',
icon: <Component size={16} strokeWidth={1.5} />,
leadingIcon: <Component size={16} strokeWidth={1.5} />,
data: { status: 'beta' }
},
{
id: 'u1',
label: 'Maya Chen',
type: 'user',
group: 'Users',
icon: <Avatar size={1} fallback="M" />
leadingIcon: <Avatar size={1} fallback="M" />
},
{
id: 'u2',
label: 'Apsara Assistant',
type: 'user',
group: 'Users',
icon: <Avatar size={1} fallback="A" />,
trailing: <Badge size="micro" variant="neutral">Agent</Badge>
leadingIcon: <Avatar size={1} fallback="A" />,
trailingIcon: <Badge size="micro" variant="neutral">Agent</Badge>
},
{
id: 'u3',
label: 'Dana Whitfield',
type: 'user',
group: 'Users',
icon: <Avatar size={1} fallback="D" />,
leadingIcon: <Avatar size={1} fallback="D" />,
disabled: true
}
];
Expand Down Expand Up @@ -240,7 +240,7 @@ export const editorCapabilitiesDemo = {
id: 'data-table',
label: 'DataTable',
type: 'component',
icon: <Component size={16} strokeWidth={1.5} />,
leadingIcon: <Component size={16} strokeWidth={1.5} />,
data: { status: 'stable' }
})
}
Expand Down Expand Up @@ -309,7 +309,7 @@ export const mentionsDemo = {
label: 'Apsara Assistant',
type: 'user',
group: 'Users',
trailing: <Badge size="micro" variant="neutral">Agent</Badge>
trailingIcon: <Badge size="micro" variant="neutral">Agent</Badge>
},
{ id: 'u3', label: 'Dana Whitfield', type: 'user', group: 'Users' }
];
Expand Down Expand Up @@ -427,7 +427,7 @@ export const insertMentionDemo = {
id: 'prompt-input',
label: 'PromptInput',
type: 'component',
icon: <Component size={16} strokeWidth={1.5} />
leadingIcon: <Component size={16} strokeWidth={1.5} />
})
}
>
Expand Down
6 changes: 3 additions & 3 deletions apps/www/src/content/docs/ai-elements/prompt-input/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ export interface PromptInputMentionItem {
*/
type?: string;

icon?: React.ReactNode;
leadingIcon?: React.ReactNode;

/** Shown at the end of the row — a badge, a shortcut, a timestamp. */
trailing?: React.ReactNode;
trailingIcon?: React.ReactNode;

/** Section heading. Sections appear in the order they first show up. */
group?: string;
Expand Down Expand Up @@ -190,7 +190,7 @@ export interface PromptInputMentionsProps {
) => Promise<PromptInputMentionItem[]>;

/**
* Looks up the icon, trailing content and `data` for chips restored from
* Looks up the leading icon, trailing icon and `data` for chips restored from
* `value` / `defaultValue`, which can't carry them, and refreshes their
* labels. Calls are batched and cached.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| Slot | Element |
|------|---------|
| `announcement-bar` | The root `<div>` element |
| `announcement-bar-icon` | Wrapper around the leading icon (when `leadingIcon` is set) |
| `announcement-bar-leading-icon` | Wrapper around the leading icon (when `leadingIcon` is set) |
| `announcement-bar-text` | The main text |
| `announcement-bar-action` | The action `<button>` (when `actionLabel` or `actionIcon` is set) |
| `announcement-bar-action-label` | The action button's text label |
Expand Down
8 changes: 4 additions & 4 deletions apps/www/src/content/docs/components/badge/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const playground = {
options: ['micro', 'small', 'regular'],
defaultValue: 'small'
},
icon: {
leadingIcon: {
type: 'icon'
},
screenReaderText: {
Expand Down Expand Up @@ -69,9 +69,9 @@ export const iconDemo = {
type: 'code',
code: `
<Flex gap={5}>
<Badge icon={<Home size="16"/>}>Badge</Badge>
<Badge icon={<Laugh size="16"/>}>Badge</Badge>
<Badge icon="🔥">Badge</Badge>
<Badge leadingIcon={<Home size="16"/>}>Badge</Badge>
<Badge leadingIcon={<Laugh size="16"/>}>Badge</Badge>
<Badge leadingIcon="🔥">Badge</Badge>
</Flex>`
};

Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/badge/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| Slot | Element |
|------|---------|
| `badge` | The root `<span>` element |
| `badge-icon` | Wrapper around `icon` (when set) |
| `badge-leading-icon` | Wrapper around `leadingIcon` (when set) |
| `badge-screen-reader-text` | Visually hidden text (when `screenReaderText` is set) |

## Accessibility
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/badge/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface BadgeProps {
size?: 'micro' | 'small' | 'regular';

/** Optional ReactNode to display an icon before the text */
icon?: React.ReactNode;
leadingIcon?: React.ReactNode;

/** Additional text content only announced to screen readers */
screenReaderText?: string;
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/callout/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const playground = {
type: 'text',
initialValue: 'A short message'
},
icon: {
leadingIcon: {
type: 'icon'
},
variant: {
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/callout/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| `callout` | The main callout `<div>` (role `status`, or `alert` for the alert type) |
| `callout-container` | Wrapper `<div>` holding the message and actions |
| `callout-message-container` | Wrapper `<div>` around the icon and message |
| `callout-icon` | Wrapper around the icon (when an icon is set) |
| `callout-leading-icon` | Wrapper around the leading icon (unless `leadingIcon` is `null`) |
| `callout-message` | Wrapper around the message content |
| `callout-actions` | Wrapper `<div>` for the action and dismiss button |
| `callout-action` | Wrapper around the action (when an action is provided) |
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/callout/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface CalloutProps {
* Custom leading icon
* @defaultValue InfoIcon
*/
icon?: React.ReactNode;
leadingIcon?: React.ReactNode;

/**
* Called when the dismiss button is clicked. When provided, the consumer owns
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/combobox/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const iconDemo = {
<Combobox.Content>
<Combobox.Item value="apple" leadingIcon={<Info size={16} />}>Apple</Combobox.Item>
<Combobox.Item value="banana" leadingIcon={<X size={16} />}>Banana</Combobox.Item>
<Combobox.Item value="grape" leadingIcon={<Home size={16} />}>Grape</Combobox.Item>
<Combobox.Item value="grape" leadingIcon={<Home size={16} />} trailingIcon={<ExternalLink size={16} />}>Grape</Combobox.Item>
<Combobox.Item value="orange" leadingIcon={<Laugh size={16} />}>Orange</Combobox.Item>
</Combobox.Content>
</Combobox>`
Expand Down
5 changes: 3 additions & 2 deletions apps/www/src/content/docs/components/combobox/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ A simple combobox with search filtering built in. Type to filter options.

### With icons

You can pass the `leadingIcon` prop to `Combobox.Item` to display icons before item text.
Pass `leadingIcon` or `trailingIcon` to `Combobox.Item` to show an icon before or after the item text.

<Demo data={iconDemo} />

Expand Down Expand Up @@ -147,7 +147,8 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| `combobox-separator` | The divider between items or groups |
| `combobox-item` | A selectable option row |
| `combobox-item-text` | The text label inside an item (when its children is a string) |
| `combobox-item-icon` | The leading icon inside an item (when `leadingIcon` is set) |
| `combobox-item-leading-icon` | The leading icon inside an item (when `leadingIcon` is set) |
| `combobox-item-trailing-icon` | The trailing icon inside an item (when `trailingIcon` is set) |

## Accessibility

Expand Down
3 changes: 3 additions & 0 deletions apps/www/src/content/docs/components/combobox/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ export interface ComboboxItemProps {
/** Leading icon to display before the item text. */
leadingIcon?: React.ReactNode;

/** Trailing icon to display after the item text. */
trailingIcon?: React.ReactNode;

/** Additional CSS class names. */
className?: string;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/editor/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export const slashItemsDemo = {
label: "Today's date",
group: 'Insert',
keywords: ['today', 'time'],
icon: <CalendarIcon />,
leadingIcon: <CalendarIcon />,
run: editor => editor.commands.insertText(new Date().toLocaleDateString())
}
];
Expand Down
8 changes: 4 additions & 4 deletions apps/www/src/content/docs/components/editor/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export interface EditorMentionsProps {
) => Promise<EditorMentionItem[]>;

/**
* Fills in the icon, trailing content and label of chips loaded from
* Fills in the leading icon, trailing icon and label of chips loaded from
* `value` or `defaultValue`.
*/
resolveMentions?: (
Expand Down Expand Up @@ -261,9 +261,9 @@ export interface EditorMentionItem {
* @defaultValue "mention"
*/
type?: string;
icon?: React.ReactNode;
leadingIcon?: React.ReactNode;
/** Trailing content on the row and the chip. */
trailing?: React.ReactNode;
trailingIcon?: React.ReactNode;
/** Section heading. Sections render in first-appearance order. */
group?: string;
disabled?: boolean;
Expand All @@ -276,7 +276,7 @@ export interface EditorSlashItem {
label: string;
/** Shown under the label. The filter matches it at the start of a word. */
description?: string;
icon?: React.ReactNode;
leadingIcon?: React.ReactNode;
/** Section heading. Sections keep the order they are declared in. */
group?: string;
/** Extra words the filter matches. */
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/select/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const iconDemo = {
<Select.Content>
<Select.Item value="apple" leadingIcon={<Info size={16} />}>Apple</Select.Item>
<Select.Item value="banana" leadingIcon={<X size={16} />}>Banana</Select.Item>
<Select.Item value="grape" leadingIcon={<Home size={16} />}>Grape</Select.Item>
<Select.Item value="grape" leadingIcon={<Home size={16} />} trailingIcon={<ExternalLink size={16} />}>Grape</Select.Item>
<Select.Item value="Orange" leadingIcon={<Laugh size={16} />}>Orange</Select.Item>
</Select.Content>
</Select>`
Expand Down
7 changes: 4 additions & 3 deletions apps/www/src/content/docs/components/select/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ A trigger and a list of items. `Select.Value` renders the current selection in t

### Icon

You can pass `leadingIcon` prop to Select.Item to include items
Pass `leadingIcon` or `trailingIcon` to `Select.Item` to show an icon before or after the item text.

<Demo data={iconDemo} />

Expand Down Expand Up @@ -152,7 +152,7 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| `select-trigger-icon` | The chevron dropdown icon in the trigger |
| `select-value` | The `<span>` (or wrapper) showing the selected value or placeholder |
| `select-value-content` | Inner wrapper around a single selected value |
| `select-value-icon` | Leading icon of the selected value (when set) |
| `select-value-leading-icon` | Leading icon of the selected value (when set) |
| `select-value-overflow` | The "+N" overflow count for multiple values (when they don't all fit) |
| `select-positioner` | The floating positioner for the popup |
| `select-content` | The popup container |
Expand All @@ -162,8 +162,9 @@ Every rendered part carries a stable `data-slot` attribute for [styling and test
| `select-label` | The label of a group |
| `select-separator` | A divider between items or groups |
| `select-item` | An individual option row |
| `select-item-icon` | Leading icon on an item (when set) |
| `select-item-leading-icon` | Leading icon on an item (when set) |
| `select-item-text` | The text label of an item |
| `select-item-trailing-icon` | Trailing icon on an item (when set) |

## Accessibility

Expand Down
6 changes: 6 additions & 0 deletions apps/www/src/content/docs/components/select/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ export interface SelectItemProps {
/** The value of the item. */
value: string;

/** Icon before the item text. */
leadingIcon?: React.ReactNode;

/** Icon after the item text. */
trailingIcon?: React.ReactNode;

/** Additional CSS class names. */
className?: string;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/sidepanel/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const preview = {
code: `
<Flex style={{ gap: '24px', flexWrap: 'wrap' }}>
<SidePanel side="right">
<SidePanel.Header title="Right Side Panel" icon={<Avatar fallback="A" />} description="This is a description." actions={[<Button>Action</Button>]} />
<SidePanel.Header title="Right Side Panel" leadingIcon={<Avatar fallback="A" />} description="This is a description." actions={[<Button>Action</Button>]} />
<SidePanel.Section>
<List>
<List.Header>User Information</List.Header>
Expand Down
2 changes: 1 addition & 1 deletion apps/www/src/content/docs/components/sidepanel/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface SidePanelHeaderProps {
/**
* Optional icon element to display before the title.
*/
icon?: React.ReactNode;
leadingIcon?: React.ReactNode;

/**
* Array of action elements to display in the header.
Expand Down
Loading
Loading