Skip to content
49 changes: 49 additions & 0 deletions .github/contributing/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,55 @@ Configure icons in your Vite config.
::
```

## AI Prompt Blocks (`::prompt`)

Use `::prompt` to surface an AI-assistant prompt alongside an example. Always place it **directly below the `::component-example` it belongs to**, inside the same `###` subsection. Never create a separate top-level `## Prompt` section.

**Correct:**

```md
### Sales dynamics widget

Real-world example: …

::component-example
---
collapse: true
name: 'card-sales-dynamics-example'
---
::

::prompt
---
description: Render a CRM dashboard widget with a few metrics and a highlighted KPI row.
actions:
- copy
- cursor
- windsurf
class: 'w-full my-0'
---
…prompt text…
::
```

**Wrong — standalone section:**

```md
### Sales dynamics widget

::component-example
---
name: 'card-sales-dynamics-example'
---
::

## Prompt ← never do this

::prompt
::
```

## Writing Guidelines

1. **Use sentence case** for headings (not Title Case)
Expand Down
158 changes: 158 additions & 0 deletions docs/app/components/content/examples/card/CardChannelPanelExample.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<script setup lang="ts">
import BellIcon from '@bitrix24/b24icons-vue/main/BellIcon'
import ClockIcon from '@bitrix24/b24icons-vue/outline/ClockIcon'
import UserGroupIcon from '@bitrix24/b24icons-vue/common-b24/UserGroupIcon'
import AiStarsIcon from '@bitrix24/b24icons-vue/outline/AiStarsIcon'
import LinkIcon from '@bitrix24/b24icons-vue/outline/LinkIcon'
import ImageIcon from '@bitrix24/b24icons-vue/outline/ImageIcon'
import TaskListIcon from '@bitrix24/b24icons-vue/outline/TaskListIcon'
import CalendarIcon from '@bitrix24/b24icons-vue/outline/CalendarIcon'
import PlusLIcon from '@bitrix24/b24icons-vue/outline/PlusLIcon'
import PersonPlus2Icon from '@bitrix24/b24icons-vue/crm/PersonPlus2Icon'

const soundEnabled = ref(true)
const autoDeleteEnabled = ref(false)
</script>

<template>
<B24Card
class="w-full max-w-xs overflow-hidden"
:b24ui="{ body: 'p-0 flex flex-col gap-0 divide-y divide-default' }"
>
<!-- Channel header -->
<div class="flex flex-col items-center gap-3 px-4 py-6 text-center">
<B24Avatar
src="/b24ui/avatar/employee.png"
alt="Sales Department"
size="3xl"
:b24ui="{ root: 'rounded-xl' }"
/>
<div>
<p class="font-semibold text-label">
Sales Department
</p>
<p class="text-description text-sm">
Channel
</p>
</div>

<!-- :max="4" with 5 children intentionally shows the +1 overflow counter -->
<div class="flex items-center gap-2">
<B24AvatarGroup :max="4" size="xs">
<B24Avatar src="/b24ui/avatar/employee.png" alt="John Doe" />
<B24Avatar src="/b24ui/avatar/assistant.png" alt="Jane Smith" />
<B24Avatar src="/b24ui/avatar/employee.png" alt="Bob Johnson" />
<B24Avatar src="/b24ui/avatar/assistant.png" alt="Alice Brown" />
<B24Avatar alt="Charlie Davis" />
</B24AvatarGroup>
<B24Button
:icon="PersonPlus2Icon"
label="Add"
color="air-secondary-accent-2"
size="xs"
/>
</div>
</div>

<!-- Toggle rows: icon outside, B24Switch label prop links toggle to text for a11y -->
<div class="py-1">
<div class="flex items-center gap-3 px-4 py-2.5">
<BellIcon class="size-5 shrink-0 text-description" aria-hidden="true" />
<B24Switch
v-model="soundEnabled"
label="Sound"
:b24ui="{
root: 'flex-1 flex-row-reverse justify-between items-center',
wrapper: 'ms-0'
}"
/>
</div>
<div class="px-4 py-2.5">
<div class="flex items-center gap-3">
<ClockIcon class="size-5 shrink-0 text-description" aria-hidden="true" />
<B24Switch
v-model="autoDeleteEnabled"
label="Auto-delete messages"
:b24ui="{
root: 'flex-1 flex-row-reverse justify-between items-center',
wrapper: 'ms-0'
}"
/>
</div>
<!-- spacer (size-5 + gap-3) aligns description under the label -->
<div class="flex gap-3">
<span class="size-5 shrink-0" />
<p class="text-xs text-dimmed mt-1">
{{ autoDeleteEnabled ? 'Messages deleted after 7 days' : 'Disabled' }}
</p>
</div>
</div>
</div>

<!-- Info rows -->
<div class="py-1">
<div class="flex items-center gap-3 px-4 py-2.5">
<UserGroupIcon class="size-5 shrink-0 text-description" aria-hidden="true" />
<span class="flex-1 text-sm text-label">Group chat</span>
</div>
<div class="flex items-center gap-3 px-4 py-2.5">
<AiStarsIcon class="size-5 shrink-0 text-description" aria-hidden="true" />
<span class="flex-1 text-sm text-label">Favorites</span>
<B24Badge :label="0" color="air-secondary-accent" size="xs" square />
</div>
<div class="flex items-center gap-3 px-4 py-2.5">
<LinkIcon class="size-5 shrink-0 text-description" aria-hidden="true" />
<span class="flex-1 text-sm text-label">Links from messages</span>
<B24Badge :label="18" color="air-secondary-accent" size="xs" square />
</div>
</div>

