Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
5 changes: 5 additions & 0 deletions .changeset/bright-docs-primitives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": minor
---

Add reusable ComponentExample, ApiTable, and PageHeader primitives for documentation interfaces.
5 changes: 5 additions & 0 deletions .changeset/calm-containers-toggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": minor
---

Add Container, Section, and ThemeToggle components for unified responsive page layouts and ready-to-use theme toggles.
5 changes: 5 additions & 0 deletions .changeset/calm-markdown-renderer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": minor
---

Add Markdown rendering system with GFM, TOC heading extraction, Shiki code blocks, and documentation directive extensions.
5 changes: 5 additions & 0 deletions .changeset/calm-shiki-pipeline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": patch
---

Reuse one process-wide Shiki highlighting pipeline during Nuxt SSR and prerendering while retaining on-demand grammar loading.
18 changes: 9 additions & 9 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
5 changes: 5 additions & 0 deletions .changeset/fair-inline-code-wraps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": patch
---

Wrap long InlineCode values into independently decorated line fragments in narrow containers instead of overflowing or leaving trailing background space.
5 changes: 5 additions & 0 deletions .changeset/green-search-inputs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": minor
---

Add SearchInput and SearchBox components with debounced querying, clearable input, loading state, shortcuts, and suggestions flyout.
5 changes: 5 additions & 0 deletions .changeset/lazy-code-blocks-improve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@recloudstudio/ui": minor
---

Expand CodeBlock language support with on-demand syntax loading, resilient retries, accessible scrolling, adaptive line numbers, and smoother collapsed and height-limited states.
22 changes: 18 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,25 @@ Read only the standard required for the current work; do not preload all three t

## Verification

- For a library-only change, run `bun run --cwd packages/ui typecheck`, `bun run --cwd packages/ui test`, and `bun run --cwd packages/ui build`.
- For component, export, Nuxt-module, or documentation changes, also run `bun run --cwd apps/playground build`.
### Mandatory pre-commit gate

**Before every `git commit` or push, run the complete verification sequence from the repository root. Do not skip a command because a subset was run earlier, and do not commit or push when any command fails.**

1. Run `bun run format`. This command writes formatting changes; inspect and intentionally include or revert every resulting diff before continuing.
2. Run `git diff --check`.
3. Run `bun run lint`.
4. Run `bun run typecheck`.
5. Run `bun run test`.
6. Run `bun run build`.
7. Run `bun run ci` as the final aggregate gate, even though it repeats lint, typecheck, test, and build.

For changes that affect component rendering, exports, the Nuxt module, Playground configuration, documentation pages, or static routes, also run `bun run --cwd apps/playground generate` after the mandatory gate. Stop any Playground dev server first because it holds `apps/playground/.nuxt`.

Record the commands and their passing results in the handoff, PR, or final status report. If a formatter, build, test, or validation command changes files, repeat every affected verification command before committing.

- `bun run ci` is the full workspace gate: `lint`, `typecheck`, `test`, then `build`. It does not replace the explicit commands above; the redundancy is intentional.
- Biome intentionally excludes `.vue` files, so do not treat a passing root lint as Vue validation. The Playground build/generate gate provides the required Vue and Nuxt coverage.
- Put `--cwd` after `run`. Bun 1.4.2 treats `bun --cwd <dir> run <script>` as `bun run` with no script: it prints usage and exits 0, so the check silently passes without running anything.
- The Playground build refuses to run while a Nuxt dev server holds `apps/playground/.nuxt`; stop the dev server first.
- `bun run ci` is the full workspace gate. Biome intentionally excludes `.vue` files, so do not treat a passing root lint as Vue validation.

## Component Delivery

Expand Down
124 changes: 47 additions & 77 deletions apps/playground/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,42 @@
<ToastProvider />
<PreviewBanner />
<div class="min-h-screen flex flex-col bg-slate-50 dark:bg-[#090E17] text-slate-700 dark:text-slate-200 transition-colors">
<!-- 顶部导航栏 -->
<header class="sticky top-0 z-40 border-b border-slate-200/80 dark:border-slate-800/80 bg-white/90 dark:bg-[#090E17]/90 backdrop-blur-md">
<div class="max-w-7xl mx-auto px-5 sm:px-8 h-16 flex items-center justify-between">
<NuxtLink to="/" class="flex items-center gap-3">
<BrandWordmark :height="28" />
<Badge variant="subtle" color="primary" size="xs">v0.1.0-alpha</Badge>
</NuxtLink>
<Navbar brand-to="/" :links="topLinks">
<template #logo>
<BrandWordmark :height="28" />
<Badge variant="subtle" color="primary" size="xs">v0.3.0</Badge>
</template>
<template #extra>
<Button
variant="ghost"
color="neutral"
size="icon"
:aria-label="isDark ? '切换至浅色模式' : '切换至深色模式'"
class="rounded-lg"
@click="toggle"
>
<Sun v-if="isDark" class="h-4 w-4 text-amber-400" />
<Moon v-else class="h-4 w-4 text-slate-600" />
</Button>
</template>
<template #actions>
<a href="https://github.com/ReCloudStudio" target="_blank" rel="noopener">
<Button variant="outline" color="neutral" size="sm">GitHub</Button>
</a>
</template>
</Navbar>

