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

Карточки

Карточка со свечением

Карточка с мягким светящимся градиентом, заголовком и дополнительными метаданными.


Карточка со свечением

glowcard.svelte — карточка с мягким градиентным свечением на фоне. Поддерживает надзаголовок, заголовок, произвольное содержимое, ссылку и настраиваемую форму углов. Это отдельный компонент; существующая страница «Светящаяся карточка» остаётся без изменений.

Интерактивное демо

Меняйте надзаголовок, заголовок, форму углов и видимость обводки в панели управления. Наведите курсор на карточку, чтобы увидеть оформление в контексте интерфейса.

Короткое описание компонента, функции или проекта. Свечение использует цвет акцента текущей темы.

Пропсы

Надзаголовок
Заголовок
Форма углов
Отключить обводку при наведении
<script lang="ts">
	import type { Snippet } from 'svelte';
	import { cn } from '$lib/utils/cn';

	type Radius = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full';

	let {
		children,
		eyebrow,
		title,
		href,
		radius = 'lg',
		disableBorder = false,
		class: className = ''
	}: {
		children?: Snippet;
		eyebrow?: string;
		title?: string;
		href?: string;
		radius?: Radius;
		disableBorder?: boolean;
		class?: string;
	} = $props();

	const radiusClasses: Record<Radius, { wrapper: string; card: string }> = {
		none: { wrapper: 'rounded-none', card: 'rounded-none' },
		sm: { wrapper: 'rounded-md', card: 'rounded-sm' },
		md: { wrapper: 'rounded-lg', card: 'rounded-md' },
		lg: { wrapper: 'rounded-xl', card: 'rounded-lg' },
		xl: { wrapper: 'rounded-2xl', card: 'rounded-xl' },
		'2xl': { wrapper: 'rounded-3xl', card: 'rounded-2xl' },
		'3xl': { wrapper: 'rounded-[2rem]', card: 'rounded-3xl' },
		full: { wrapper: 'rounded-full', card: 'rounded-full' }
	};
</script>

