Перейти к содержимому

Форматирование

Предпросмотр компонента

Как использовать ComponentPreview для живого предпросмотра компонентов прямо в документации — с кодом и интерактивным демо.


Component Preview

ComponentPreview — компонент для живого предпросмотра Svelte-компонентов прямо на странице документации. Показывает интерактивное демо сверху и исходный код снизу с подсветкой синтаксиса и вкладками.

Как это выглядит

Демонстрация на примере ThemeToggle — кнопки переключения тёмной/светлой темы. Вкладки показывают полный исходный код компонента и его store:

<script lang="ts">
	import { cn } from '$lib/utils/cn';
	import { themeStore } from '$lib/stores/theme.svelte';
	import Sun from 'carbon-icons-svelte/lib/Sun.svelte';
	import Moon from 'carbon-icons-svelte/lib/Moon.svelte';

	type Props = {
		class?: string;
	};

	const props = $props();
	const className = $derived((props as Props).class ?? '');
</script>

<button
	type="button"
	class={cn(
		'group transition-scale inset-shadow relative inline-flex size-9 items-center justify-center rounded-sm bg-background-inset text-foreground duration-150 ease-out active:scale-[0.95]',
		className
	)}
	onclick={themeStore.toggle}
	aria-label={themeStore.isDark ? 'Светлая тема' : 'Тёмная тема'}
>
	<span class="sr-only">{themeStore.isDark ? 'Switch to light mode' : 'Switch to dark mode'}</span>
	<span class="theme-toggle-icon theme-toggle-sun">
		<Sun size={16} />
	</span>
	<span class="theme-toggle-icon theme-toggle-moon">
		<Moon size={16} />
	</span>
</button>

<style>
	.theme-toggle-icon {
		position: absolute;
		opacity: 0;
		filter: blur(4px);
		scale: 0.25;
		transition:
			opacity 150ms ease-out,
			filter 150ms ease-out,
			scale 150ms ease-out;
		will-change: opacity, filter, scale;
	}

	.theme-toggle-sun {
		opacity: 1;
		filter: blur(0);
		scale: 1;
	}

	:global(.dark) .theme-toggle-sun {
		opacity: 0;
		filter: blur(4px);
		scale: 0.25;
	}

	:global(.dark) .theme-toggle-moon {
		opacity: 1;
		filter: blur(0);
		scale: 1;
	}
</style>
<script lang="ts">
	import { cn } from '$lib/utils/cn';
	import { themeStore } from '$lib/stores/theme.svelte';
	import Sun from 'carbon-icons-svelte/lib/Sun.svelte';
	import Moon from 'carbon-icons-svelte/lib/Moon.svelte';

	type Props = {
		class?: string;
	};

	const props = $props();
	const className = $derived((props as Props).class ?? '');
</script>

<button
	type="button"
	class={cn(
		'group transition-scale inset-shadow relative inline-flex size-9 items-center justify-center rounded-sm bg-background-inset text-foreground duration-150 ease-out active:scale-[0.95]',
		className
	)}
	onclick={themeStore.toggle}
	aria-label={themeStore.isDark ? 'Светлая тема' : 'Тёмная тема'}
>
	<span class="sr-only">{themeStore.isDark ? 'Switch to light mode' : 'Switch to dark mode'}</span>
	<span class="theme-toggle-icon theme-toggle-sun">
		<Sun size={16} />
	</span>
	<span class="theme-toggle-icon theme-toggle-moon">
		<Moon size={16} />
	</span>
</button>

<style>
	.theme-toggle-icon {
		position: absolute;
		opacity: 0;
		filter: blur(4px);
		scale: 0.25;
		transition:
			opacity 150ms ease-out,
			filter 150ms ease-out,
			scale 150ms ease-out;
		will-change: opacity, filter, scale;
	}

	.theme-toggle-sun {
		opacity: 1;
		filter: blur(0);
		scale: 1;
	}

	:global(.dark) .theme-toggle-sun {
		opacity: 0;
		filter: blur(4px);
		scale: 0.25;
	}

	:global(.dark) .theme-toggle-moon {
		opacity: 1;
		filter: blur(0);
		scale: 1;
	}
</style>

Нажмите на кнопку выше — тема переключится. Вкладки внизу показывают полный исходный код обоих файлов с подсветкой и кнопкой копирования.

Как подключить

ComponentPreview не входит в список автоимпортируемых markdown-компонентов, поэтому его нужно импортировать вручную через блок script в .svx файле.

Шаг 1: Добавить импорты

В начале .svx файла, после frontmatter, добавьте блок script с импортом ComponentPreview, самого компонента и его исходного кода через суффикс ?raw:

--- frontmatter ---
title: Моя страница
--- конец frontmatter ---

блок script (lang ts):
  import { ComponentPreview } from '$lib';
  import ThemeToggle from '$lib/components/ui/ThemeToggle.svelte';
  import { themeToggleSource } from '$lib/components/ui/demo-sources';
конец блока script
--- frontmatter ---
title: Моя страница
--- конец frontmatter ---

блок script (lang ts):
  import { ComponentPreview } from '$lib';
  import ThemeToggle from '$lib/components/ui/ThemeToggle.svelte';
  import { themeToggleSource } from '$lib/components/ui/demo-sources';
конец блока script

Импорт с суффиксом ?raw возвращает содержимое файла как строку — это и есть исходный код для вкладок. Импорт без суффикса — живой компонент для превью. Чтобы избежать проблем с source maps внутри .svx файлов, ?raw импорты вынесите в отдельный .ts модуль (например demo-sources.ts) и импортируйте оттуда.

Шаг 2: Использовать в markdown

Передайте компонент в children (между открывающим и закрывающим тегом), а исходный код — в пропс sources как массив вкладок:

ComponentPreview с пропом sources:
  sources — массив объектов с полями name, code, language
  children — живой компонент ThemeToggle
ComponentPreview с пропом sources:
  sources — массив объектов с полями name, code, language
  children — живой компонент ThemeToggle

Пропсы

Пропс Тип Назначение
code string Исходный код для отображения в панели снизу (одна вкладка)
language string Язык подсветки синтаксиса (по умолчанию typescript)
label string Название вкладки с кодом (по умолчанию Code)
sources SourceTab[] Массив вкладок с кодом (заменяёт code)
children Snippet Живой превью компонента
class string Дополнительные классы для области превью

Несколько вкладок с кодом

Если нужно показать несколько файлов, используйте пропс sources вместо code. Передайте массив объектов с полями name, code и language — каждый объект станет отдельной вкладкой. Демонстрация выше использует именно этот подход с двумя вкладками: ThemeToggle.svelte и theme.svelte.ts.

Каждый объект в массиве sources содержит:

Поле Тип Назначение
name string Название вкладки
code string Исходный код
language string Язык подсветки (по умолчанию typescript)

Особенности

  • Превью рендерится в изолированной области с прокруткой
  • Код подсвечивается через Shiki (github-light / github-dark)
  • Вкладки переключаются стрелками на клавиатуре (ArrowLeft / ArrowRight)
  • Кнопка копирования кода в правом верхнем углу панели с кодом
  • Тема превью наследует текущую тему сайта
Важно
Компонент `ComponentPreview` не автоимпортируется. Всегда добавляйте блок `script` с импортом вручную. Это сделано намеренно — превью требует передачи реального Svelte-компонента, что невозможно через чистый markdown.