<!-- Media & Files section -->
<div class="py-2">
<h3 class="px-4 py-1 text-xs text-description font-semibold">
Media & Files
</h3>
<B24Empty
:icon="ImageIcon"
title="No media or files"
size="xs"
color="air-tertiary"
:b24ui="{ root: 'ring-0 rounded-none py-3' }"
/>
</div>

<!-- Tasks section -->
<div class="py-2">
<div class="flex items-center justify-between px-4 py-1">
<h3 class="text-xs text-description font-semibold">
Tasks
</h3>
<B24Button :icon="PlusLIcon" label="Add" color="air-secondary-accent-2" size="xs" />
</div>
<B24Empty
:icon="TaskListIcon"
title="No tasks"
size="xs"
color="air-tertiary"
:b24ui="{ root: 'ring-0 rounded-none py-3' }"
/>
</div>

<!-- Meetings section -->
<div class="py-2">
<div class="flex items-center justify-between px-4 py-1">
<h3 class="text-xs text-description font-semibold">
Meetings
</h3>
<B24Button :icon="PlusLIcon" label="Add" color="air-secondary-accent-2" size="xs" />
</div>
<B24Empty
:icon="CalendarIcon"
title="No meetings"
size="xs"
color="air-tertiary"
:b24ui="{ root: 'ring-0 rounded-none py-3' }"
/>
</div>
</B24Card>
</template>
42 changes: 40 additions & 2 deletions docs/content/docs/2.components/card.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ name: 'card-sales-dynamics-example'
---
::

## Prompt

::prompt
---
description: Render a CRM dashboard widget with a few metrics and a highlighted KPI row.
Expand All @@ -165,6 +163,46 @@ Requirements:
- Drive the values from `rows: { label, count, amount }[]` and an optional `highlight: { label, count, amount, info }`. Keep amounts pre-formatted strings to avoid coupling with a money formatter
::

### Channel detail panel

Composed entity sidebar built entirely from standard components: `Card` (with `divide-y` body for automatic section dividers), a square `Avatar`, an `AvatarGroup` with overflow counter, `Switch` toggle rows, `Badge` counters and `Empty` section placeholders. Use it as a starting point for chat channel info panels or CRM record details.

::component-example
---
collapse: true
name: 'card-channel-panel-example'
---
::

Generate this layout with your AI assistant. The prompt asks the assistant to confirm the entity type and which sections you need before writing any code:

::prompt
---
description: Build a Bitrix24-style entity detail sidebar from standard components.
actions:
- copy
- cursor
- windsurf
class: 'w-full my-0'
---
You are a Bitrix24 UI expert. Help me build an entity detail sidebar (info panel) using only standard `@bitrix24/b24ui-nuxt` components, with minimal custom styling.

Before writing any code, ask me clarifying questions and wait for my answers:
- What entity is this panel for (chat channel, CRM contact/deal, project, something else)?
- Which header info should it show (avatar shape, title, subtitle, member group)?
- Which toggle settings do I need (e.g. notifications, auto-delete) and their default state?
- Which info rows and counters should appear (and which need a badge)?
- Which content sections do I need (e.g. Media & Files, Tasks, Meetings) and what is their empty state?

Once I confirm, build it with these conventions:
- Wrap everything in a `B24Card` with `class="w-full max-w-xs overflow-hidden"` and `:b24ui="{ body: 'p-0 flex flex-col gap-0 divide-y divide-default' }"` so each child section is auto-divided
- Square the channel avatar with `B24Avatar :b24ui="{ root: 'rounded-xl' }"`; show members with `B24AvatarGroup :max="N"` plus one extra child to render the `+1` counter
- For toggle rows, put the icon outside and use `B24Switch` with the `label` prop for accessibility, reversing layout via `:b24ui="{ root: 'flex-1 flex-row-reverse justify-between items-center', wrapper: 'ms-0' }"`
- Use `B24Badge ... square` for numeric counters on info rows
- Use `B24Empty` for section empty states, flattened with `:b24ui="{ root: 'ring-0 rounded-none py-3' }"`
- Use semantic text tokens (`text-label`, `text-description`, `text-dimmed`) and `<h3>` for section headings
::

## API

### Props
Expand Down
7 changes: 7 additions & 0 deletions docs/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,13 @@ export default defineNuxtConfig({
'@bitrix24/b24icons-vue/outline/OpenChatIcon',
'@bitrix24/b24icons-vue/button/PageIcon',
'@bitrix24/b24icons-vue/outline/TaskListIcon',
'@bitrix24/b24icons-vue/main/BellIcon',
'@bitrix24/b24icons-vue/outline/ClockIcon',
'@bitrix24/b24icons-vue/common-b24/UserGroupIcon',
'@bitrix24/b24icons-vue/outline/ImageIcon',
'@bitrix24/b24icons-vue/outline/CalendarIcon',
'@bitrix24/b24icons-vue/outline/PlusLIcon',
'@bitrix24/b24icons-vue/crm/PersonPlus2Icon',
'@bitrix24/b24icons-vue/common-service/CodeIcon',
'@bitrix24/b24icons-vue/actions/BrushIcon',
'@bitrix24/b24icons-vue/main/EarthLanguageIcon',
Expand Down
Loading