style: auto-format codebase with Prettier

Applied formatting to 1487+ files using pnpm format:write
  - TypeScript/JavaScript files
  - Svelte components
  - Astro pages
  - JSON configs
  - Markdown docs

  13 files still need manual review (Astro JSX comments)
This commit is contained in:
Wuesteon 2025-11-27 18:33:16 +01:00
parent 0241f5554c
commit d36b321d9d
3952 changed files with 661498 additions and 739751 deletions

View file

@ -6,69 +6,79 @@ import Container from '../atoms/Container.astro';
import Button from '../atoms/Button.astro';
interface CTA {
text: string;
href: string;
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
text: string;
href: string;
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
}
interface Props {
title: string;
subtitle?: string;
primaryCta?: CTA;
secondaryCta?: CTA;
variant?: 'default' | 'highlighted' | 'minimal';
class?: string;
id?: string;
title: string;
subtitle?: string;
primaryCta?: CTA;
secondaryCta?: CTA;
variant?: 'default' | 'highlighted' | 'minimal';
class?: string;
id?: string;
}
const {
title,
subtitle,
primaryCta,
secondaryCta,
variant = 'default',
class: className = '',
id
title,
subtitle,
primaryCta,
secondaryCta,
variant = 'default',
class: className = '',
id,
} = Astro.props;
const variantStyles = {
default: 'bg-[var(--color-background-page)]',
highlighted: 'bg-[var(--color-primary)]/10 border-y border-[var(--color-primary)]/20',
minimal: ''
default: 'bg-[var(--color-background-page)]',
highlighted: 'bg-[var(--color-primary)]/10 border-y border-[var(--color-primary)]/20',
minimal: '',
};
---
<section id={id} class:list={["py-16 md:py-24", variantStyles[variant], className]}>
<Container size="md">
<div class="text-center space-y-6">
<h2 class="text-2xl sm:text-3xl md:text-4xl font-bold text-[var(--color-text-primary)] leading-tight">
<slot name="title">{title}</slot>
</h2>
<section id={id} class:list={['py-16 md:py-24', variantStyles[variant], className]}>
<Container size="md">
<div class="text-center space-y-6">
<h2
class="text-2xl sm:text-3xl md:text-4xl font-bold text-[var(--color-text-primary)] leading-tight"
>
<slot name="title">{title}</slot>
</h2>
{subtitle && (
<p class="text-base sm:text-lg text-[var(--color-text-secondary)] max-w-2xl mx-auto leading-relaxed">
{subtitle}
</p>
)}
{
subtitle && (
<p class="text-base sm:text-lg text-[var(--color-text-secondary)] max-w-2xl mx-auto leading-relaxed">
{subtitle}
</p>
)
}
{(primaryCta || secondaryCta) && (
<div class="flex flex-col sm:flex-row gap-4 justify-center pt-4">
{primaryCta && (
<Button href={primaryCta.href} variant={primaryCta.variant ?? 'primary'} size="lg">
<slot name="primaryCtaIcon" />
{primaryCta.text}
</Button>
)}
{secondaryCta && (
<Button href={secondaryCta.href} variant={secondaryCta.variant ?? 'secondary'} size="lg">
<slot name="secondaryCtaIcon" />
{secondaryCta.text}
</Button>
)}
</div>
)}
{
(primaryCta || secondaryCta) && (
<div class="flex flex-col sm:flex-row gap-4 justify-center pt-4">
{primaryCta && (
<Button href={primaryCta.href} variant={primaryCta.variant ?? 'primary'} size="lg">
<slot name="primaryCtaIcon" />
{primaryCta.text}
</Button>
)}
{secondaryCta && (
<Button
href={secondaryCta.href}
variant={secondaryCta.variant ?? 'secondary'}
size="lg"
>
<slot name="secondaryCtaIcon" />
{secondaryCta.text}
</Button>
)}
</div>
)
}
<slot />
</div>
</Container>
<slot />
</div>
</Container>
</section>

