Skip to content

Commit

Permalink
feat(components): add tabs card variant
Browse files Browse the repository at this point in the history
Signed-off-by: ZTL-UwU <zhangtianli2006@163.com>
  • Loading branch information
ZTL-UwU committed Jun 5, 2024
1 parent b20dafd commit d888788
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 103 deletions.
54 changes: 6 additions & 48 deletions components/content/CodeGroup.vue
Original file line number Diff line number Diff line change
@@ -1,55 +1,13 @@
<template>
<UiCard class="[&:not(:first-child)]:mt-5">
<UiScrollArea>
<div class="border-b p-0.5 flex text-sm relative overflow-x-auto">
<div class="flex p-1">
<div
v-for="(slot, i) in ($slots.default?.() ?? [])"
:key="`${i}${slot?.props?.filename}`"
:value="slot?.props?.filename"
class="flex px-3 py-1.5 rounded-md text-muted-foreground transition-all duration-75 cursor-pointer"
:class="[activeTabIndex === i && 'bg-muted text-primary']"
@mousedown.left="activeTabIndex = i"
>
<Icon
v-if="getIcon(slot?.props?.filename, slot?.props?.language)"
:name="getIcon(slot?.props?.filename, slot?.props?.language)!"
class="self-center mr-1.5"
/>
{{ slot?.props?.filename }}
</div>
</div>
<CodeCopy
v-if="selected?.props?.code && selected?.type !== 'preview'"
class="self-center ml-auto mr-3 pl-2"
:code="selected.props.code"
/>
</div>
<ScrollBar orientation="horizontal" />
</UiScrollArea>

<div
v-for="(slot, i) in $slots.default?.() ?? []"
v-show="activeTabIndex === i"
:key="`${i}${slot?.props?.filename}`"
:value="slot?.props?.filename"
class="mt-0"
>
<component :is="slot" :in-group="true" />
</div>
</UiCard>
<render />
</template>

