Skip to content

Commit facd76c

Browse files
authored
feat(layer): enhance MDC tabs with icons, type safety, and accessibility (#6)
* feat(layer): implement MDC tabs component with Nuxt UI style - Add reference submodules: nuxt/content, nuxt-content/mdc, nuxt/ui - Implement Tabs and TabsItem content components for MDC syntax - Add MDC component mapping in nuxt.config.ts - Update UPageCard to apply padding on default slot - Update index.md to use new ::tabs-item MDC syntax - Update ref-analysis.md with Nuxt Content, MDC, and Nuxt UI analysis - Add MDC component mapping documentation BREAKING CHANGE: Tabs now use ::tabs-item{label="..."} syntax instead of ::tabs-list/::tabs-trigger/::tabs-content * feat(layer): enhance MDC tabs with icons, type safety, and accessibility - Fix index bug in slot transformation for fragment handling - Add icon prop support with aria-hidden for accessibility - Replace any types with VNode for type safety - Update documentation for new ::tabs-item API - Add aria-hidden to UPageCard decorative icons
1 parent 770cb12 commit facd76c

17 files changed

Lines changed: 504 additions & 177 deletions

File tree

.gitmodules

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,12 @@
77
[submodule "ref/docus"]
88
path = ref/docus
99
url = https://github.com/nuxt-content/docus
10+
[submodule "ref/content"]
11+
path = ref/content
12+
url = https://github.com/nuxt/content
13+
[submodule "ref/mdc"]
14+
path = ref/mdc
15+
url = https://github.com/nuxt-content/mdc
16+
[submodule "ref/ui"]
17+
path = ref/ui
18+
url = https://github.com/nuxt/ui

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ export default defineNuxtConfig({
8989
})
9090
```
9191

92+
## References
93+
94+
- [Nuxt Content Markdown Documentation](https://content.nuxt.com/raw/docs/files/markdown.md)
95+
- [MDC Prose Components](https://github.com/nuxt-content/mdc/tree/main/src/runtime/components/prose)
96+
9297
## ESLint
9398

9499
Uses `@antfu/eslint-config` with Vue and formatters enabled.

apps/docs/content/docs/2.components/6.tabs.md

Lines changed: 111 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,41 @@ description: Tabbed content sections for organizing related content
55

66
# Tabs
77

8-
A component system for creating tabbed content sections. Useful for showing multiple code examples, alternative approaches, or organizing related content.
8+
A component for creating tabbed content sections. Useful for showing multiple code examples, alternative approaches, or organizing related content.
99

1010
## Usage
1111

12-
Create tabs using the `::tabs`, `::tabs-list`, `::tabs-trigger`, and `::tabs-content` components:
12+
Create tabs using the `::tabs` and `::tabs-item` components:
1313

1414
```mdc
15-
::tabs{default-value="tab1"}
16-
::tabs-list
17-
::tabs-trigger{value="tab1"}
18-
First Tab
19-
::
20-
::tabs-trigger{value="tab2"}
21-
Second Tab
22-
::
23-
::
24-
25-
::tabs-content{value="tab1"}
15+
::tabs
16+
::tabs-item{label="First Tab"}
2617
Content for the first tab.
2718
::
2819
29-
::tabs-content{value="tab2"}
20+
::tabs-item{label="Second Tab"}
3021
Content for the second tab.
3122
::
3223
::
3324
```
3425

35-
::tabs{default-value="tab1"}
36-
::tabs-list
37-
::tabs-trigger{value="tab1"}
38-
First Tab
39-
::
40-
::tabs-trigger{value="tab2"}
41-
Second Tab
42-
::
43-
::
44-
45-
::tabs-content{value="tab1"}
46-
Content for the first tab.
47-
::
26+
::tabs
27+
::tabs-item{label="First Tab"}
28+
Content for the first tab.
29+
::
4830

49-
::tabs-content{value="tab2"}
50-
Content for the second tab.
51-
::
31+
::tabs-item{label="Second Tab"}
32+
Content for the second tab.
33+
::
5234
::
5335

5436
## Code Examples
5537

5638
Tabs are useful for showing code in different languages or frameworks:
5739

5840
```mdc
59-
::tabs{default-value="vue"}
60-
::tabs-list
61-
::tabs-trigger{value="vue"}
62-
Vue
63-
::
64-
::tabs-trigger{value="react"}
65-
React
66-
::
67-
::
68-
69-
::tabs-content{value="vue"}
41+
::tabs
42+
::tabs-item{label="Vue"}
7043
\`\`\`vue
7144
<script setup>
7245
const count = ref(0)
@@ -78,7 +51,7 @@ Tabs are useful for showing code in different languages or frameworks:
7851
\`\`\`
7952
::
8053
81-
::tabs-content{value="react"}
54+
::tabs-item{label="React"}
8255
\`\`\`tsx
8356
function Counter() {
8457
const [count, setCount] = useState(0)
@@ -89,80 +62,124 @@ Tabs are useful for showing code in different languages or frameworks:
8962
::
9063
```
9164

92-
::tabs{default-value="vue"}
93-
::tabs-list
94-
::tabs-trigger{value="vue"}
95-
Vue
96-
::
97-
::tabs-trigger{value="react"}
98-
React
99-
::
100-
::
65+
::tabs
66+
::tabs-item{label="Vue"}
10167

102-
::tabs-content{value="vue"}
68+
```vue
69+
<script setup>
70+
const count = ref(0)
71+
</script>
72+
73+
<template>
74+
<button @click="count++">
75+
{{ count }}
76+
</button>
77+
</template>
78+
```
10379

104-
```vue
105-
<script setup>
106-
const count = ref(0)
107-
</script>
80+
::
10881

109-
<template>
110-
<button @click="count++">
111-
{{ count }}
112-
</button>
113-
</template>
114-
```
82+
::tabs-item{label="React"}
11583

84+
```tsx
85+
function Counter() {
86+
const [count, setCount] = useState(0)
87+
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
88+
}
89+
```
90+
91+
::
11692
::
11793

118-
::tabs-content{value="react"}
94+
## Package Manager Example
11995

120-
```tsx
121-
function Counter() {
122-
const [count, setCount] = useState(0)
123-
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
124-
}
125-
```
96+
Use the `sync` prop to remember the user's choice across tabs:
12697

98+
```mdc
99+
::tabs{sync="pm"}
100+
::tabs-item{label="npm"}
101+
\`\`\`bash
102+
npm install @pleaseai/docs
103+
\`\`\`
104+
::
105+
106+
::tabs-item{label="pnpm"}
107+
\`\`\`bash
108+
pnpm add @pleaseai/docs
109+
\`\`\`
110+
::
111+
112+
::tabs-item{label="bun"}
113+
\`\`\`bash
114+
bun add @pleaseai/docs
115+
\`\`\`
116+
::
127117
::
128-
::
118+
```
129119

130-
## Components
120+
::tabs{sync="pm"}
121+
::tabs-item{label="npm"}
131122

132-
### Tabs
123+
```bash
124+
npm install @pleaseai/docs
125+
```
133126

134-
The root container for the tab system.
127+
::
128+
129+
::tabs-item{label="pnpm"}
130+
131+
```bash
132+
pnpm add @pleaseai/docs
133+
```
135134

136-
| Prop | Type | Default | Description |
137-
| --------------- | -------- | ------- | -------------------------- |
138-
| `default-value` | `string` | - | Initially active tab value |
139-
| `class` | `string` | - | Additional CSS classes |
135+
::
136+
137+
::tabs-item{label="bun"}
138+
139+
```bash
140+
bun add @pleaseai/docs
141+
```
142+
143+
::
144+
::
145+
146+
## With Icons
147+
148+
Add icons to tab triggers using the `icon` prop:
140149

141-
### TabsList
150+
```mdc
151+
::tabs
152+
::tabs-item{label="Vue" icon="i-logos-vue"}
153+
Vue content here.
154+
::
142155
143-
Container for tab triggers/buttons.
156+
::tabs-item{label="React" icon="i-logos-react"}
157+
React content here.
158+
::
159+
::
160+
```
144161

145-
| Prop | Type | Default | Description |
146-
| ------- | -------- | ------- | ---------------------- |
147-
| `class` | `string` | - | Additional CSS classes |
162+
## Components
148163

149-
### TabsTrigger
164+
### Tabs
150165

151-
Individual tab button.
166+
The root container for the tab system.
152167

153-
| Prop | Type | Default | Description |
154-
| ------- | -------- | ------------ | ----------------------------- |
155-
| `value` | `string` | **required** | Unique identifier for the tab |
156-
| `class` | `string` | - | Additional CSS classes |
168+
| Prop | Type | Default | Description |
169+
| -------------- | -------- | ------- | ---------------------------------------------------- |
170+
| `defaultIndex` | `number` | `0` | Initially active tab index (0-based) |
171+
| `sync` | `string` | - | Sync tab selection across tabs with this key via localStorage |
172+
| `class` | `string` | - | Additional CSS classes |
157173

158-
### TabsContent
174+
### TabsItem
159175

160-
Content panel for each tab.
176+
Individual tab content panel with its trigger label.
161177

162-
| Prop | Type | Default | Description |
163-
| ------- | -------- | ------------ | ------------------------------ |
164-
| `value` | `string` | **required** | Must match a TabsTrigger value |
165-
| `class` | `string` | - | Additional CSS classes |
178+
| Prop | Type | Default | Description |
179+
| ------- | -------- | ------------ | ---------------------------------- |
180+
| `label` | `string` | **required** | The label displayed in the tab trigger |
181+
| `icon` | `string` | - | Optional icon name for the tab |
182+
| `class` | `string` | - | Additional CSS classes |
166183

167184
## Styling
168185

apps/docs/content/index.md

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,38 +57,30 @@ Ship fast, flexible, and SEO-optimized documentation with beautiful design out o
5757
::::u-page-card
5858
---
5959
spotlight: true
60-
class: col-span-1 lg:col-span-2
60+
class: col-span-2
6161
---
62-
:::::tabs{default-value="preview"}
63-
::::::tabs-list
64-
:::::::tabs-trigger{value="preview"}
65-
Preview
66-
:::::::
67-
:::::::tabs-trigger{value="code"}
68-
Code
69-
:::::::
70-
::::::
71-
::::::tabs-content{value="preview"}
72-
:::::::div{class="flex flex-col gap-4"}
73-
::::::::note{class="my-0"}
74-
Here's some additional information for you.
75-
::::::::
76-
77-
::::::::tip{class="my-0"}
78-
Here's a helpful suggestion.
79-
::::::::
80-
81-
::::::::warning{class="my-0"}
82-
Be careful with this action as it might have unexpected results.
83-
::::::::
84-
85-
::::::::caution{class="my-0"}
86-
This action cannot be undone.
87-
::::::::
88-
:::::::
62+
:::::tabs
63+
::::::tabs-item{label="Preview" icon="lucide:eye" class="mt-5"}
64+
:::::::div{class="flex flex-col gap-4"}
65+
::::::::note{class="my-0"}
66+
Here's some additional information for you.
67+
::::::::
68+
69+
::::::::tip{class="my-0"}
70+
Here's a helpful suggestion.
71+
::::::::
72+
73+
::::::::warning{class="my-0"}
74+
Be careful with this action as it might have unexpected results.
75+
::::::::
76+
77+
::::::::caution{class="my-0"}
78+
This action cannot be undone.
79+
::::::::
80+
:::::::
8981
::::::
9082

91-
::::::tabs-content{value="code" class="text-sm overflow-x-auto"}
83+
::::::tabs-item{label="Code" icon="lucide:code" class="mt-5 mb-2 text-xs overflow-x-auto"}
9284
```mdc
9385
::note
9486
Here's some additional information.

bun.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)