<div class="flex items-center gap-2">
<Button
variant="ghost"
color="neutral"
size="icon"
:aria-label="isDark ? '切换至浅色模式' : '切换至深色模式'"
class="rounded-lg"
@click="toggle"
>
<Sun v-if="isDark" class="w-4 h-4 text-amber-400" />
<Moon v-else class="w-4 h-4 text-slate-600" />
</Button>
<a
href="https://github.com/ReCloudStudio"
target="_blank"
rel="noopener"
aria-label="在 GitHub 上查看 ReCloud Studio"
class="inline-flex h-7 items-center justify-center gap-1.5 rounded-lg bg-transparent px-2.5 text-xs font-semibold tracking-[-0.01em] text-slate-800 ring-1 ring-inset ring-slate-300 shadow-xs transition-all duration-150 ease-out hover:bg-slate-100/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 dark:text-slate-200 dark:ring-slate-700 dark:hover:bg-slate-800/60"
>
<svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.53 1.032 1.53 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" />
</svg>
GitHub
</a>
</div>
</div>
</header>

<div class="w-full max-w-7xl mx-auto px-5 sm:px-8 py-10 lg:py-12 flex gap-12 pb-24 lg:pb-12 flex-1">
<div class="mx-auto flex w-full max-w-[90rem] flex-1 gap-[clamp(1.25rem,3vw,3rem)] px-[clamp(0.75rem,1.8vw,2rem)] py-10 pb-24 lg:py-12 lg:pb-12">
<!-- 分组侧边导航 -->
<aside class="hidden lg:block w-60 shrink-0 sticky top-24 max-h-[calc(100vh-7rem)] overflow-y-auto pr-3 pb-8">
<nav class="space-y-6">
<div v-for="group in docGroups" :key="group.label" class="space-y-1">
<span class="block px-3 py-1 text-xs font-semibold uppercase tracking-[0.08em] text-slate-500 dark:text-slate-400">{{ group.label }}</span>
<NuxtLink
v-for="item in group.items"
:key="item.name"
:to="docPath(item.name)"
class="block px-3 py-1.5 text-sm rounded-lg transition-colors"
:class="isActive(item.name)
? 'font-semibold bg-blue-600/10 dark:bg-[#70ACFE]/15 text-blue-700 dark:text-[#70ACFE]'
: 'font-medium text-slate-600 dark:text-slate-400 hover:text-slate-950 dark:hover:text-white hover:bg-slate-200/60 dark:hover:bg-slate-800/70'"
>{{ item.title }}</NuxtLink>
</div>
</nav>
<aside class="hidden max-h-[calc(100vh-7rem)] w-[clamp(13rem,18vw,16rem)] shrink-0 overflow-y-auto pb-8 pr-2 lg:sticky lg:top-24 lg:block">
<NavTree :groups="navigationGroups" :active-href="route.path" size="comfortable" />
</aside>

<!-- 移动端横向分类导航 -->
<div class="lg:hidden fixed bottom-0 inset-x-0 z-30 bg-white/95 dark:bg-[#090E17]/95 backdrop-blur-md border-t border-slate-200/80 dark:border-slate-800/80">
<nav class="flex gap-1 overflow-x-auto px-4 py-2.5 no-scrollbar">
<NuxtLink
v-for="item in flatDocs"
:key="item.name"
:to="docPath(item.name)"
class="shrink-0 rounded-lg px-3 py-1.5 text-xs font-medium whitespace-nowrap transition-colors"
:class="isActive(item.name)
? 'bg-blue-600/10 dark:bg-[#70ACFE]/15 text-blue-700 dark:text-[#70ACFE]'
: 'text-slate-600 dark:text-slate-400 hover:bg-slate-200/60 dark:hover:bg-slate-800/70'"
>{{ item.title }}</NuxtLink>
</nav>
</div>
<aside class="fixed inset-x-0 bottom-0 z-30 max-h-52 overflow-y-auto border-t border-[color:var(--border)] bg-[color:var(--background)]/95 p-4 backdrop-blur-md lg:hidden">
<NavTree :groups="navigationGroups" :active-href="route.path" searchable />
</aside>

<main class="flex-1 min-w-0 max-w-3xl">
<main class="flex-1 min-w-0">
<NuxtPage />
</main>
</div>
Expand All @@ -85,20 +50,25 @@
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { BrandWordmark, Sun, Moon } from '@recloudstudio/ui/icons'
import { useTheme } from '@recloudstudio/ui'
import { docGroups, docPath, flatDocs } from '~/utils/catalog'
import { useTheme, type NavTreeGroup } from '@recloudstudio/ui'
import { docGroups, docPath } from '~/utils/catalog'

const route = useRoute()
const { isDark, toggle } = useTheme()

const currentName = computed(() => {
const path = route.path
if (path === '/' || path === '') return 'index'
const m = path.match(/^\/components\/([^/]+)/)
return m ? m[1] : ''
})
// 顶栏只放精选入口;完整目录由侧边栏与移动端 NavTree 承载,避免 74 项链接撑爆顶栏
const topLinks = computed(() => [
{ label: '介绍', to: '/', active: route.path === '/' },
{ label: '快速开始', to: '/#quick-start', active: false },
{ label: '组件总览', to: '/#components', active: false },
{ label: '色彩与渐变', to: '/components/colors', active: route.path === '/components/colors' }
])

function isActive(name: string): boolean {
return currentName.value === name
}
const navigationGroups = computed<NavTreeGroup[]>(() => docGroups.map(group => ({
title: group.label,
items: group.items.map(item => ({
title: item.title,
to: docPath(item.name)
}))
})))
</script>
40 changes: 0 additions & 40 deletions apps/playground/components/DocApiTable.vue

This file was deleted.

83 changes: 0 additions & 83 deletions apps/playground/components/DocExample.vue

This file was deleted.

Loading
Loading