View file

@ -7,109 +7,119 @@ import Container from '../atoms/Container.astro';
import SectionHeader from '../atoms/SectionHeader.astro';
interface FAQItem {
question: string;
answer: string;
question: string;
answer: string;
}
interface Props {
title?: string;
subtitle?: string;
faqs: FAQItem[];
class?: string;
id?: string;
singleExpand?: boolean;
title?: string;
subtitle?: string;
faqs: FAQItem[];
class?: string;
id?: string;
singleExpand?: boolean;
}
const {
title = 'Frequently Asked Questions',
subtitle,
faqs,
class: className = '',
id = 'faq',
singleExpand = true
title = 'Frequently Asked Questions',
subtitle,
faqs,
class: className = '',
id = 'faq',
singleExpand = true,
} = Astro.props;
const sectionId = `faq-section-${Math.random().toString(36).substring(7)}`;
---
<section id={id} class:list={["py-16 md:py-24", className]}>
<Container size="md">
<SectionHeader title={title} subtitle={subtitle} />
<section id={id} class:list={['py-16 md:py-24', className]}>
<Container size="md">
<SectionHeader title={title} subtitle={subtitle} />
<div class="max-w-3xl mx-auto space-y-4" data-faq-container={singleExpand ? sectionId : undefined}>
{faqs.map((faq, index) => (
<details class="group" data-faq-item={singleExpand ? sectionId : undefined}>
<summary class="cursor-pointer list-none">
<div class="bg-[var(--color-background-card)] rounded-xl p-5 sm:p-6 border border-[var(--color-border)] hover:bg-[var(--color-background-card-hover)] hover:border-[var(--color-border-hover,var(--color-border))] transition-all duration-200">
<div class="flex items-center justify-between gap-4">
<h3 class="font-semibold text-base sm:text-lg text-[var(--color-text-primary)] pr-4 group-open:text-[var(--color-primary)] transition-colors text-left">
{faq.question}
</h3>
<div class="flex-shrink-0 w-5 h-5 text-[var(--color-primary)] transition-transform duration-300 group-open:rotate-180">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</div>
</div>
<div class="overflow-hidden max-h-0 group-open:max-h-[1000px] transition-all duration-300 ease-in-out">
<div class="pt-4 text-[var(--color-text-secondary)] leading-relaxed text-sm sm:text-base prose prose-sm max-w-none">
<Fragment set:html={faq.answer} />
</div>
</div>
</div>
</summary>
</details>
))}
</div>
<div
class="max-w-3xl mx-auto space-y-4"
data-faq-container={singleExpand ? sectionId : undefined}
>
{
faqs.map((faq, index) => (
<details class="group" data-faq-item={singleExpand ? sectionId : undefined}>
<summary class="cursor-pointer list-none">
<div class="bg-[var(--color-background-card)] rounded-xl p-5 sm:p-6 border border-[var(--color-border)] hover:bg-[var(--color-background-card-hover)] hover:border-[var(--color-border-hover,var(--color-border))] transition-all duration-200">
<div class="flex items-center justify-between gap-4">
<h3 class="font-semibold text-base sm:text-lg text-[var(--color-text-primary)] pr-4 group-open:text-[var(--color-primary)] transition-colors text-left">
{faq.question}
</h3>
<div class="flex-shrink-0 w-5 h-5 text-[var(--color-primary)] transition-transform duration-300 group-open:rotate-180">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
</div>
<div class="overflow-hidden max-h-0 group-open:max-h-[1000px] transition-all duration-300 ease-in-out">
<div class="pt-4 text-[var(--color-text-secondary)] leading-relaxed text-sm sm:text-base prose prose-sm max-w-none">
<Fragment set:html={faq.answer} />
</div>
</div>
</div>
</summary>
</details>
))
}
</div>
<slot name="contact" />
<slot />
</Container>
<slot name="contact" />
<slot />
</Container>
</section>
<style>
details summary::-webkit-details-marker {
display: none;
}
details summary::-webkit-details-marker {
display: none;
}
details[open] summary ~ * {
animation: slideDown 0.3s ease-out;
}
details[open] summary ~ * {
animation: slideDown 0.3s ease-out;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
<script define:vars={{ sectionId, singleExpand }}>
if (singleExpand) {
function setupFAQ() {
const container = document.querySelector(`[data-faq-container="${sectionId}"]`);
if (!container) return;
if (singleExpand) {
function setupFAQ() {
const container = document.querySelector(`[data-faq-container="${sectionId}"]`);
if (!container) return;
const items = container.querySelectorAll(`[data-faq-item="${sectionId}"]`);
const items = container.querySelectorAll(`[data-faq-item="${sectionId}"]`);
items.forEach((item) => {
item.addEventListener('toggle', (e) => {
if (e.target.open) {
items.forEach((otherItem) => {
if (otherItem !== e.target && otherItem.open) {
otherItem.open = false;
}
});
}
});
});
}
items.forEach((item) => {
item.addEventListener('toggle', (e) => {
if (e.target.open) {
items.forEach((otherItem) => {
if (otherItem !== e.target && otherItem.open) {
otherItem.open = false;
}
});
}
});
});
}
setupFAQ();
document.addEventListener('astro:page-load', setupFAQ);
}
setupFAQ();
document.addEventListener('astro:page-load', setupFAQ);
}
</script>

View file

@ -8,88 +8,88 @@ import Card from '../atoms/Card.astro';
import SectionHeader from '../atoms/SectionHeader.astro';
interface Feature {
icon: string;
title: string;
description: string;
href?: string;
icon: string;
title: string;
description: string;
href?: string;
}
interface Props {
title: string;
subtitle?: string;
features: Feature[];
columns?: 2 | 3 | 4;
variant?: 'cards' | 'simple' | 'icons-left';
class?: string;
id?: string;
title: string;
subtitle?: string;
features: Feature[];
columns?: 2 | 3 | 4;
variant?: 'cards' | 'simple' | 'icons-left';
class?: string;
id?: string;
}
const {
title,
subtitle,
features,
columns = 3,
variant = 'cards',
class: className = '',
id
title,
subtitle,
features,
columns = 3,
variant = 'cards',
class: className = '',
id,
} = Astro.props;
const gridCols = {
2: 'md:grid-cols-2',
3: 'md:grid-cols-2 lg:grid-cols-3',
4: 'md:grid-cols-2 lg:grid-cols-4'
2: 'md:grid-cols-2',
3: 'md:grid-cols-2 lg:grid-cols-3',
4: 'md:grid-cols-2 lg:grid-cols-4',
};
---
<section id={id} class:list={["py-16 md:py-24", className]}>
<Container>
<SectionHeader title={title} subtitle={subtitle} />
<section id={id} class:list={['py-16 md:py-24', className]}>
<Container>
<SectionHeader title={title} subtitle={subtitle} />
<div class:list={["grid gap-6 md:gap-8", gridCols[columns]]}>
{features.map((feature) => (
variant === 'cards' ? (
<Card variant="hover" padding="lg" as={feature.href ? 'a' : 'div'} href={feature.href}>
<div class="flex flex-col items-center text-center h-full">
<div class="text-4xl sm:text-5xl mb-4 transform group-hover:scale-110 transition-transform duration-300">
{feature.icon}
</div>
<h3 class="font-semibold text-lg sm:text-xl text-[var(--color-text-primary)] mb-3">
{feature.title}
</h3>
<p class="text-[var(--color-text-secondary)] text-sm sm:text-base leading-relaxed">
{feature.description}
</p>
</div>
</Card>
) : variant === 'icons-left' ? (
<div class="flex gap-4">
<div class="flex-shrink-0 text-3xl">
{feature.icon}
</div>
<div>
<h3 class="font-semibold text-lg text-[var(--color-text-primary)] mb-2">
{feature.title}
</h3>
<p class="text-[var(--color-text-secondary)] text-sm leading-relaxed">
{feature.description}
</p>
</div>
</div>
) : (
<div class="text-center">
<div class="text-4xl mb-4">{feature.icon}</div>
<h3 class="font-semibold text-lg text-[var(--color-text-primary)] mb-2">
{feature.title}
</h3>
<p class="text-[var(--color-text-secondary)] text-sm leading-relaxed">
{feature.description}
</p>
</div>
)
))}
</div>
<div class:list={['grid gap-6 md:gap-8', gridCols[columns]]}>
{
features.map((feature) =>
variant === 'cards' ? (
<Card variant="hover" padding="lg" as={feature.href ? 'a' : 'div'} href={feature.href}>
<div class="flex flex-col items-center text-center h-full">
<div class="text-4xl sm:text-5xl mb-4 transform group-hover:scale-110 transition-transform duration-300">
{feature.icon}
</div>
<h3 class="font-semibold text-lg sm:text-xl text-[var(--color-text-primary)] mb-3">
{feature.title}
</h3>
<p class="text-[var(--color-text-secondary)] text-sm sm:text-base leading-relaxed">
{feature.description}
</p>
</div>
</Card>
) : variant === 'icons-left' ? (
<div class="flex gap-4">
<div class="flex-shrink-0 text-3xl">{feature.icon}</div>
<div>
<h3 class="font-semibold text-lg text-[var(--color-text-primary)] mb-2">
{feature.title}
</h3>
<p class="text-[var(--color-text-secondary)] text-sm leading-relaxed">
{feature.description}
</p>
</div>
</div>
) : (
<div class="text-center">
<div class="text-4xl mb-4">{feature.icon}</div>
<h3 class="font-semibold text-lg text-[var(--color-text-primary)] mb-2">
{feature.title}
</h3>
<p class="text-[var(--color-text-secondary)] text-sm leading-relaxed">
{feature.description}
</p>
</div>
)
)
}
</div>
<slot name="highlight" />
<slot />
</Container>
<slot name="highlight" />
<slot />
</Container>
</section>

View file

@ -9,132 +9,136 @@ import Badge from '../atoms/Badge.astro';
import SectionHeader from '../atoms/SectionHeader.astro';
interface PricingFeature {
text: string;
included: boolean;
text: string;
included: boolean;
}
interface PricingPlan {
name: string;
description?: string;
price: string;
period?: string;
features: PricingFeature[] | string[];
cta: {
text: string;
href: string;
};
highlighted?: boolean;
badge?: string;
name: string;
description?: string;
price: string;
period?: string;
features: PricingFeature[] | string[];
cta: {
text: string;
href: string;
};
highlighted?: boolean;
badge?: string;
}
interface Props {
title: string;
subtitle?: string;
plans: PricingPlan[];
class?: string;
id?: string;
title: string;
subtitle?: string;
plans: PricingPlan[];
class?: string;
id?: string;
}
const {
title,
subtitle,
plans,
class: className = '',
id = 'pricing'
} = Astro.props;
const { title, subtitle, plans, class: className = '', id = 'pricing' } = Astro.props;
// Normalize features to always have { text, included } format
function normalizeFeatures(features: PricingFeature[] | string[]): PricingFeature[] {
return features.map(f => typeof f === 'string' ? { text: f, included: true } : f);
return features.map((f) => (typeof f === 'string' ? { text: f, included: true } : f));
}
---
<section id={id} class:list={["py-16 md:py-24", className]}>
<Container>
<SectionHeader title={title} subtitle={subtitle} />
<section id={id} class:list={['py-16 md:py-24', className]}>
<Container>
<SectionHeader title={title} subtitle={subtitle} />
<div class:list={[
"grid gap-6 md:gap-8",
plans.length === 2 && "md:grid-cols-2 max-w-4xl mx-auto",
plans.length === 3 && "md:grid-cols-3",
plans.length >= 4 && "md:grid-cols-2 lg:grid-cols-4"
]}>
{plans.map((plan) => (
<Card
variant={plan.highlighted ? 'glow' : 'bordered'}
padding="lg"
class:list={[
"flex flex-col relative",
plan.highlighted && "ring-2 ring-[var(--color-primary)] scale-105"
]}
>
{plan.badge && (
<div class="absolute -top-3 left-1/2 -translate-x-1/2">
<Badge variant="primary">{plan.badge}</Badge>
</div>
)}
<div
class:list={[
'grid gap-6 md:gap-8',
plans.length === 2 && 'md:grid-cols-2 max-w-4xl mx-auto',
plans.length === 3 && 'md:grid-cols-3',
plans.length >= 4 && 'md:grid-cols-2 lg:grid-cols-4',
]}
>
{
plans.map((plan) => (
<Card
variant={plan.highlighted ? 'glow' : 'bordered'}
padding="lg"
class:list={[
'flex flex-col relative',
plan.highlighted && 'ring-2 ring-[var(--color-primary)] scale-105',
]}
>
{plan.badge && (
<div class="absolute -top-3 left-1/2 -translate-x-1/2">
<Badge variant="primary">{plan.badge}</Badge>
</div>
)}
<div class="text-center mb-6">
<h3 class="text-xl font-bold text-[var(--color-text-primary)] mb-2">
{plan.name}
</h3>
{plan.description && (
<p class="text-sm text-[var(--color-text-secondary)]">
{plan.description}
</p>
)}
</div>
<div class="text-center mb-6">
<h3 class="text-xl font-bold text-[var(--color-text-primary)] mb-2">{plan.name}</h3>
{plan.description && (
<p class="text-sm text-[var(--color-text-secondary)]">{plan.description}</p>
)}
</div>
<div class="text-center mb-6">
<span class="text-4xl font-bold text-[var(--color-text-primary)]">
{plan.price}
</span>
{plan.period && (
<span class="text-[var(--color-text-secondary)]">
/{plan.period}
</span>
)}
</div>
<div class="text-center mb-6">
<span class="text-4xl font-bold text-[var(--color-text-primary)]">{plan.price}</span>
{plan.period && (
<span class="text-[var(--color-text-secondary)]">/{plan.period}</span>
)}
</div>
<ul class="space-y-3 mb-8 flex-1">
{normalizeFeatures(plan.features).map((feature) => (
<li class="flex items-start gap-3">
<svg
class:list={[
"w-5 h-5 flex-shrink-0 mt-0.5",
feature.included ? "text-green-500" : "text-[var(--color-text-muted)]"
]}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
{feature.included ? (
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
) : (
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
)}
</svg>
<span class:list={[
"text-sm",
feature.included ? "text-[var(--color-text-primary)]" : "text-[var(--color-text-muted)] line-through"
]}>
{feature.text}
</span>
</li>
))}
</ul>
<ul class="space-y-3 mb-8 flex-1">
{normalizeFeatures(plan.features).map((feature) => (
<li class="flex items-start gap-3">
<svg
class:list={[
'w-5 h-5 flex-shrink-0 mt-0.5',
feature.included ? 'text-green-500' : 'text-[var(--color-text-muted)]',
]}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
{feature.included ? (
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
/>
) : (
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
)}
</svg>
<span
class:list={[
'text-sm',
feature.included
? 'text-[var(--color-text-primary)]'
: 'text-[var(--color-text-muted)] line-through',
]}
>
{feature.text}
</span>
</li>
))}
</ul>
<Button
href={plan.cta.href}
variant={plan.highlighted ? 'primary' : 'secondary'}
fullWidth
>
{plan.cta.text}
</Button>
</Card>
))}
</div>
<Button
href={plan.cta.href}
variant={plan.highlighted ? 'primary' : 'secondary'}
fullWidth
>
{plan.cta.text}
</Button>
</Card>
))
}
</div>
<slot />
</Container>
<slot />
</Container>
</section>