<script setup lang="ts">
import ScrollBar from '../ui/scroll-area/ScrollBar.vue';
const activeTabIndex = ref(0);
const selected = computed(() => {
return useSlots().default?.()[activeTabIndex.value];
});
import Tabs from './Tabs.vue';
const iconMap = new Map(Object.entries(useConfig().value.main.codeIcon));
function getIcon(filename: string, language: string) {
return iconMap.get(filename?.toLowerCase()) || iconMap.get(language);
const _slots = useSlots();
function render() {
const slots = _slots?.default?.() || [];
return h(Tabs, { variant: 'card' }, slots);
}
</script>
14 changes: 0 additions & 14 deletions components/content/Preview.vue

This file was deleted.

83 changes: 76 additions & 7 deletions components/content/Tabs.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,94 @@
<template>
<UiTabs
v-if="variant === 'separate'"
class="[&:not(:first-child)]:mt-5"
:default-value="($slots.default?.() ?? [])[0]?.props?.label"
:default-value="label(($slots.default?.() ?? [])[0]?.props)"
>
<UiTabsList>
<UiTabsTrigger
v-for="(slot, i) in $slots.default?.() ?? []"
:key="`${i}${slot?.props?.label}`"
:value="slot?.props?.label"
:key="`${i}${label(slot.props)}`"
:value="label(slot.props)"
>
<Icon v-if="slot?.props?.icon" :name="slot?.props?.icon" class="mr-1" />
{{ slot?.props?.label }}
<Icon
v-if="icon(slot?.props)"
:name="icon(slot?.props)!"
class="self-center mr-1.5"
/>
{{ label(slot.props) }}
</UiTabsTrigger>
</UiTabsList>

<UiTabsContent
v-for="(slot, i) in $slots.default?.() ?? []"
:key="`${i}${slot?.props?.label}`"
:value="slot?.props?.label"
:key="`${i}${label(slot.props)}`"
:value="label(slot.props)"
>
<component :is="slot" />
</UiTabsContent>
</UiTabs>

<UiCard v-else-if="variant === 'card'" class="[&:not(:first-child)]:mt-5">
<UiScrollArea>
<div class="border-b p-0.5 flex text-sm relative overflow-x-auto">
<div class="flex p-1">
<div
v-for="(slot, i) in ($slots.default?.() ?? [])"
:key="`${i}${label(slot.props)}`"
:value="label(slot.props)"
class="flex px-3 py-1.5 rounded-md text-muted-foreground transition-all duration-75 cursor-pointer"
:class="[activeTabIndex === i && 'bg-muted text-primary']"
@mousedown.left="activeTabIndex = i"
>
<Icon
v-if="icon(slot?.props)"
:name="icon(slot?.props)!"
class="self-center mr-1.5"
/>
{{ label(slot.props) }}
</div>
</div>
<CodeCopy
v-if="$slots.default?.()[activeTabIndex]?.props?.code"
class="self-center ml-auto mr-3 pl-2"
:code="$slots.default?.()[activeTabIndex]?.props?.code"
/>
</div>
<ScrollBar orientation="horizontal" />
</UiScrollArea>

<div
v-for="(slot, i) in $slots.default?.() ?? []"
v-show="activeTabIndex === i"
:key="`${i}${label(slot.props)}`"
:value="label(slot.props)"
class="mt-0"
:class="[padded && ($slots.default?.()[activeTabIndex]?.type as any).tag !== 'pre' && 'p-3']"
>
<component :is="slot" :in-group="true" />
</div>
</UiCard>
</template>

<script setup lang="ts">
import ScrollBar from '../ui/scroll-area/ScrollBar.vue';
withDefaults(defineProps<{
variant?: 'separate' | 'card';
padded?: boolean;
}>(), {
variant: 'separate',
padded: true,
});
const activeTabIndex = ref(0);
const iconMap = new Map(Object.entries(useConfig().value.main.codeIcon));
function icon(props: any) {
return props?.icon || iconMap.get(props?.filename?.toLowerCase()) || iconMap.get(props?.language);
}
function label(props: any) {
return props?.label || props?.filename;
}
</script>
72 changes: 39 additions & 33 deletions content/1.getting-started/3.writing/2.components.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The **Badges** under each component title marks the compatibility with other doc
:badge[Docus]{variant="outline" to="https://docus.dev/api/components#alert" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::alert{icon="lucide:info"}
An **default** alert with `code` and a [link](/).
::
Expand Down Expand Up @@ -78,14 +78,14 @@ The **Badges** under each component title marks the compatibility with other doc

:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/callout" target="_blank"}

`::callout` is an alias to `::alert`.
`::callout`{language="mdc"} is an alias to `::alert`{language="mdc"}.

### Read More

:badge[undocs]{variant="outline" to="https://undocs.pages.dev/guide/components#read-more" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
:read-more{to="/getting-started/writing/markdown"}
:read-more{title="Nuxt website" to="https://nuxt.com/"}
::
Expand All @@ -101,7 +101,7 @@ The **Badges** under each component title marks the compatibility with other doc
:badge[Docus]{variant="outline" to="https://docus.dev/api/components#badge" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::badge
Default
::
Expand Down Expand Up @@ -140,7 +140,7 @@ The **Badges** under each component title marks the compatibility with other doc
:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/code-group" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::code-group
```bash [npm]
npm run dev
Expand All @@ -158,16 +158,6 @@ The **Badges** under each component title marks the compatibility with other doc
bun run dev
```
::

::code-group
::preview{filename="Preview"}
### This is a header
::

```mdc [Code]
### This is a header
```
::
::

```mdc [Code]
Expand All @@ -188,26 +178,20 @@ The **Badges** under each component title marks the compatibility with other doc
bun run dev
```
::
::code-group
::preview{filename="Preview"}
### This is a header
::
```mdc [Code]
### This is a header
```
::
```
::

::alert{to="/getting-started/writing/components#tabs"}
`::code-group`{language="mdc"} is a wrapper around `::tabs{variant="card"}`{language="mdc"}.
::

### Card

:badge[Docus]{variant="outline" to="https://docus.dev/api/components#card" target="_blank"}
:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/card" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::card
#title
Card with slots
Expand Down Expand Up @@ -289,7 +273,7 @@ The **Badges** under each component title marks the compatibility with other doc
:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/card-group" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::card-group
::card
---
Expand Down Expand Up @@ -380,7 +364,7 @@ The icon component uses **Nuxt Icon** under the hood. Check out the usage guide
::

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
<div class="space-x-2">

:icon{name="lucide:box"}
Expand Down Expand Up @@ -410,7 +394,7 @@ npm i -D @iconify-json/collection-name
### Steps

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::steps
### Get Starter Template

Expand Down Expand Up @@ -515,7 +499,7 @@ npm i -D @iconify-json/collection-name
:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/field" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::field{name="Field" type="string" required}
The `description` can be set as prop or in the default slot with full **markdown** support.
::
Expand All @@ -532,7 +516,7 @@ npm i -D @iconify-json/collection-name
:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/field-group" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::field-group
::field{name="validate (path?: string, opts: { silent?: boolean })" type="Promise<T>"}
Triggers form validation. Will raise any errors unless `opts.silent` is set to true.
Expand Down Expand Up @@ -578,7 +562,7 @@ npm i -D @iconify-json/collection-name
:badge[Nuxt UI Pro]{variant="outline" to="https://ui.nuxt.com/pro/prose/tabs" target="_blank"}

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::tabs
::div{label="PostgreSQL" icon="lucide:database"}
### PostgreSQL column types
Expand Down Expand Up @@ -620,6 +604,17 @@ npm i -D @iconify-json/collection-name
```
::
::
::tabs{variant="card"}
::div{label="Card Tab"}
### This is a card-style tab
::
::div{label="Tab 2" icon="lucide:atom"}
This is Tab #2
::
```ts [Code Tab]
console.log('Hello World!');
```
::
::
```mdc [Code]
::tabs
Expand Down Expand Up @@ -663,6 +658,17 @@ npm i -D @iconify-json/collection-name
```
::
::
::tabs{variant="card"}
::div{label="Card Tab"}
### This is a card-style tab
::
::div{label="Tab 2" icon="lucide:atom"}
This is Tab #2
::
```ts [Code Tab]
console.log('Hello World!');
```
::
```
::

Expand All @@ -671,7 +677,7 @@ npm i -D @iconify-json/collection-name
### Hero

::code-group
::preview{filename="Preview"}
::div{label="Preview"}
::hero
---
announcement:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "shadcn-docs-nuxt",
"type": "module",
"version": "0.1.2",
"version": "0.1.3",
"author": "Tony Zhang <zhangtianli2006@gmail.com>",
"license": "MIT",
"homepage": "https://shadcn-docs-nuxt.vercel.app/",
Expand Down

0 comments on commit d888788

Please sign in to comment.