Skip to content
Merged
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
77 changes: 76 additions & 1 deletion apps/docs-smoke/content/docs/guides/components-fixture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,36 @@ description: "Render the browser-facing @inth/docs adapters through authored MDX

<CommandTabs command="next-app" mode="create" />

<Accordion>
<AccordionItem title="Pipeline behavior">
Accordion content is collapsible in the browser and still available after MDX-to-markdown conversion.
</AccordionItem>
</Accordion>

<Tabs items={["Overview", "Types"]}>
<Tab value="Overview">Tabs hydrate in the browser.</Tab>
<Tab value="Types">Use `TypeTable` when type data already exists in MDX.</Tab>
</Tabs>

<TopicSwitcher
label="Framework"
activeValue="react"
items={[
{
value: "react",
label: "React",
href: "/docs/frameworks/react/quickstart",
description: "React integration",
},
{
value: "vue",
label: "Vue",
href: "/docs/frameworks/vue/quickstart",
description: "Vue integration",
},
]}
/>

<Mermaid chart={`flowchart LR
A[MDX] --> B[mdxComponents]
B --> C[Rendered route]
Expand All @@ -42,7 +67,7 @@ description: "Render the browser-facing @inth/docs adapters through authored MDX

<Steps>
<Step title="Author MDX">
Use semantic components such as `Callout`, `Tabs`, `Cards`, `Steps`, `CommandTabs`, and `TypeTable`.
Use semantic components such as `Callout`, `Tabs`, `Cards`, `Steps`, `CommandTabs`, `Accordion`, `Example`, `TopicSwitcher`, and `TypeTable`.
</Step>
<Step title="Render in the app">
Import the `.mdx` file directly and provide `mdxComponents` through the shared runtime map.
Expand All @@ -54,6 +79,15 @@ description: "Render the browser-facing @inth/docs adapters through authored MDX

<CommandTabs command="@inth/docs" mode="install" />

<Accordion>
<AccordionItem title="Authoring rule" defaultOpen>
Prefer semantic components whose content can flatten cleanly into markdown for agents, search indexes, and LLM bundles.
</AccordionItem>
<AccordionItem title="Naming rule">
Use `TopicSwitcher` for equivalent docs slices. Frameworks are one topic category, not the whole abstraction.
</AccordionItem>
</Accordion>

<Tabs items={["Overview", "Tables", "Pipeline note"]}>
<Tab value="Overview">
This tabset proves the package adapters hydrate correctly inside the demo app.
Expand All @@ -66,6 +100,47 @@ description: "Render the browser-facing @inth/docs adapters through authored MDX
</Tab>
</Tabs>

<TopicSwitcher
label="Framework"
activeValue="react"
items={[
{
value: "react",
label: "React",
href: "/docs/frameworks/react/quickstart",
description: "React integration",
},
{
value: "next",
label: "Next.js",
href: "/docs/frameworks/next/quickstart",
description: "Next.js integration",
},
{
value: "svelte",
label: "Svelte",
href: "/docs/frameworks/svelte/quickstart",
description: "Svelte integration",
},
]}
/>

<Example
title="Render MDX"
description="Preview the output and inspect the source."
filename="mdx-components.tsx"
language="tsx"
code={`import { mdxComponents } from "@inth/docs";

export const components = {
...mdxComponents,
};`}
>
<Callout title="Runtime adapter" variant="success">
The host app owns styling while `@inth/docs` owns the MDX component contract.
</Callout>
</Example>

<Mermaid chart={`flowchart LR
A[Authored MDX] --> B[mdxComponents]
B --> C[TanStack Start route]
Expand Down
4 changes: 3 additions & 1 deletion apps/docs-smoke/content/docs/guides/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@ import { mdxComponents } from "@inth/docs";
export const components = {
...mdxComponents,
// Add or override project-specific MDX components here.
// Example: Icon, APIExample, FrameworkTabs, or branded Callout.
// Example: Icon, APIExample, TopicSwitcher, or branded Callout.
};
```

`@inth/docs` does not own your routing, sidebar, layout, hosting, or framework. A Next.js, TanStack Start, Vite, Fumadocs, or Astro-backed docs app can still own those pieces.

Framework docs can be exposed through `TopicSwitcher` while the conversion pipeline still resolves `{framework}` placeholders from `/docs/frameworks/:framework` routes.

## 3. Convert Authored MDX To Markdown

Create a docs conversion script in the consuming repo.
Expand Down
2 changes: 1 addition & 1 deletion apps/docs-smoke/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ After conversion, use `@inth/docs/llm` to write `llms.txt` and topic-scoped full
/>
<Card
title="Runtime Components"
description="Exercise the browser-facing adapters through authored MDX."
description="Exercise browser-facing adapters including Accordion, Example, and TopicSwitcher through authored MDX."
href="/docs/guides/components-fixture"
/>
<Card
Expand Down
2 changes: 1 addition & 1 deletion apps/docs-smoke/src/generated/docs-search-content.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/docs-smoke/src/generated/docs-search-index.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions apps/docs-smoke/src/lib/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,21 @@ export const componentMatrix: Array<{
coverage: ["runtime render", "browser hydration", "agent docs"],
note: "Switches install, run, or create commands in-browser.",
},
{
name: "Accordion / AccordionItem",
coverage: ["runtime render", "pipeline conversion", "agent docs"],
note: "Collapsible details that still flatten into generated markdown.",
},
{
name: "Example",
coverage: ["runtime render", "pipeline conversion", "agent docs"],
note: "Data-driven preview and source examples for authored MDX.",
},
{
name: "TopicSwitcher",
coverage: ["runtime render", "pipeline conversion", "agent docs"],
note: "Reader-facing navigation across equivalent docs topics.",
},
{
name: "Selector",
coverage: ["runtime render", "browser hydration"],
Expand Down
87 changes: 87 additions & 0 deletions apps/docs-smoke/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,93 @@
@apply mt-4 overflow-x-auto rounded-lg border border-border bg-secondary px-4 py-3 text-sm text-foreground;
}

[data-inth-accordion] {
@apply my-6 space-y-3;
}

[data-inth-accordion-item] {
@apply rounded-lg border border-border bg-card px-4 py-3;
}

[data-inth-accordion-summary] {
@apply cursor-pointer select-none text-sm font-medium text-foreground;
}

[data-inth-accordion-content] {
@apply mt-3 text-sm leading-7 text-muted-foreground;
}

[data-inth-example] {
@apply my-6 overflow-hidden rounded-lg border border-border bg-card;
}

[data-inth-example-header] {
@apply border-border border-b px-4 py-4;
}

[data-inth-example-title] {
@apply m-0 text-base font-semibold tracking-tight text-foreground;
}

[data-inth-example-description] {
@apply mt-1 text-sm leading-6 text-muted-foreground;
}

[data-inth-example-preview] {
@apply border-border border-b px-4 py-4;
}

[data-inth-example-code],
[data-inth-example-source-files] {
@apply bg-secondary/70 px-4 py-4;
}

[data-inth-example-source-files] {
@apply space-y-4 border-border border-t;
}

[data-inth-example-filename] {
font-family: var(--font-mono);
@apply mb-2 text-xs text-muted-foreground;
}

[data-inth-example-code-block] {
font-family: var(--font-mono);
@apply overflow-x-auto rounded-lg border border-border bg-background px-4 py-3 text-[13px] leading-6 text-foreground;
}

[data-inth-topic-switcher] {
@apply my-6 rounded-lg border border-border bg-card p-4;
}

[data-inth-topic-switcher-label] {
@apply m-0 text-xs font-medium text-muted-foreground;
}

[data-inth-topic-switcher-list] {
@apply mt-3 grid list-none gap-2 p-0 sm:grid-cols-2;
}

[data-inth-topic-switcher-item] {
@apply m-0;
}

[data-inth-topic-switcher-link] {
@apply block rounded-lg border border-border bg-background px-3 py-3 no-underline transition-colors hover:bg-secondary;
}

[data-inth-topic-switcher-link][data-active] {
@apply bg-secondary text-foreground;
}

[data-inth-topic-switcher-item-label] {
@apply block text-sm font-medium text-foreground;
}

[data-inth-topic-switcher-item-description] {
@apply mt-1 block text-xs leading-5 text-muted-foreground;
}

[data-inth-mermaid] {
font-family: var(--font-mono);
@apply my-6 overflow-x-auto rounded-lg border border-border bg-secondary px-4 py-4 text-sm;
Expand Down
8 changes: 7 additions & 1 deletion apps/docs-smoke/tests/e2e/smoke.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const DASHBOARD_HEADING = /Build docs with @inth\/docs/i;
const QUICKSTART_ROUTE_LINK = /Quickstart/;
const AI_DISABLED_MESSAGE = /AI answers are disabled/i;
const QUICKSTART_INSTALL_HEADING_HREF = "/docs/guides/quickstart#1-install";
const COMPONENT_FIXTURE_CALLOUT_COUNT = 3;

async function waitForClientHydration(page: Page): Promise<void> {
await page.waitForFunction(
Expand Down Expand Up @@ -130,9 +131,14 @@ test("components fixture renders package adapters and preserves external link sa
await expect(
page.getByRole("heading", { name: "Runtime Components", exact: true })
).toBeVisible();
await expect(page.locator("[data-inth-callout]")).toHaveCount(2);
await expect(page.locator("[data-inth-callout]")).toHaveCount(
COMPONENT_FIXTURE_CALLOUT_COUNT
);
await expect(page.locator("[data-inth-accordion]")).toBeVisible();
await expect(page.locator("[data-inth-cards]")).toBeVisible();
await expect(page.locator("[data-inth-example]")).toBeVisible();
await expect(page.locator("[data-inth-steps]")).toBeVisible();
await expect(page.locator("[data-inth-topic-switcher]")).toBeVisible();

const overview = page.getByRole("tab", { name: "Overview" });
const tables = page.getByRole("tab", { name: "Tables" });
Expand Down
69 changes: 69 additions & 0 deletions packages/docs/agent-docs-src/docs/components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ The root export is intentionally small. It gives consumers a ready-to-spread MDX

`mdxComponents` includes:

- `Accordion`
- `AccordionItem`
- `ExtractedTypeTable`
- `Callout`
- `Card`
- `Cards`
- `Example`
- `Mermaid`
- `CommandTabs`
- `Selector`
- `Step`
- `Steps`
- `Tab`
- `Tabs`
- `TopicSwitcher`
- `TypeTable`

Use it like this:
Expand All @@ -45,6 +49,20 @@ Override individual entries rather than replacing the full map unless you want t

## Important Components

### `Accordion` and `AccordionItem`

Use for secondary details that should be collapsible in the browser but still available to markdown conversion, search, and LLM bundles.

```tsx
<Accordion>
<AccordionItem title="When should I use this?">
Use accordions for supporting details, troubleshooting notes, and optional reference material.
</AccordionItem>
</Accordion>
```

Closed content is still flattened by the remark pipeline, so do not use accordions to hide content from generated outputs.

### `CommandTabs`

Use for package-manager-specific install or run commands.
Expand All @@ -64,6 +82,30 @@ Use for package-manager-specific install or run commands.

Use `mode="install"` when `command` is a package name, `mode="run"` when `command` is a CLI name, and `mode="create"` for starter commands such as `pnpm create next-app`. `command` can also include a `{pm}` placeholder for custom templates. Use `commands` for exact per-manager overrides and `defaultManager` to choose the initial tab.

### `Example`

Use for data-driven preview and source examples. The package component receives code as data; host apps can add filesystem loaders or dynamic imports outside `@inth/docs` when they need app-specific behavior.

```tsx
<Example
title="Render MDX"
description="Preview the output and inspect the source."
filename="mdx-components.tsx"
language="tsx"
code={`import { mdxComponents } from "@inth/docs";

export const components = {
...mdxComponents,
};`}
>
<Callout title="Runtime adapter" variant="success">
The host app owns styling while `@inth/docs` owns the MDX component contract.
</Callout>
</Example>
```

Use `sourceFiles` when an example needs to show supporting files in addition to the primary snippet.

### `TypeTable` and `ExtractedTypeTable`

Use `TypeTable` for explicit prop or type rows you already know. Use `ExtractedTypeTable` when the docs should extract types from source files.
Expand All @@ -74,6 +116,33 @@ Use `TypeTable` for explicit prop or type rows you already know. Use `ExtractedT

These components are primarily authoring affordances in MDX. When the markdown conversion pipeline runs, their content is flattened into standard markdown so agents do not need JSX-aware renderers.

### `TopicSwitcher`

Use for reader-facing navigation across equivalent documentation topics.

```tsx
<TopicSwitcher
label="Framework"
activeValue="react"
items={[
{
value: "react",
label: "React",
href: "/docs/frameworks/react/quickstart",
description: "React integration",
},
{
value: "vue",
label: "Vue",
href: "/docs/frameworks/vue/quickstart",
description: "Vue integration",
},
]}
/>
```

`TopicSwitcher` is intentionally generic. Frameworks are one topic category, but the same component can represent SDKs, runtimes, deployment targets, product areas, or other equivalent slices of docs. It does not automatically read LLM topic config.

## Guidance

- Prefer the package root export for React doc-site rendering.
Expand Down
Loading
Loading