<div class={cn('inset-shadow bg-background-inset p-1.5', radiusClasses[radius].wrapper, className)}>
	<svelte:element
		this={href ? 'a' : 'div'}
		{href}
		class={cn(
			'group relative isolate block overflow-hidden bg-background p-5 card transition-colors duration-150',
			!disableBorder && 'border border-border hover:border-accent/60',
			radiusClasses[radius].card
		)}
	>
		<div class="card-glow pointer-events-none absolute inset-0 -z-10" aria-hidden="true"></div>

		{#if eyebrow}<div class="mb-3 text-xs font-semibold tracking-widest text-accent uppercase">
				{eyebrow}
			</div>{/if}
		{#if title}<div class="text-lg font-semibold tracking-tight text-foreground">{title}</div>{/if}
		<div class="mt-2 text-sm leading-relaxed text-foreground-muted">{@render children?.()}</div>
	</svelte:element>
</div>

<style>
	.card-glow {
		background: radial-gradient(
			ellipse 130% 107.5% at 50% 10% in srgb,
			transparent 37%,
			var(--accent) 69%,
			color-mix(in srgb, var(--accent) 35%, transparent) 100%
		);
		filter: blur(clamp(0.75rem, 2.5vw, 1.5rem));
		opacity: 0.38;
	}
</style>
<script lang="ts">
	import type { Snippet } from 'svelte';
	import { cn } from '$lib/utils/cn';

	type Radius = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full';

	let {
		children,
		eyebrow,
		title,
		href,
		radius = 'lg',
		disableBorder = false,
		class: className = ''
	}: {
		children?: Snippet;
		eyebrow?: string;
		title?: string;
		href?: string;
		radius?: Radius;
		disableBorder?: boolean;
		class?: string;
	} = $props();

	const radiusClasses: Record<Radius, { wrapper: string; card: string }> = {
		none: { wrapper: 'rounded-none', card: 'rounded-none' },
		sm: { wrapper: 'rounded-md', card: 'rounded-sm' },
		md: { wrapper: 'rounded-lg', card: 'rounded-md' },
		lg: { wrapper: 'rounded-xl', card: 'rounded-lg' },
		xl: { wrapper: 'rounded-2xl', card: 'rounded-xl' },
		'2xl': { wrapper: 'rounded-3xl', card: 'rounded-2xl' },
		'3xl': { wrapper: 'rounded-[2rem]', card: 'rounded-3xl' },
		full: { wrapper: 'rounded-full', card: 'rounded-full' }
	};
</script>

<div class={cn('inset-shadow bg-background-inset p-1.5', radiusClasses[radius].wrapper, className)}>
	<svelte:element
		this={href ? 'a' : 'div'}
		{href}
		class={cn(
			'group relative isolate block overflow-hidden bg-background p-5 card transition-colors duration-150',
			!disableBorder && 'border border-border hover:border-accent/60',
			radiusClasses[radius].card
		)}
	>
		<div class="card-glow pointer-events-none absolute inset-0 -z-10" aria-hidden="true"></div>

		{#if eyebrow}<div class="mb-3 text-xs font-semibold tracking-widest text-accent uppercase">
				{eyebrow}
			</div>{/if}
		{#if title}<div class="text-lg font-semibold tracking-tight text-foreground">{title}</div>{/if}
		<div class="mt-2 text-sm leading-relaxed text-foreground-muted">{@render children?.()}</div>
	</svelte:element>
</div>

<style>
	.card-glow {
		background: radial-gradient(
			ellipse 130% 107.5% at 50% 10% in srgb,
			transparent 37%,
			var(--accent) 69%,
			color-mix(in srgb, var(--accent) 35%, transparent) 100%
		);
		filter: blur(clamp(0.75rem, 2.5vw, 1.5rem));
		opacity: 0.38;
	}
</style>

Использование

Базовый вариант

<script lang="ts">
	import GlowCard from '$lib/components/ui-registry/glowcard.svelte';
</script>

<GlowCard eyebrow="FEATURED" title="Новый проект">
	<p>Описание проекта или дополнительная информация.</p>
</GlowCard>
<script lang="ts">
	import GlowCard from '$lib/components/ui-registry/glowcard.svelte';
</script>

<GlowCard eyebrow="FEATURED" title="Новый проект">
	<p>Описание проекта или дополнительная информация.</p>
</GlowCard>

Карточка-ссылка

<GlowCard
	eyebrow="ДОКУМЕНТАЦИЯ"
	title="Изучить компоненты"
	href="/components"
>
	<p>Открыть библиотеку компонентов.</p>
</GlowCard>
<GlowCard
	eyebrow="ДОКУМЕНТАЦИЯ"
	title="Изучить компоненты"
	href="/components"
>
	<p>Открыть библиотеку компонентов.</p>
</GlowCard>

Выбор формы углов и отключение обводки

<GlowCard radius="none" disableBorder class="my-custom-card" title="Без скругления и обводки">
	<p>Содержимое карточки.</p>
</GlowCard>
<GlowCard radius="none" disableBorder class="my-custom-card" title="Без скругления и обводки">
	<p>Содержимое карточки.</p>
</GlowCard>

Пропсы

Пропс Тип По умолчанию Описание
children Snippet — Произвольное содержимое внутри карточки
eyebrow string — Небольшой надзаголовок над основным заголовком
title string — Заголовок карточки
href string — Если задан, карточка рендерится как ссылка <a>
radius 'none' 'sm' 'md' 'lg' 'xl' '2xl' '3xl' 'full' 'lg' Форма скругления углов, выбирается из списка доступных вариантов
class string '' Дополнительные CSS-классы внешней обёртки

Как работает свечение

  • Фоновый градиент строится на основе CSS-переменной --accent.
  • Внутренний блок использует цвета и границы текущей темы.
  • Эффект не требует дополнительных зависимостей JavaScript.

Исходный код

Полный исходный код glowcard.svelte доступен во вкладке исходников в интерактивном демо выше.