Don't use tabs in editor
This commit is contained in:
@ -3,12 +3,12 @@ import Item from '~/components/blog/GridItem.astro';
|
||||
import type { Post } from '~/types';
|
||||
|
||||
export interface Props {
|
||||
posts: Array<Post>;
|
||||
posts: Array<Post>;
|
||||
}
|
||||
|
||||
const { posts } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="grid gap-6 row-gap-5 md:grid-cols-2 lg:grid-cols-4 -mb-6">
|
||||
{posts.map((post) => <Item post={post} />)}
|
||||
{posts.map((post) => <Item post={post} />)}
|
||||
</div>
|
||||
|
@ -8,7 +8,7 @@ import { findImage } from '~/utils/images';
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
|
||||
export interface Props {
|
||||
post: Post;
|
||||
post: Post;
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
@ -16,33 +16,33 @@ const image = await findImage(post.image);
|
||||
---
|
||||
|
||||
<article class="mb-6 transition">
|
||||
<div class="relative h-0 pb-[56.25%] lg:h-64 overflow-hidden bg-gray-400 dark:bg-slate-700 rounded shadow-lg mb-6">
|
||||
{
|
||||
image && (
|
||||
<Picture
|
||||
src={image}
|
||||
class="object-cover w-full lg:h-64 rounded shadow-lg bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.title}
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<h3 class="mb-2 text-xl font-bold leading-tight sm:text-2xl font-heading">
|
||||
{
|
||||
BLOG?.post?.disabled ? (
|
||||
post.title
|
||||
) : (
|
||||
<a
|
||||
href={getPermalink(post.slug, 'post')}
|
||||
class="hover:text-primary-800 dark:hover:text-primary-700 transition ease-in duration-200"
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</h3>
|
||||
<p class="text-gray-500 dark:text-slate-400 text-lg">{post.excerpt || post.description}</p>
|
||||
<div class="relative h-0 pb-[56.25%] lg:h-64 overflow-hidden bg-gray-400 dark:bg-slate-700 rounded shadow-lg mb-6">
|
||||
{
|
||||
image && (
|
||||
<Picture
|
||||
src={image}
|
||||
class="object-cover w-full lg:h-64 rounded shadow-lg bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.title}
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<h3 class="mb-2 text-xl font-bold leading-tight sm:text-2xl font-heading">
|
||||
{
|
||||
BLOG?.post?.disabled ? (
|
||||
post.title
|
||||
) : (
|
||||
<a
|
||||
href={getPermalink(post.slug, 'post')}
|
||||
class="hover:text-primary-800 dark:hover:text-primary-700 transition ease-in duration-200"
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</h3>
|
||||
<p class="text-gray-500 dark:text-slate-400 text-lg">{post.excerpt || post.description}</p>
|
||||
</article>
|
||||
|
@ -3,8 +3,12 @@ const { title = await Astro.slots.render('default'), subtitle = await Astro.slot
|
||||
---
|
||||
|
||||
<header class="mb-8 md:mb-16 text-center max-w-3xl mx-auto">
|
||||
<h1 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter font-heading">
|
||||
{title}
|
||||
</h1>
|
||||
{subtitle && <div class="mt-2 md:mt-3 mx-auto text-xl text-gray-500 dark:text-slate-400 font-medium" set:html={subtitle} />}
|
||||
<h1 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter font-heading">
|
||||
{title}
|
||||
</h1>
|
||||
{
|
||||
subtitle && (
|
||||
<div class="mt-2 md:mt-3 mx-auto text-xl text-gray-500 dark:text-slate-400 font-medium" set:html={subtitle} />
|
||||
)
|
||||
}
|
||||
</header>
|
||||
|
@ -5,49 +5,49 @@ import { getBlogPermalink } from '~/utils/permalinks';
|
||||
import { findPostsByIds } from '~/utils/blog';
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
allPostsText?: string;
|
||||
allPostsLink?: string | URL;
|
||||
information?: string;
|
||||
postIds: string[];
|
||||
title?: string;
|
||||
allPostsText?: string;
|
||||
allPostsLink?: string | URL;
|
||||
information?: string;
|
||||
postIds: string[];
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
allPostsText = 'View all posts',
|
||||
allPostsLink = getBlogPermalink(),
|
||||
information = await Astro.slots.render('information'),
|
||||
postIds = [],
|
||||
title = await Astro.slots.render('title'),
|
||||
allPostsText = 'View all posts',
|
||||
allPostsLink = getBlogPermalink(),
|
||||
information = await Astro.slots.render('information'),
|
||||
postIds = [],
|
||||
} = Astro.props;
|
||||
|
||||
const posts = await findPostsByIds(postIds);
|
||||
---
|
||||
|
||||
<section class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
|
||||
<div class="flex flex-col lg:justify-between lg:flex-row mb-8">
|
||||
<div class="md:max-w-sm">
|
||||
{
|
||||
title && (
|
||||
<h2
|
||||
class="text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none group font-heading mb-2"
|
||||
set:html={title}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
allPostsText && allPostsLink && (
|
||||
<a
|
||||
class="text-gray-500 dark:text-slate-400 hover:text-primary-800 transition ease-in duration-200 block mb-6 md:mb-0"
|
||||
href={allPostsLink}
|
||||
>
|
||||
{allPostsText} »
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="flex flex-col lg:justify-between lg:flex-row mb-8">
|
||||
<div class="md:max-w-sm">
|
||||
{
|
||||
title && (
|
||||
<h2
|
||||
class="text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none group font-heading mb-2"
|
||||
set:html={title}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
allPostsText && allPostsLink && (
|
||||
<a
|
||||
class="text-gray-500 dark:text-slate-400 hover:text-primary-800 transition ease-in duration-200 block mb-6 md:mb-0"
|
||||
href={allPostsLink}
|
||||
>
|
||||
{allPostsText} »
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
{information && <p class="text-gray-700 dark:text-slate-400 lg:text-sm lg:max-w-md" set:html={information} />}
|
||||
</div>
|
||||
{information && <p class="text-gray-700 dark:text-slate-400 lg:text-sm lg:max-w-md" set:html={information} />}
|
||||
</div>
|
||||
|
||||
<Grid posts={posts} />
|
||||
<Grid posts={posts} />
|
||||
</section>
|
||||
|
@ -9,22 +9,22 @@ const posts = await findLatestPosts({ count });
|
||||
---
|
||||
|
||||
<section class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
|
||||
<div class="flex flex-col mb-6 lg:justify-between lg:flex-row md:mb-8">
|
||||
<h2 class="max-w-lg mb-2 text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none lg:mb-5 group font-heading">
|
||||
<span class="inline-block mb-1 sm:mb-4"
|
||||
>Latest articles<br class="hidden md:block" /> in our <a
|
||||
class="hover:text-primary-800 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200"
|
||||
href={getBlogPermalink()}>Blog</a
|
||||
>
|
||||
</span>
|
||||
</h2>
|
||||
<div class="flex flex-col mb-6 lg:justify-between lg:flex-row md:mb-8">
|
||||
<h2 class="max-w-lg mb-2 text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none lg:mb-5 group font-heading">
|
||||
<span class="inline-block mb-1 sm:mb-4"
|
||||
>Latest articles<br class="hidden md:block" /> in our <a
|
||||
class="hover:text-primary-800 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200"
|
||||
href={getBlogPermalink()}>Blog</a
|
||||
>
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
<p class="text-gray-700 dark:text-slate-400 lg:text-sm lg:max-w-md">
|
||||
The blog will be used to display AstroWind documentation. Each new article will be an important step that you will
|
||||
need to know to be an expert in creating a website using Astro + Tailwind CSS The blog does not exist yet, but
|
||||
very soon. Astro is a very interesting technology. Thanks.
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-gray-700 dark:text-slate-400 lg:text-sm lg:max-w-md">
|
||||
The blog will be used to display AstroWind documentation. Each new article will be an important step that you will
|
||||
need to know to be an expert in creating a website using Astro + Tailwind CSS The blog does not exist yet, but
|
||||
very soon. Astro is a very interesting technology. Thanks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Grid posts={posts} />
|
||||
<Grid posts={posts} />
|
||||
</section>
|
||||
|
@ -3,18 +3,18 @@ import Item from '~/components/blog/ListItem.astro';
|
||||
import type { Post } from '~/types';
|
||||
|
||||
export interface Props {
|
||||
posts: Array<Post>;
|
||||
posts: Array<Post>;
|
||||
}
|
||||
|
||||
const { posts } = Astro.props;
|
||||
---
|
||||
|
||||
<ul>
|
||||
{
|
||||
posts.map((post) => (
|
||||
<li class="mb-12 md:mb-20">
|
||||
<Item post={post} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
{
|
||||
posts.map((post) => (
|
||||
<li class="mb-12 md:mb-20">
|
||||
<Item post={post} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
@ -11,7 +11,7 @@ import { findImage } from '~/utils/images';
|
||||
import { getFormattedDate } from '~/utils/utils';
|
||||
|
||||
export interface Props {
|
||||
post: Post;
|
||||
post: Post;
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
@ -21,53 +21,49 @@ const link = !BLOG?.post?.disabled ? getPermalink(post.slug, 'post') : '';
|
||||
---
|
||||
|
||||
<article class={`max-w-md mx-auto md:max-w-none grid gap-6 md:gap-8 ${image ? 'md:grid-cols-2' : ''}`}>
|
||||
{
|
||||
image && (
|
||||
<a class="relative block group" href={link ?? 'javascript:void(0)'}>
|
||||
<div class="relative h-0 pb-[56.25%] md:pb-[75%] md:h-72 lg:pb-[56.25%] overflow-hidden bg-gray-400 dark:bg-slate-700 rounded shadow-lg">
|
||||
{image && (
|
||||
<Picture
|
||||
src={image}
|
||||
class="absolute inset-0 object-cover w-full h-full mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.title}
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<div class="mt-2">
|
||||
<header>
|
||||
<div class="mb-1">
|
||||
<span class="text-sm">
|
||||
<Icon name="tabler:clock" class="w-3.5 h-3.5 inline-block -mt-0.5 text-gray-500 dark:text-gray-400" />
|
||||
<time datetime={String(post.publishDate)}>{getFormattedDate(post.publishDate)}</time> ~
|
||||
{Math.ceil(post.readingTime)} min read
|
||||
</span>
|
||||
</div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold leading-tight mb-2 font-heading text-gray-700 dark:text-slate-300">
|
||||
{
|
||||
link ? (
|
||||
<a
|
||||
class="hover:text-primary-800 dark:hover:text-primary-700 transition ease-in duration-200"
|
||||
href={link}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
) : (
|
||||
post.title
|
||||
)
|
||||
}
|
||||
</h2>
|
||||
</header>
|
||||
{
|
||||
image && (
|
||||
<a class="relative block group" href={link ?? 'javascript:void(0)'}>
|
||||
<div class="relative h-0 pb-[56.25%] md:pb-[75%] md:h-72 lg:pb-[56.25%] overflow-hidden bg-gray-400 dark:bg-slate-700 rounded shadow-lg">
|
||||
{image && (
|
||||
<Picture
|
||||
src={image}
|
||||
class="absolute inset-0 object-cover w-full h-full mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.title}
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<div class="mt-2">
|
||||
<header>
|
||||
<div class="mb-1">
|
||||
<span class="text-sm">
|
||||
<Icon name="tabler:clock" class="w-3.5 h-3.5 inline-block -mt-0.5 text-gray-500 dark:text-gray-400" />
|
||||
<time datetime={String(post.publishDate)}>{getFormattedDate(post.publishDate)}</time> ~
|
||||
{Math.ceil(post.readingTime)} min read
|
||||
</span>
|
||||
</div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold leading-tight mb-2 font-heading text-gray-700 dark:text-slate-300">
|
||||
{
|
||||
link ? (
|
||||
<a class="hover:text-primary-800 dark:hover:text-primary-700 transition ease-in duration-200" href={link}>
|
||||
{post.title}
|
||||
</a>
|
||||
) : (
|
||||
post.title
|
||||
)
|
||||
}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
{post.excerpt && <p class="flex-grow text-gray-500 dark:text-slate-400 text-lg">{post.excerpt}</p>}
|
||||
<footer class="mt-5">
|
||||
<PostTags tags={post.tags} />
|
||||
|
||||
</footer>
|
||||
</div>
|
||||
{post.excerpt && <p class="flex-grow text-gray-500 dark:text-slate-400 text-lg">{post.excerpt}</p>}
|
||||
<footer class="mt-5">
|
||||
<PostTags tags={post.tags} />
|
||||
</footer>
|
||||
</div>
|
||||
</article>
|
||||
|
@ -10,70 +10,72 @@ import { getFormattedDate } from '~/utils/utils';
|
||||
import type { Post } from '~/types';
|
||||
|
||||
export interface Props {
|
||||
post: Post;
|
||||
url: string | URL;
|
||||
post: Post;
|
||||
url: string | URL;
|
||||
}
|
||||
|
||||
const { post, url } = Astro.props;
|
||||
---
|
||||
|
||||
<section class="py-8 sm:py-16 lg:py-20 mx-auto">
|
||||
<article>
|
||||
<header class={post.image ? '' : ''}>
|
||||
<div class="flex justify-between flex-col sm:flex-row max-w-3xl mx-auto mt-0 mb-2 px-4 sm:px-6 sm:items-center">
|
||||
<p>
|
||||
<Icon name="tabler:clock" class="w-4 h-4 inline-block -mt-1 text-gray-500 dark:text-gray-400" />
|
||||
<time datetime={String(post.publishDate)}>{getFormattedDate(post.publishDate)}</time> ~ {
|
||||
Math.ceil(post.readingTime)
|
||||
} min read
|
||||
</p>
|
||||
</div>
|
||||
<h1
|
||||
class="px-4 sm:px-6 max-w-3xl mx-auto text-4xl md:text-5xl font-bold leading-tighter tracking-tighter font-heading"
|
||||
>
|
||||
{post.title}
|
||||
</h1>
|
||||
<p class="max-w-3xl mx-auto mt-4 mb-8 px-4 sm:px-6 text-xl md:text-2xl text-gray-500 dark:text-slate-400 font-medium text-justify">
|
||||
{post.excerpt}
|
||||
</p>
|
||||
|
||||
{
|
||||
post.image ? (
|
||||
<Picture
|
||||
src={post.image}
|
||||
class="max-w-full lg:max-w-6xl mx-auto mb-6 sm:rounded-md bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.description || ''}
|
||||
loading="eager"
|
||||
aspectRatio={16 / 9}
|
||||
width={900}
|
||||
height={506}
|
||||
/>
|
||||
) : (
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<div class="border-t dark:border-slate-700" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</header>
|
||||
<div
|
||||
class="mx-auto px-6 sm:px-6 max-w-3xl prose prose-lg lg:prose-xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-primary-800 dark:prose-a:text-primary-400 prose-img:rounded-md prose-img:shadow-lg mt-8"
|
||||
>
|
||||
{
|
||||
post.Content ? (
|
||||
<>
|
||||
{/* @ts-ignore */}
|
||||
<post.Content />
|
||||
</>
|
||||
) : (
|
||||
<Fragment set:html={post.content} />
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="mx-auto px-6 sm:px-6 max-w-3xl mt-8 flex justify-between flex-col sm:flex-row">
|
||||
<PostTags tags={post.tags} class="mr-5" />
|
||||
<SocialShare url={url} text={post.title} class="mt-5 sm:mt-1 align-middle text-gray-500 dark:text-slate-600" />
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<header class={post.image ? '' : ''}>
|
||||
<div class="flex justify-between flex-col sm:flex-row max-w-3xl mx-auto mt-0 mb-2 px-4 sm:px-6 sm:items-center">
|
||||
<p>
|
||||
<Icon name="tabler:clock" class="w-4 h-4 inline-block -mt-1 text-gray-500 dark:text-gray-400" />
|
||||
<time datetime={String(post.publishDate)}>{getFormattedDate(post.publishDate)}</time> ~ {
|
||||
Math.ceil(post.readingTime)
|
||||
} min read
|
||||
</p>
|
||||
</div>
|
||||
<h1
|
||||
class="px-4 sm:px-6 max-w-3xl mx-auto text-4xl md:text-5xl font-bold leading-tighter tracking-tighter font-heading"
|
||||
>
|
||||
{post.title}
|
||||
</h1>
|
||||
<p
|
||||
class="max-w-3xl mx-auto mt-4 mb-8 px-4 sm:px-6 text-xl md:text-2xl text-gray-500 dark:text-slate-400 font-medium text-justify"
|
||||
>
|
||||
{post.excerpt}
|
||||
</p>
|
||||
|
||||
{
|
||||
post.image ? (
|
||||
<Picture
|
||||
src={post.image}
|
||||
class="max-w-full lg:max-w-6xl mx-auto mb-6 sm:rounded-md bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.description || ''}
|
||||
loading="eager"
|
||||
aspectRatio={16 / 9}
|
||||
width={900}
|
||||
height={506}
|
||||
/>
|
||||
) : (
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<div class="border-t dark:border-slate-700" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</header>
|
||||
<div
|
||||
class="mx-auto px-6 sm:px-6 max-w-3xl prose prose-lg lg:prose-xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-primary-800 dark:prose-a:text-primary-400 prose-img:rounded-md prose-img:shadow-lg mt-8"
|
||||
>
|
||||
{
|
||||
post.Content ? (
|
||||
<>
|
||||
{/* @ts-ignore */}
|
||||
<post.Content />
|
||||
</>
|
||||
) : (
|
||||
<Fragment set:html={post.content} />
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="mx-auto px-6 sm:px-6 max-w-3xl mt-8 flex justify-between flex-col sm:flex-row">
|
||||
<PostTags tags={post.tags} class="mr-5" />
|
||||
<SocialShare url={url} text={post.title} class="mt-5 sm:mt-1 align-middle text-gray-500 dark:text-slate-600" />
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
@ -4,7 +4,7 @@ import { getBlogPermalink } from '~/utils/permalinks';
|
||||
---
|
||||
|
||||
<div class="mx-auto px-6 sm:px-6 max-w-3xl pt-8 md:pt-4 pb-12 md:pb-20">
|
||||
<a class="btn btn-ghost px-3 md:px-3" href={getBlogPermalink()}
|
||||
><Icon name="tabler:chevron-left" class="w-5 h-5 mr-1 -ml-1.5" /> Back to Blog</a
|
||||
>
|
||||
<a class="btn btn-ghost px-3 md:px-3" href={getBlogPermalink()}
|
||||
><Icon name="tabler:chevron-left" class="w-5 h-5 mr-1 -ml-1.5" /> Back to Blog</a
|
||||
>
|
||||
</div>
|
||||
|
@ -3,117 +3,117 @@ import { SITE } from '~/config.mjs';
|
||||
---
|
||||
|
||||
<script is:inline define:vars={{ defaultTheme: SITE.defaultTheme }}>
|
||||
function applyTheme(theme) {
|
||||
if (theme === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
}
|
||||
function applyTheme(theme) {
|
||||
if (theme === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
}
|
||||
|
||||
if ((defaultTheme && defaultTheme.endsWith(':only')) || (!localStorage.theme && defaultTheme !== 'system')) {
|
||||
applyTheme(defaultTheme.replace(':only', ''));
|
||||
} else if (
|
||||
localStorage.theme === 'dark' ||
|
||||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
applyTheme('dark');
|
||||
} else {
|
||||
applyTheme('light');
|
||||
}
|
||||
if ((defaultTheme && defaultTheme.endsWith(':only')) || (!localStorage.theme && defaultTheme !== 'system')) {
|
||||
applyTheme(defaultTheme.replace(':only', ''));
|
||||
} else if (
|
||||
localStorage.theme === 'dark' ||
|
||||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
applyTheme('dark');
|
||||
} else {
|
||||
applyTheme('light');
|
||||
}
|
||||
|
||||
function attachEvent(selector, event, fn) {
|
||||
const matches = typeof selector === 'string' ? document.querySelectorAll(selector) : selector;
|
||||
if (matches && matches.length) {
|
||||
matches.forEach((elem) => {
|
||||
elem.addEventListener(event, (e) => fn(e, elem), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
function attachEvent(selector, event, fn) {
|
||||
const matches = typeof selector === 'string' ? document.querySelectorAll(selector) : selector;
|
||||
if (matches && matches.length) {
|
||||
matches.forEach((elem) => {
|
||||
elem.addEventListener(event, (e) => fn(e, elem), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
let lastKnownScrollPosition = window.scrollY;
|
||||
let ticking = true;
|
||||
window.onload = function () {
|
||||
let lastKnownScrollPosition = window.scrollY;
|
||||
let ticking = true;
|
||||
|
||||
attachEvent('[data-aw-toggle-menu]', 'click', function (_, elem) {
|
||||
elem.classList.toggle('expanded');
|
||||
document.body.classList.toggle('overflow-hidden');
|
||||
document.getElementById('header')?.classList.toggle('h-screen');
|
||||
document.querySelector('#header nav')?.classList.toggle('hidden');
|
||||
});
|
||||
attachEvent('[data-aw-toggle-menu]', 'click', function (_, elem) {
|
||||
elem.classList.toggle('expanded');
|
||||
document.body.classList.toggle('overflow-hidden');
|
||||
document.getElementById('header')?.classList.toggle('h-screen');
|
||||
document.querySelector('#header nav')?.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
attachEvent('[data-aw-toggle-color-scheme]', 'click', function () {
|
||||
if (defaultTheme.endsWith(':only')) {
|
||||
return;
|
||||
}
|
||||
document.documentElement.classList.toggle('dark');
|
||||
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
|
||||
});
|
||||
attachEvent('[data-aw-toggle-color-scheme]', 'click', function () {
|
||||
if (defaultTheme.endsWith(':only')) {
|
||||
return;
|
||||
}
|
||||
document.documentElement.classList.toggle('dark');
|
||||
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
|
||||
});
|
||||
|
||||
attachEvent('[data-aw-social-share]', 'click', function (_, elem) {
|
||||
const network = elem.getAttribute('data-aw-social-share');
|
||||
const url = encodeURIComponent(elem.getAttribute('data-aw-url'));
|
||||
const text = encodeURIComponent(elem.getAttribute('data-aw-text'));
|
||||
attachEvent('[data-aw-social-share]', 'click', function (_, elem) {
|
||||
const network = elem.getAttribute('data-aw-social-share');
|
||||
const url = encodeURIComponent(elem.getAttribute('data-aw-url'));
|
||||
const text = encodeURIComponent(elem.getAttribute('data-aw-text'));
|
||||
|
||||
let href;
|
||||
switch (network) {
|
||||
case 'facebook':
|
||||
href = `https://www.facebook.com/sharer.php?u=${url}`;
|
||||
break;
|
||||
case 'twitter':
|
||||
href = `https://twitter.com/intent/tweet?url=${url}&text=${text}`;
|
||||
break;
|
||||
case 'linkedin':
|
||||
href = `https://www.linkedin.com/shareArticle?mini=true&url=${url}&title=${text}`;
|
||||
break;
|
||||
case 'whatsapp':
|
||||
href = `https://wa.me/?text=${text}%20${url}`;
|
||||
break;
|
||||
case 'mail':
|
||||
href = `mailto:?subject=%22${text}%22&body=${text}%20${url}`;
|
||||
break;
|
||||
let href;
|
||||
switch (network) {
|
||||
case 'facebook':
|
||||
href = `https://www.facebook.com/sharer.php?u=${url}`;
|
||||
break;
|
||||
case 'twitter':
|
||||
href = `https://twitter.com/intent/tweet?url=${url}&text=${text}`;
|
||||
break;
|
||||
case 'linkedin':
|
||||
href = `https://www.linkedin.com/shareArticle?mini=true&url=${url}&title=${text}`;
|
||||
break;
|
||||
case 'whatsapp':
|
||||
href = `https://wa.me/?text=${text}%20${url}`;
|
||||
break;
|
||||
case 'mail':
|
||||
href = `mailto:?subject=%22${text}%22&body=${text}%20${url}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
const newlink = document.createElement('a');
|
||||
newlink.target = '_blank';
|
||||
newlink.href = href;
|
||||
newlink.click();
|
||||
});
|
||||
const newlink = document.createElement('a');
|
||||
newlink.target = '_blank';
|
||||
newlink.href = href;
|
||||
newlink.click();
|
||||
});
|
||||
|
||||
function appyHeaderStylesOnScroll() {
|
||||
const header = document.getElementById('header');
|
||||
if (lastKnownScrollPosition > 60 && !header.classList.contains('scroll')) {
|
||||
document.getElementById('header').classList.add('scroll');
|
||||
} else if (lastKnownScrollPosition <= 60 && header.classList.contains('scroll')) {
|
||||
document.getElementById('header').classList.remove('scroll');
|
||||
}
|
||||
ticking = false;
|
||||
}
|
||||
appyHeaderStylesOnScroll();
|
||||
function appyHeaderStylesOnScroll() {
|
||||
const header = document.getElementById('header');
|
||||
if (lastKnownScrollPosition > 60 && !header.classList.contains('scroll')) {
|
||||
document.getElementById('header').classList.add('scroll');
|
||||
} else if (lastKnownScrollPosition <= 60 && header.classList.contains('scroll')) {
|
||||
document.getElementById('header').classList.remove('scroll');
|
||||
}
|
||||
ticking = false;
|
||||
}
|
||||
appyHeaderStylesOnScroll();
|
||||
|
||||
attachEvent([document], 'scroll', function () {
|
||||
lastKnownScrollPosition = window.scrollY;
|
||||
attachEvent([document], 'scroll', function () {
|
||||
lastKnownScrollPosition = window.scrollY;
|
||||
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
appyHeaderStylesOnScroll();
|
||||
});
|
||||
ticking = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
appyHeaderStylesOnScroll();
|
||||
});
|
||||
ticking = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.onpageshow = function () {
|
||||
document.documentElement.classList.add('motion-safe:scroll-smooth');
|
||||
const elem = document.querySelector('[data-aw-toggle-menu]');
|
||||
if (elem) {
|
||||
elem.classList.remove('expanded');
|
||||
}
|
||||
document.body.classList.remove('overflow-hidden');
|
||||
document.getElementById('header')?.classList.remove('h-screen');
|
||||
document.querySelector('#header nav')?.classList.add('hidden');
|
||||
};
|
||||
window.onpageshow = function () {
|
||||
document.documentElement.classList.add('motion-safe:scroll-smooth');
|
||||
const elem = document.querySelector('[data-aw-toggle-menu]');
|
||||
if (elem) {
|
||||
elem.classList.remove('expanded');
|
||||
}
|
||||
document.body.classList.remove('overflow-hidden');
|
||||
document.getElementById('header')?.classList.remove('h-screen');
|
||||
document.querySelector('#header nav')?.classList.add('hidden');
|
||||
};
|
||||
</script>
|
||||
|
@ -2,5 +2,5 @@
|
||||
---
|
||||
|
||||
<span class="self-center ml-2 text-2xl md:text-xl font-bold text-gray-900 whitespace-nowrap dark:text-white">
|
||||
🚀 AstroWind</span
|
||||
🚀 AstroWind</span
|
||||
>
|
||||
|
@ -12,74 +12,74 @@ import Fonts from '~/components/common/Fonts.astro';
|
||||
import SplitbeeAnalytics from './SplitbeeAnalytics.astro';
|
||||
|
||||
export interface Props extends MetaSEO {
|
||||
dontUseTitleTemplate?: boolean;
|
||||
dontUseTitleTemplate?: boolean;
|
||||
}
|
||||
|
||||
const defaultImage = SITE.defaultImage
|
||||
? (
|
||||
await getImage({
|
||||
src: SITE.defaultImage,
|
||||
alt: 'Default image',
|
||||
width: 1200,
|
||||
height: 628,
|
||||
})
|
||||
).src
|
||||
: '';
|
||||
? (
|
||||
await getImage({
|
||||
src: SITE.defaultImage,
|
||||
alt: 'Default image',
|
||||
width: 1200,
|
||||
height: 628,
|
||||
})
|
||||
).src
|
||||
: '';
|
||||
|
||||
const {
|
||||
title = SITE.name,
|
||||
description = '',
|
||||
image: _image = defaultImage,
|
||||
title = SITE.name,
|
||||
description = '',
|
||||
image: _image = defaultImage,
|
||||
|
||||
canonical = getCanonical(String(Astro.url.pathname)),
|
||||
noindex = false,
|
||||
nofollow = false,
|
||||
canonical = getCanonical(String(Astro.url.pathname)),
|
||||
noindex = false,
|
||||
nofollow = false,
|
||||
|
||||
ogTitle = title,
|
||||
ogType = 'website',
|
||||
ogTitle = title,
|
||||
ogType = 'website',
|
||||
|
||||
dontUseTitleTemplate = false,
|
||||
dontUseTitleTemplate = false,
|
||||
} = Astro.props;
|
||||
|
||||
const image =
|
||||
typeof _image === 'string'
|
||||
? new URL(_image, Astro.site)
|
||||
: _image && typeof _image['src'] !== 'undefined'
|
||||
? // @ts-ignore
|
||||
new URL(getRelativeUrlByFilePath(_image.src), Astro.site)
|
||||
: null;
|
||||
typeof _image === 'string'
|
||||
? new URL(_image, Astro.site)
|
||||
: _image && typeof _image['src'] !== 'undefined'
|
||||
? // @ts-ignore
|
||||
new URL(getRelativeUrlByFilePath(_image.src), Astro.site)
|
||||
: null;
|
||||
---
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<AstroSeo
|
||||
title={title}
|
||||
titleTemplate={dontUseTitleTemplate ? '%s' : `%s — ${SITE.name}`}
|
||||
description={description}
|
||||
canonical={String(canonical)}
|
||||
noindex={noindex}
|
||||
nofollow={nofollow}
|
||||
openGraph={{
|
||||
url: String(canonical),
|
||||
title: ogTitle,
|
||||
description: description,
|
||||
type: ogType,
|
||||
images: image
|
||||
? [
|
||||
{
|
||||
url: image.toString(),
|
||||
alt: ogTitle,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
// site_name: 'SiteName',
|
||||
}}
|
||||
twitter={{
|
||||
// handle: '@handle',
|
||||
// site: '@site',
|
||||
cardType: image ? 'summary_large_image' : undefined,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={dontUseTitleTemplate ? '%s' : `%s — ${SITE.name}`}
|
||||
description={description}
|
||||
canonical={String(canonical)}
|
||||
noindex={noindex}
|
||||
nofollow={nofollow}
|
||||
openGraph={{
|
||||
url: String(canonical),
|
||||
title: ogTitle,
|
||||
description: description,
|
||||
type: ogType,
|
||||
images: image
|
||||
? [
|
||||
{
|
||||
url: image.toString(),
|
||||
alt: ogTitle,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
// site_name: 'SiteName',
|
||||
}}
|
||||
twitter={{
|
||||
// handle: '@handle',
|
||||
// site: '@site',
|
||||
cardType: image ? 'summary_large_image' : undefined,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Fonts />
|
||||
|
@ -3,32 +3,32 @@ import { Icon } from 'astro-icon';
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
|
||||
export interface Props {
|
||||
prevUrl: string;
|
||||
nextUrl: string;
|
||||
prevText?: string;
|
||||
nextText?: string;
|
||||
prevUrl: string;
|
||||
nextUrl: string;
|
||||
prevText?: string;
|
||||
nextText?: string;
|
||||
}
|
||||
|
||||
const { prevUrl, nextUrl, prevText = 'Newer posts', nextText = 'Older posts' } = Astro.props;
|
||||
---
|
||||
|
||||
{
|
||||
(prevUrl || nextUrl) && (
|
||||
<div class="container flex">
|
||||
<div class="flex flex-row mx-auto container justify-between">
|
||||
<a href={getPermalink(prevUrl)} class={`btn btn-ghost px-3 mr-2 ${!prevUrl ? 'invisible' : ''}`}>
|
||||
<div class="flex flex-row align-middle">
|
||||
<Icon name="tabler:chevron-left" class="w-6 h-6" />
|
||||
<p class="ml-2">{prevText}</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href={getPermalink(nextUrl)} class={`btn btn-ghost px-3 ${!nextUrl ? 'invisible' : ''}`}>
|
||||
<div class="flex flex-row align-middle">
|
||||
<span class="mr-2">{nextText}</span>
|
||||
<Icon name="tabler:chevron-right" class="w-6 h-6" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
(prevUrl || nextUrl) && (
|
||||
<div class="container flex">
|
||||
<div class="flex flex-row mx-auto container justify-between">
|
||||
<a href={getPermalink(prevUrl)} class={`btn btn-ghost px-3 mr-2 ${!prevUrl ? 'invisible' : ''}`}>
|
||||
<div class="flex flex-row align-middle">
|
||||
<Icon name="tabler:chevron-left" class="w-6 h-6" />
|
||||
<p class="ml-2">{prevText}</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href={getPermalink(nextUrl)} class={`btn btn-ghost px-3 ${!nextUrl ? 'invisible' : ''}`}>
|
||||
<div class="flex flex-row align-middle">
|
||||
<span class="mr-2">{nextText}</span>
|
||||
<Icon name="tabler:chevron-right" class="w-6 h-6" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -2,29 +2,29 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
export interface Props {
|
||||
text: string;
|
||||
url: string | URL;
|
||||
class?: string;
|
||||
text: string;
|
||||
url: string | URL;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { text, url, class: className = 'inline-block' } = Astro.props;
|
||||
---
|
||||
|
||||
<div class={className}>
|
||||
<span class="align-super font-bold dark:text-slate-400">Share:</span>
|
||||
<button class="ml-2" title="Twitter Share" data-aw-social-share="twitter" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:twitter" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Facebook Share" data-aw-social-share="facebook" data-aw-url={url}
|
||||
><Icon name="logos:facebook" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Linkedin Share" data-aw-social-share="linkedin" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:linkedin-icon" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Whatsapp Share" data-aw-social-share="whatsapp" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:whatsapp" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Email Share" data-aw-social-share="mail" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="tabler:mail" class="w-6 h-6" />
|
||||
</button>
|
||||
<span class="align-super font-bold dark:text-slate-400">Share:</span>
|
||||
<button class="ml-2" title="Twitter Share" data-aw-social-share="twitter" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:twitter" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Facebook Share" data-aw-social-share="facebook" data-aw-url={url}
|
||||
><Icon name="logos:facebook" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Linkedin Share" data-aw-social-share="linkedin" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:linkedin-icon" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Whatsapp Share" data-aw-social-share="whatsapp" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:whatsapp" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Email Share" data-aw-social-share="mail" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="tabler:mail" class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -5,21 +5,30 @@ import { BLOG } from '~/config.mjs';
|
||||
import type { Post } from '~/types';
|
||||
|
||||
export interface Props {
|
||||
tags: Post['tags'];
|
||||
class?: string;
|
||||
tags: Post['tags'];
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { tags, class: className = 'text-sm' } = Astro.props;
|
||||
---
|
||||
|
||||
{
|
||||
tags && Array.isArray(tags) && (
|
||||
<ul class={className}>
|
||||
{tags.map((tag) => (
|
||||
<li class="bg-gray-100 dark:bg-slate-700 inline-block mr-2 mb-2 py-0.5 px-2 lowercase font-medium">
|
||||
{BLOG?.tag?.disabled ? tag : <a href={getPermalink(tag, 'tag')} class="text-gray-600 dark:text-slate-300 hover:text-primary-800 dark:hover:text-gray-200">{tag}</a>}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
tags && Array.isArray(tags) && (
|
||||
<ul class={className}>
|
||||
{tags.map((tag) => (
|
||||
<li class="bg-gray-100 dark:bg-slate-700 inline-block mr-2 mb-2 py-0.5 px-2 lowercase font-medium">
|
||||
{BLOG?.tag?.disabled ? (
|
||||
tag
|
||||
) : (
|
||||
<a
|
||||
href={getPermalink(tag, 'tag')}
|
||||
class="text-gray-600 dark:text-slate-300 hover:text-primary-800 dark:hover:text-gray-200"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
@ -2,21 +2,21 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
export interface Props {
|
||||
label?: string;
|
||||
class?: string;
|
||||
iconClass?: string;
|
||||
iconName?: string;
|
||||
label?: string;
|
||||
class?: string;
|
||||
iconClass?: string;
|
||||
iconName?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
label = 'Toggle Menu',
|
||||
class:
|
||||
className = 'ml-1.5 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center transition',
|
||||
iconClass = 'w-6 h-6',
|
||||
iconName = 'tabler:menu',
|
||||
label = 'Toggle Menu',
|
||||
class:
|
||||
className = 'ml-1.5 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center transition',
|
||||
iconClass = 'w-6 h-6',
|
||||
iconName = 'tabler:menu',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<button type="button" class={className} aria-label={label} data-aw-toggle-menu>
|
||||
<Icon name={iconName} class={iconClass} optimize={false} />
|
||||
<Icon name={iconName} class={iconClass} optimize={false} />
|
||||
</button>
|
||||
|
@ -2,21 +2,21 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
export interface Props {
|
||||
label?: string;
|
||||
class?: string;
|
||||
iconClass?: string;
|
||||
iconName?: string;
|
||||
label?: string;
|
||||
class?: string;
|
||||
iconClass?: string;
|
||||
iconName?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
label = 'Toggle between Dark and Light mode',
|
||||
class:
|
||||
className = 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center',
|
||||
iconClass = 'w-6 h-6',
|
||||
iconName = 'tabler:sun',
|
||||
label = 'Toggle between Dark and Light mode',
|
||||
class:
|
||||
className = 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center',
|
||||
iconClass = 'w-6 h-6',
|
||||
iconName = 'tabler:sun',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<button type="button" class={className} aria-label={label} data-aw-toggle-color-scheme>
|
||||
<Icon name={iconName} class={iconClass} />
|
||||
<Icon name={iconName} class={iconClass} />
|
||||
</button>
|
||||
|
@ -3,26 +3,26 @@ import { getPermalink } from '~/utils/permalinks';
|
||||
---
|
||||
|
||||
<div
|
||||
class="hidden md:block bg-primary-900 dark:bg-slate-800 dark:border-slate-800 dark:text-slate-400 border-b border-primary-900 text-sm px-3 py-2 text-gray-200 overflow-hidden whitespace-nowrap text-ellipsis"
|
||||
class="hidden md:block bg-primary-900 dark:bg-slate-800 dark:border-slate-800 dark:text-slate-400 border-b border-primary-900 text-sm px-3 py-2 text-gray-200 overflow-hidden whitespace-nowrap text-ellipsis"
|
||||
>
|
||||
<span class="text-xs py-0.5 px-1 bg-primary-800 dark:bg-slate-700 dark:text-slate-300 font-semibold">NEW</span>
|
||||
<a
|
||||
href={getPermalink('useful-resources-to-create-websites', 'post')}
|
||||
class="hover:underline text-gray-200 dark:text-slate-400"
|
||||
>Useful tools and resources to create a professional website »</a
|
||||
>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="float-right"
|
||||
title="If you like AstroWind, give us a star."
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
>
|
||||
<img
|
||||
src="https://img.shields.io/github/stars/onwidget/astrowind.svg?style=social&label=Stars&maxAge=86400"
|
||||
alt="Follow @onWidget"
|
||||
width="84"
|
||||
height="20"
|
||||
/>
|
||||
</a>
|
||||
<span class="text-xs py-0.5 px-1 bg-primary-800 dark:bg-slate-700 dark:text-slate-300 font-semibold">NEW</span>
|
||||
<a
|
||||
href={getPermalink('useful-resources-to-create-websites', 'post')}
|
||||
class="hover:underline text-gray-200 dark:text-slate-400"
|
||||
>Useful tools and resources to create a professional website »</a
|
||||
>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="float-right"
|
||||
title="If you like AstroWind, give us a star."
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
>
|
||||
<img
|
||||
src="https://img.shields.io/github/stars/onwidget/astrowind.svg?style=social&label=Stars&maxAge=86400"
|
||||
alt="Follow @onWidget"
|
||||
width="84"
|
||||
height="20"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -2,54 +2,56 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
interface CallToAction {
|
||||
text: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
text: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
callToAction?: string | CallToAction;
|
||||
title?: string;
|
||||
description?: string;
|
||||
callToAction?: string | CallToAction;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
callToAction = await Astro.slots.render('callToAction'),
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
callToAction = await Astro.slots.render('callToAction'),
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class="relative">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="max-w-3xl mx-auto text-center p-6 rounded-md shadow-xl dark:shadow-none dark:border dark:border-slate-600">
|
||||
{
|
||||
title && (
|
||||
<h2
|
||||
class="text-4xl md:text-4xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{subtitle && <p class="text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />}
|
||||
{
|
||||
typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
callToAction &&
|
||||
callToAction.text &&
|
||||
callToAction.href && (
|
||||
<div class="mt-6 max-w-xs mx-auto">
|
||||
<a class="btn btn-primary w-full sm:w-auto" href={callToAction.href} target="_blank" rel="noopener">
|
||||
{callToAction.icon && <Icon name={callToAction.icon} class="w-5 h-5 mr-1 -ml-1.5" />}
|
||||
{callToAction.text}
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div
|
||||
class="max-w-3xl mx-auto text-center p-6 rounded-md shadow-xl dark:shadow-none dark:border dark:border-slate-600"
|
||||
>
|
||||
{
|
||||
title && (
|
||||
<h2
|
||||
class="text-4xl md:text-4xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{subtitle && <p class="text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />}
|
||||
{
|
||||
typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
callToAction &&
|
||||
callToAction.text &&
|
||||
callToAction.href && (
|
||||
<div class="mt-6 max-w-xs mx-auto">
|
||||
<a class="btn btn-primary w-full sm:w-auto" href={callToAction.href} target="_blank" rel="noopener">
|
||||
{callToAction.icon && <Icon name={callToAction.icon} class="w-5 h-5 mr-1 -ml-1.5" />}
|
||||
{callToAction.text}
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -1,107 +1,107 @@
|
||||
---
|
||||
import Icon from "astro-icon"
|
||||
import Icon from 'astro-icon';
|
||||
import { Picture } from '@astrojs/image/components';
|
||||
|
||||
interface Item {
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
content?: string;
|
||||
items?: Array<Item>;
|
||||
image?: string | any; // TODO: find HTMLElementProps
|
||||
isReversed?: boolean;
|
||||
isAfterContent?: boolean;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
content?: string;
|
||||
items?: Array<Item>;
|
||||
image?: string | any; // TODO: find HTMLElementProps
|
||||
isReversed?: boolean;
|
||||
isAfterContent?: boolean;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
content = await Astro.slots.render('content'),
|
||||
items = [],
|
||||
image = await Astro.slots.render('image'),
|
||||
isReversed = false,
|
||||
isAfterContent = false,
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
content = await Astro.slots.render('content'),
|
||||
items = [],
|
||||
image = await Astro.slots.render('image'),
|
||||
isReversed = false,
|
||||
isAfterContent = false,
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class={`bg-primary-50 dark:bg-slate-800 py-16 md:py-20 ${isAfterContent ? 'pt-0 md:pt-0' : ''}`}>
|
||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="mx-auto max-w-6xl p-4 md:px-8">
|
||||
<div class={`md:flex ${isReversed ? 'md:flex-row-reverse' : ''} md:gap-16`}>
|
||||
<div class="md:basis-1/2 self-center">
|
||||
{content && <div class="mb-12 text-lg text-gray-600 dark:text-slate-400" set:html={content} />}
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="mx-auto max-w-6xl p-4 md:px-8">
|
||||
<div class={`md:flex ${isReversed ? 'md:flex-row-reverse' : ''} md:gap-16`}>
|
||||
<div class="md:basis-1/2 self-center">
|
||||
{content && <div class="mb-12 text-lg text-gray-600 dark:text-slate-400" set:html={content} />}
|
||||
|
||||
{
|
||||
items && (
|
||||
<div class="space-y-8">
|
||||
{items.map(({ title: title2, description, icon }) => (
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="flex h-7 w-7 items-center justify-center rounded-full bg-blue-800 text-gray-50">
|
||||
<Icon name={icon? icon : "tabler:check"} class="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
{title2 && <h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-white">{title2}</h3>}
|
||||
{description && <p class="mt-2 text-gray-600 dark:text-slate-400" set:html={description} />}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div aria-hidden="true" class="mt-10 md:mt-0 md:basis-1/2">
|
||||
{
|
||||
image && (
|
||||
<div class="relative m-auto max-w-4xl">
|
||||
{typeof image === 'string' ? (
|
||||
<Fragment set:html={image} />
|
||||
) : (
|
||||
<Picture
|
||||
class="mx-auto w-full rounded-lg bg-gray-500 shadow-lg"
|
||||
width={500}
|
||||
height={500}
|
||||
widths={[400, 768]}
|
||||
sizes="(max-width: 768px) 100vw, 432px"
|
||||
aspectRatio="500:500"
|
||||
{...image}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
items && (
|
||||
<div class="space-y-8">
|
||||
{items.map(({ title: title2, description, icon }) => (
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="flex h-7 w-7 items-center justify-center rounded-full bg-blue-800 text-gray-50">
|
||||
<Icon name={icon ? icon : 'tabler:check'} class="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
{title2 && <h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-white">{title2}</h3>}
|
||||
{description && <p class="mt-2 text-gray-600 dark:text-slate-400" set:html={description} />}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div aria-hidden="true" class="mt-10 md:mt-0 md:basis-1/2">
|
||||
{
|
||||
image && (
|
||||
<div class="relative m-auto max-w-4xl">
|
||||
{typeof image === 'string' ? (
|
||||
<Fragment set:html={image} />
|
||||
) : (
|
||||
<Picture
|
||||
class="mx-auto w-full rounded-lg bg-gray-500 shadow-lg"
|
||||
width={500}
|
||||
height={500}
|
||||
widths={[400, 768]}
|
||||
sizes="(max-width: 768px) 100vw, 432px"
|
||||
aspectRatio="500:500"
|
||||
{...image}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -2,65 +2,65 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
interface Item {
|
||||
question: string;
|
||||
answer: string;
|
||||
question: string;
|
||||
answer: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items: Array<Array<Item>>;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items: Array<Array<Item>>;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
|
||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="max-w-xl mb-10 md:mx-auto md:text-center lg:max-w-2xl md:mb-12">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="max-w-lg mb-4 text-3xl font-bold leading-none md:tracking-tight sm:text-4xl md:mx-auto font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
{subtitle && <p class="max-w-3xl mx-auto text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="max-w-screen-xl sm:mx-auto">
|
||||
<div class="grid grid-cols-1 gap-x-8 gap-y-8 lg:gap-x-16 md:grid-cols-2">
|
||||
{
|
||||
items &&
|
||||
items.map((subitems) => (
|
||||
<div class="space-y-8">
|
||||
{subitems.map(({ question, answer }) => (
|
||||
<div>
|
||||
<h3 class="mb-4 text-xl font-bold">
|
||||
<Icon name="tabler:arrow-down-right" class="w-7 h-7 text-primary-800 inline-block" />
|
||||
{question}
|
||||
</h3>
|
||||
{answer && <div class="text-gray-700 dark:text-gray-400" set:html={answer} />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="max-w-xl mb-10 md:mx-auto md:text-center lg:max-w-2xl md:mb-12">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="max-w-lg mb-4 text-3xl font-bold leading-none md:tracking-tight sm:text-4xl md:mx-auto font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
{subtitle && <p class="max-w-3xl mx-auto text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="max-w-screen-xl sm:mx-auto">
|
||||
<div class="grid grid-cols-1 gap-x-8 gap-y-8 lg:gap-x-16 md:grid-cols-2">
|
||||
{
|
||||
items &&
|
||||
items.map((subitems) => (
|
||||
<div class="space-y-8">
|
||||
{subitems.map(({ question, answer }) => (
|
||||
<div>
|
||||
<h3 class="mb-4 text-xl font-bold">
|
||||
<Icon name="tabler:arrow-down-right" class="w-7 h-7 text-primary-800 inline-block" />
|
||||
{question}
|
||||
</h3>
|
||||
{answer && <div class="text-gray-700 dark:text-gray-400" set:html={answer} />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,70 +2,70 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
interface Item {
|
||||
title: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items: Array<Array<Item>>;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items: Array<Array<Item>>;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class="scroll-mt-16" id="features">
|
||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:px-8 lg:py-20">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:px-8 lg:py-20">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class="grid mx-auto space-y-6 md:grid-cols-2 md:space-y-0">
|
||||
{
|
||||
items.map((subitems) => (
|
||||
<div class="space-y-8 sm:px-8">
|
||||
{subitems.map(({ title, description, icon }) => (
|
||||
<div class="flex flex-row max-w-md">
|
||||
<div class="mb-4 mr-4">
|
||||
<div class="flex items-center justify-center w-12 h-12 rounded-full bg-primary-800 dark:bg-primary-700">
|
||||
{icon && <Icon name={icon} class="w-6 h-6 text-white icon-light" />}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="mb-3 text-xl font-bold">{title}</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400" set:html={description} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class="grid mx-auto space-y-6 md:grid-cols-2 md:space-y-0">
|
||||
{
|
||||
items.map((subitems) => (
|
||||
<div class="space-y-8 sm:px-8">
|
||||
{subitems.map(({ title, description, icon }) => (
|
||||
<div class="flex flex-row max-w-md">
|
||||
<div class="mb-4 mr-4">
|
||||
<div class="flex items-center justify-center w-12 h-12 rounded-full bg-primary-800 dark:bg-primary-700">
|
||||
{icon && <Icon name={icon} class="w-6 h-6 text-white icon-light" />}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="mb-3 text-xl font-bold">{title}</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400" set:html={description} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -2,65 +2,68 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
interface Item {
|
||||
title?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items: Array<Item>;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items: Array<Item>;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class="relative">
|
||||
<div class="absolute inset-0 bg-primary-50 dark:bg-slate-800 pointer-events-none mb-32" aria-hidden="true"></div>
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 -mb-12">
|
||||
<div class="py-4 pt-8 sm:py-6 lg:py-8 lg:pt-12">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="mb-8 md:mx-auto text-center max-w-3xl">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class={`grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 my-12 dark:text-white items-stretch`}>
|
||||
{
|
||||
items.map(({ title, description, icon }) => (
|
||||
<div class="relative flex flex-col p-6 bg-white dark:bg-slate-900 rounded shadow-lg hover:shadow-md transition border border-transparent dark:border-slate-800">
|
||||
<div class="flex items-center">
|
||||
<Icon name={icon} class="w-10 h-10" />
|
||||
<div class="ml-4 text-xl font-bold">{title}</div>
|
||||
</div>
|
||||
{description && <p class="text-gray-500 dark:text-gray-400 text-md mt-4" set:html={description} />}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-primary-50 dark:bg-slate-800 pointer-events-none mb-32" aria-hidden="true"></div>
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 -mb-12">
|
||||
<div class="py-4 pt-8 sm:py-6 lg:py-8 lg:pt-12">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="mb-8 md:mx-auto text-center max-w-3xl">
|
||||
{highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
|
||||
{subtitle && (
|
||||
<p
|
||||
class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400"
|
||||
set:html={subtitle}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class={`grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 my-12 dark:text-white items-stretch`}>
|
||||
{
|
||||
items.map(({ title, description, icon }) => (
|
||||
<div class="relative flex flex-col p-6 bg-white dark:bg-slate-900 rounded shadow-lg hover:shadow-md transition border border-transparent dark:border-slate-800">
|
||||
<div class="flex items-center">
|
||||
<Icon name={icon} class="w-10 h-10" />
|
||||
<div class="ml-4 text-xl font-bold">{title}</div>
|
||||
</div>
|
||||
{description && <p class="text-gray-500 dark:text-gray-400 text-md mt-4" set:html={description} />}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -3,126 +3,126 @@ import { Icon } from 'astro-icon';
|
||||
import { getHomePermalink, getPermalink } from '~/utils/permalinks';
|
||||
|
||||
const links = [
|
||||
{
|
||||
title: 'Product',
|
||||
items: [
|
||||
{ title: 'Features', href: '#' },
|
||||
{ title: 'Security', href: '#' },
|
||||
{ title: 'Team', href: '#' },
|
||||
{ title: 'Enterprise', href: '#' },
|
||||
{ title: 'Customer stories', href: '#' },
|
||||
{ title: 'Pricing', href: '#' },
|
||||
{ title: 'Resources', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Platform',
|
||||
items: [
|
||||
{ title: 'Developer API', href: '#' },
|
||||
{ title: 'Partners', href: '#' },
|
||||
{ title: 'Atom', href: '#' },
|
||||
{ title: 'Electron', href: '#' },
|
||||
{ title: 'AstroWind Desktop', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Support',
|
||||
items: [
|
||||
{ title: 'Docs', href: '#' },
|
||||
{ title: 'Community Forum', href: '#' },
|
||||
{ title: 'Professional Services', href: '#' },
|
||||
{ title: 'Skills', href: '#' },
|
||||
{ title: 'Status', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Company',
|
||||
items: [
|
||||
{ title: 'About', href: '#' },
|
||||
{ title: 'Blog', href: '#' },
|
||||
{ title: 'Careers', href: '#' },
|
||||
{ title: 'Press', href: '#' },
|
||||
{ title: 'Inclusion', href: '#' },
|
||||
{ title: 'Social Impact', href: '#' },
|
||||
{ title: 'Shop', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Product',
|
||||
items: [
|
||||
{ title: 'Features', href: '#' },
|
||||
{ title: 'Security', href: '#' },
|
||||
{ title: 'Team', href: '#' },
|
||||
{ title: 'Enterprise', href: '#' },
|
||||
{ title: 'Customer stories', href: '#' },
|
||||
{ title: 'Pricing', href: '#' },
|
||||
{ title: 'Resources', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Platform',
|
||||
items: [
|
||||
{ title: 'Developer API', href: '#' },
|
||||
{ title: 'Partners', href: '#' },
|
||||
{ title: 'Atom', href: '#' },
|
||||
{ title: 'Electron', href: '#' },
|
||||
{ title: 'AstroWind Desktop', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Support',
|
||||
items: [
|
||||
{ title: 'Docs', href: '#' },
|
||||
{ title: 'Community Forum', href: '#' },
|
||||
{ title: 'Professional Services', href: '#' },
|
||||
{ title: 'Skills', href: '#' },
|
||||
{ title: 'Status', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Company',
|
||||
items: [
|
||||
{ title: 'About', href: '#' },
|
||||
{ title: 'Blog', href: '#' },
|
||||
{ title: 'Careers', href: '#' },
|
||||
{ title: 'Press', href: '#' },
|
||||
{ title: 'Inclusion', href: '#' },
|
||||
{ title: 'Social Impact', href: '#' },
|
||||
{ title: 'Shop', href: '#' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const social = [
|
||||
{ label: 'Twitter', icon: 'tabler:brand-twitter', href: '#' },
|
||||
{ label: 'Instagram', icon: 'tabler:brand-instagram', href: '#' },
|
||||
{ label: 'Facebook', icon: 'tabler:brand-facebook', href: '#' },
|
||||
{ label: 'RSS', icon: 'tabler:rss', href: getPermalink('/rss.xml') },
|
||||
{ label: 'Github', icon: 'tabler:brand-github', href: 'https://github.com/onwidget/astrowind' },
|
||||
{ label: 'Twitter', icon: 'tabler:brand-twitter', href: '#' },
|
||||
{ label: 'Instagram', icon: 'tabler:brand-instagram', href: '#' },
|
||||
{ label: 'Facebook', icon: 'tabler:brand-facebook', href: '#' },
|
||||
{ label: 'RSS', icon: 'tabler:rss', href: getPermalink('/rss.xml') },
|
||||
{ label: 'Github', icon: 'tabler:brand-github', href: 'https://github.com/onwidget/astrowind' },
|
||||
];
|
||||
---
|
||||
|
||||
<footer class="border-t border-gray-200 dark:border-slate-800">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid grid-cols-12 gap-4 gap-y-8 sm:gap-8 py-8 md:py-12">
|
||||
<div class="col-span-12 lg:col-span-4">
|
||||
<div class="mb-2">
|
||||
<a class="inline-block font-bold text-xl" href={getHomePermalink()}>AstroWind</a>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 dark:text-gray-400 hover:underline transition duration-150 ease-in-out"
|
||||
href={getPermalink('/terms')}>Terms</a
|
||||
> ·
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 dark:text-gray-400 hover:underline transition duration-150 ease-in-out"
|
||||
href={getPermalink('/privacy')}>Privacy Policy</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
links.map(({ title, items }) => (
|
||||
<div class="col-span-6 md:col-span-3 lg:col-span-2">
|
||||
<div class="text-gray-800 dark:text-gray-300 font-medium mb-2">{title}</div>
|
||||
{items && Array.isArray(items) && items.length > 0 && (
|
||||
<ul class="text-sm">
|
||||
{items.map(({ title, href }) => (
|
||||
<li class="mb-2">
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out"
|
||||
href={href}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="md:flex md:items-center md:justify-between py-6 md:py-8">
|
||||
<ul class="flex mb-4 md:order-1 -ml-2 md:ml-4 md:mb-0">
|
||||
{
|
||||
social.map(({ label, href, icon }) => (
|
||||
<li>
|
||||
<a
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
|
||||
aria-label={label}
|
||||
href={href}
|
||||
>
|
||||
<Icon name={icon} class="w-5 h-5" />
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid grid-cols-12 gap-4 gap-y-8 sm:gap-8 py-8 md:py-12">
|
||||
<div class="col-span-12 lg:col-span-4">
|
||||
<div class="mb-2">
|
||||
<a class="inline-block font-bold text-xl" href={getHomePermalink()}>AstroWind</a>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 dark:text-gray-400 hover:underline transition duration-150 ease-in-out"
|
||||
href={getPermalink('/terms')}>Terms</a
|
||||
> ·
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 dark:text-gray-400 hover:underline transition duration-150 ease-in-out"
|
||||
href={getPermalink('/privacy')}>Privacy Policy</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
links.map(({ title, items }) => (
|
||||
<div class="col-span-6 md:col-span-3 lg:col-span-2">
|
||||
<div class="text-gray-800 dark:text-gray-300 font-medium mb-2">{title}</div>
|
||||
{items && Array.isArray(items) && items.length > 0 && (
|
||||
<ul class="text-sm">
|
||||
{items.map(({ title, href }) => (
|
||||
<li class="mb-2">
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out"
|
||||
href={href}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="md:flex md:items-center md:justify-between py-6 md:py-8">
|
||||
<ul class="flex mb-4 md:order-1 -ml-2 md:ml-4 md:mb-0">
|
||||
{
|
||||
social.map(({ label, href, icon }) => (
|
||||
<li>
|
||||
<a
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
|
||||
aria-label={label}
|
||||
href={href}
|
||||
>
|
||||
<Icon name={icon} class="w-5 h-5" />
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div class="text-sm text-gray-700 mr-4 dark:text-slate-400">
|
||||
<span
|
||||
class="w-5 h-5 md:w-6 md:h-6 md:-mt-0.5 bg-cover mr-1.5 float-left rounded-sm bg-[url(https://onwidget.com/favicon/favicon-32x32.png)]"
|
||||
>
|
||||
</span>
|
||||
Made by <a class="text-blue-600 hover:underline dark:text-gray-200" href="https://onwidget.com/"> onWidget</a> ·
|
||||
All rights reserved.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-700 mr-4 dark:text-slate-400">
|
||||
<span
|
||||
class="w-5 h-5 md:w-6 md:h-6 md:-mt-0.5 bg-cover mr-1.5 float-left rounded-sm bg-[url(https://onwidget.com/favicon/favicon-32x32.png)]"
|
||||
>
|
||||
</span>
|
||||
Made by <a class="text-blue-600 hover:underline dark:text-gray-200" href="https://onwidget.com/"> onWidget</a> ·
|
||||
All rights reserved.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
@ -7,117 +7,117 @@ import ToggleMenu from '~/components/common/ToggleMenu.astro';
|
||||
import { getHomePermalink, getBlogPermalink, getPermalink } from '~/utils/permalinks';
|
||||
|
||||
const links = [
|
||||
{
|
||||
text: 'Pages',
|
||||
links: [
|
||||
{
|
||||
text: 'Features',
|
||||
href: "#",
|
||||
},
|
||||
{
|
||||
text: 'Pricing',
|
||||
href: "#",
|
||||
},
|
||||
{
|
||||
text: 'About us',
|
||||
href: "#",
|
||||
},
|
||||
{
|
||||
text: 'Contact',
|
||||
href: "#",
|
||||
},
|
||||
{
|
||||
text: 'Terms',
|
||||
href: getPermalink('/terms'),
|
||||
},
|
||||
{
|
||||
text: 'Privacy policy',
|
||||
href: getPermalink('/privacy'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Resources',
|
||||
href: getPermalink('useful-resources-to-create-websites', 'post'),
|
||||
},
|
||||
{
|
||||
text: 'Blog',
|
||||
href: getBlogPermalink(),
|
||||
},
|
||||
{
|
||||
text: 'Pages',
|
||||
links: [
|
||||
{
|
||||
text: 'Features',
|
||||
href: '#',
|
||||
},
|
||||
{
|
||||
text: 'Pricing',
|
||||
href: '#',
|
||||
},
|
||||
{
|
||||
text: 'About us',
|
||||
href: '#',
|
||||
},
|
||||
{
|
||||
text: 'Contact',
|
||||
href: '#',
|
||||
},
|
||||
{
|
||||
text: 'Terms',
|
||||
href: getPermalink('/terms'),
|
||||
},
|
||||
{
|
||||
text: 'Privacy policy',
|
||||
href: getPermalink('/privacy'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Resources',
|
||||
href: getPermalink('useful-resources-to-create-websites', 'post'),
|
||||
},
|
||||
{
|
||||
text: 'Blog',
|
||||
href: getBlogPermalink(),
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<header class="sticky top-0 z-40 flex-none mx-auto w-full transition-all ease-in duration-100" id="header">
|
||||
<div class="py-3 px-3 md:py-3.5 md:px-4 mx-auto w-full md:flex md:justify-between max-w-6xl">
|
||||
<div class="flex justify-between">
|
||||
<a class="flex items-center" href={getHomePermalink()}>
|
||||
<Logo />
|
||||
</a>
|
||||
<div class="flex items-center md:hidden">
|
||||
<ToggleTheme />
|
||||
<ToggleMenu />
|
||||
</div>
|
||||
</div>
|
||||
<nav
|
||||
class="items-center w-full md:w-auto hidden md:flex text-gray-600 dark:text-slate-200 h-[calc(100vh-72px)] md:h-auto overflow-y-auto md:overflow-visible"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<ul class="flex flex-col pt-8 md:pt-0 md:flex-row md:self-center w-full md:w-auto text-xl md:text-base">
|
||||
{
|
||||
links.map(({ text, href, links }) => (
|
||||
<li class={links?.length ? 'dropdown' : ''}>
|
||||
{links?.length ? (
|
||||
<>
|
||||
<button class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out">
|
||||
{text} <Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 hidden md:inline" />
|
||||
</button>
|
||||
<ul class="dropdown-menu rounded md:absolute pl-4 md:pl-0 md:hidden font-medium md:bg-white md:min-w-[200px] dark:md:bg-slate-800 drop-shadow-xl">
|
||||
{links.map(({ text: text2, href: href2 }) => (
|
||||
<li>
|
||||
<a
|
||||
class="first:rounded-t last:rounded-b md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-5 block whitespace-no-wrap"
|
||||
href={href2}
|
||||
>
|
||||
{text2}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : (
|
||||
<a
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href={href}
|
||||
>
|
||||
{text}
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
<li class="md:hidden">
|
||||
<a
|
||||
class="font-bold hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href="https://github.com/onwidget/astrowind">Github</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="md:self-center flex items-center md:mb-0 ml-4">
|
||||
<div class="hidden items-center md:flex">
|
||||
<ToggleTheme iconClass="w-5 h-5" />
|
||||
<a
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
|
||||
aria-label="RSS Feed"
|
||||
href={getPermalink('/rss.xml')}
|
||||
>
|
||||
<Icon name="tabler:rss" class="w-5 h-5" />
|
||||
</a>
|
||||
<a
|
||||
class="btn w-full ml-3 py-2.5 px-5 font-semibold text-gray-600 shadow-none text-sm"
|
||||
href="https://github.com/onwidget/astrowind">Download</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="py-3 px-3 md:py-3.5 md:px-4 mx-auto w-full md:flex md:justify-between max-w-6xl">
|
||||
<div class="flex justify-between">
|
||||
<a class="flex items-center" href={getHomePermalink()}>
|
||||
<Logo />
|
||||
</a>
|
||||
<div class="flex items-center md:hidden">
|
||||
<ToggleTheme />
|
||||
<ToggleMenu />
|
||||
</div>
|
||||
</div>
|
||||
<nav
|
||||
class="items-center w-full md:w-auto hidden md:flex text-gray-600 dark:text-slate-200 h-[calc(100vh-72px)] md:h-auto overflow-y-auto md:overflow-visible"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<ul class="flex flex-col pt-8 md:pt-0 md:flex-row md:self-center w-full md:w-auto text-xl md:text-base">
|
||||
{
|
||||
links.map(({ text, href, links }) => (
|
||||
<li class={links?.length ? 'dropdown' : ''}>
|
||||
{links?.length ? (
|
||||
<>
|
||||
<button class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out">
|
||||
{text} <Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 hidden md:inline" />
|
||||
</button>
|
||||
<ul class="dropdown-menu rounded md:absolute pl-4 md:pl-0 md:hidden font-medium md:bg-white md:min-w-[200px] dark:md:bg-slate-800 drop-shadow-xl">
|
||||
{links.map(({ text: text2, href: href2 }) => (
|
||||
<li>
|
||||
<a
|
||||
class="first:rounded-t last:rounded-b md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-5 block whitespace-no-wrap"
|
||||
href={href2}
|
||||
>
|
||||
{text2}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : (
|
||||
<a
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href={href}
|
||||
>
|
||||
{text}
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
<li class="md:hidden">
|
||||
<a
|
||||
class="font-bold hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href="https://github.com/onwidget/astrowind">Github</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="md:self-center flex items-center md:mb-0 ml-4">
|
||||
<div class="hidden items-center md:flex">
|
||||
<ToggleTheme iconClass="w-5 h-5" />
|
||||
<a
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
|
||||
aria-label="RSS Feed"
|
||||
href={getPermalink('/rss.xml')}
|
||||
>
|
||||
<Icon name="tabler:rss" class="w-5 h-5" />
|
||||
</a>
|
||||
<a
|
||||
class="btn w-full ml-3 py-2.5 px-5 font-semibold text-gray-600 shadow-none text-sm"
|
||||
href="https://github.com/onwidget/astrowind">Download</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
@ -3,96 +3,104 @@ import { Icon } from 'astro-icon';
|
||||
import { Picture } from '@astrojs/image/components';
|
||||
|
||||
interface CallToAction {
|
||||
text: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
text: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
callToAction?: string | CallToAction;
|
||||
callToAction2?: string | CallToAction;
|
||||
image?: string | any; // TODO: find HTMLElementProps
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
callToAction?: string | CallToAction;
|
||||
callToAction2?: string | CallToAction;
|
||||
image?: string | any; // TODO: find HTMLElementProps
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
callToAction = await Astro.slots.render('callToAction'),
|
||||
callToAction2 = await Astro.slots.render('callToAction2'),
|
||||
image = await Astro.slots.render('image'),
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
callToAction = await Astro.slots.render('callToAction'),
|
||||
callToAction2 = await Astro.slots.render('callToAction2'),
|
||||
image = await Astro.slots.render('image'),
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="text-center pb-10 md:pb-16 max-w-5xl mx-auto">
|
||||
{
|
||||
title && (
|
||||
<h1
|
||||
class="text-5xl md:text-[3.50rem] font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)
|
||||
}
|
||||
<div class="max-w-3xl mx-auto">
|
||||
{subtitle && <p class="text-xl font-medium text-gray-500 mb-8 dark:text-slate-400" set:html={subtitle} />}
|
||||
<div class="max-w-xs sm:max-w-md m-auto flex flex-nowrap flex-col sm:flex-row sm:justify-center gap-4">
|
||||
{
|
||||
callToAction && (
|
||||
<div class="flex w-full sm:w-auto">
|
||||
{typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
<a class="btn btn-primary sm:mb-0 w-full" href={callToAction?.href} target="_blank" rel="noopener">
|
||||
{callToAction?.icon && <><Icon name={callToAction.icon} class="w-5 h-5 mr-1 -ml-1.5" />{' '}</>}
|
||||
{callToAction?.text}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
callToAction2 && (
|
||||
<div class="flex w-full sm:w-auto">
|
||||
{typeof callToAction2 === 'string' ? (
|
||||
<Fragment set:html={callToAction2} />
|
||||
) : (
|
||||
<a class="btn w-full" href={callToAction2?.href}>
|
||||
{callToAction2?.icon && <><Icon name={callToAction2.icon} class="w-5 h-5 mr-1 -ml-1.5" />{' '}</>}
|
||||
{callToAction2.text}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{
|
||||
image && (
|
||||
<div class="relative m-auto max-w-4xl">
|
||||
{typeof image === 'string' ? (
|
||||
<Fragment set:html={image} />
|
||||
) : (
|
||||
<Picture
|
||||
class="mx-auto rounded-md w-full"
|
||||
widths={[400, 768, 1480]}
|
||||
sizes="(max-width: 767px) 400px, (max-width: 1479px) 768px, 1480px"
|
||||
aspectRatio={1480 / 833}
|
||||
loading="eager"
|
||||
width={1480}
|
||||
height={833}
|
||||
{...image}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="text-center pb-10 md:pb-16 max-w-5xl mx-auto">
|
||||
{
|
||||
title && (
|
||||
<h1
|
||||
class="text-5xl md:text-[3.50rem] font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)
|
||||
}
|
||||
<div class="max-w-3xl mx-auto">
|
||||
{subtitle && <p class="text-xl font-medium text-gray-500 mb-8 dark:text-slate-400" set:html={subtitle} />}
|
||||
<div class="max-w-xs sm:max-w-md m-auto flex flex-nowrap flex-col sm:flex-row sm:justify-center gap-4">
|
||||
{
|
||||
callToAction && (
|
||||
<div class="flex w-full sm:w-auto">
|
||||
{typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
<a class="btn btn-primary sm:mb-0 w-full" href={callToAction?.href} target="_blank" rel="noopener">
|
||||
{callToAction?.icon && (
|
||||
<>
|
||||
<Icon name={callToAction.icon} class="w-5 h-5 mr-1 -ml-1.5" />{' '}
|
||||
</>
|
||||
)}
|
||||
{callToAction?.text}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
callToAction2 && (
|
||||
<div class="flex w-full sm:w-auto">
|
||||
{typeof callToAction2 === 'string' ? (
|
||||
<Fragment set:html={callToAction2} />
|
||||
) : (
|
||||
<a class="btn w-full" href={callToAction2?.href}>
|
||||
{callToAction2?.icon && (
|
||||
<>
|
||||
<Icon name={callToAction2.icon} class="w-5 h-5 mr-1 -ml-1.5" />{' '}
|
||||
</>
|
||||
)}
|
||||
{callToAction2.text}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{
|
||||
image && (
|
||||
<div class="relative m-auto max-w-4xl">
|
||||
{typeof image === 'string' ? (
|
||||
<Fragment set:html={image} />
|
||||
) : (
|
||||
<Picture
|
||||
class="mx-auto rounded-md w-full"
|
||||
widths={[400, 768, 1480]}
|
||||
sizes="(max-width: 767px) 400px, (max-width: 1479px) 768px, 1480px"
|
||||
aspectRatio={1480 / 833}
|
||||
loading="eager"
|
||||
width={1480}
|
||||
height={833}
|
||||
{...image}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -3,9 +3,9 @@ import { Icon } from 'astro-icon';
|
||||
---
|
||||
|
||||
<section class="bg-primary-50 dark:bg-slate-800">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-4 text-md text-center font-medium">
|
||||
<span class="font-bold">
|
||||
<Icon name="tabler:info-square" class="w-5 h-5 inline-block align-text-bottom" /> Philosophy:</span
|
||||
> Simplicity, Best Practices and High Performance
|
||||
</div>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-4 text-md text-center font-medium">
|
||||
<span class="font-bold">
|
||||
<Icon name="tabler:info-square" class="w-5 h-5 inline-block align-text-bottom" /> Philosophy:</span
|
||||
> Simplicity, Best Practices and High Performance
|
||||
</div>
|
||||
</section>
|
||||
|
@ -3,272 +3,272 @@
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto">
|
||||
<!-- Title -->
|
||||
<div class="max-w-2xl mx-auto text-center mb-10 lg:mb-14">
|
||||
<h2 class="text-2xl font-bold md:text-4xl md:leading-tight dark:text-white">Pricing</h2>
|
||||
<p class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
Whatever your status, our offers evolve according to your needs.
|
||||
</p>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
<!-- Title -->
|
||||
<div class="max-w-2xl mx-auto text-center mb-10 lg:mb-14">
|
||||
<h2 class="text-2xl font-bold md:text-4xl md:leading-tight dark:text-white">Pricing</h2>
|
||||
<p class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
Whatever your status, our offers evolve according to your needs.
|
||||
</p>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
|
||||
<!-- Grid -->
|
||||
<div class="mt-12 grid sm:grid-cols-2 lg:grid-cols-4 gap-6 lg:items-center">
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Free</h4>
|
||||
<span class="mt-7 font-bold text-5xl text-gray-800 dark:text-gray-200">Free</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Forever free</p>
|
||||
<!-- Grid -->
|
||||
<div class="mt-12 grid sm:grid-cols-2 lg:grid-cols-4 gap-6 lg:items-center">
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Free</h4>
|
||||
<span class="mt-7 font-bold text-5xl text-gray-800 dark:text-gray-200">Free</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Forever free</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 1 user</span>
|
||||
</li>
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 1 user</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border-2 border-blue-600 text-center shadow-xl rounded-xl p-8 dark:border-blue-500">
|
||||
<p class="mb-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 py-1.5 px-3 rounded-md text-xs uppercase font-semibold bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-white"
|
||||
>Most popular</span
|
||||
>
|
||||
</p>
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Startup</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
39
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">All the basics for starting a new business</p>
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border-2 border-blue-600 text-center shadow-xl rounded-xl p-8 dark:border-blue-500">
|
||||
<p class="mb-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 py-1.5 px-3 rounded-md text-xs uppercase font-semibold bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-white"
|
||||
>Most popular</span
|
||||
>
|
||||
</p>
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Startup</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
39
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">All the basics for starting a new business</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 2 users</span>
|
||||
</li>
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 2 users</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Team</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
89
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Everything you need for a growing business</p>
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Team</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
89
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Everything you need for a growing business</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 5 users</span>
|
||||
</li>
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 5 users</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Enterprise</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
149
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Advanced features for scaling your business</p>
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Enterprise</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
149
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Advanced features for scaling your business</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 10 users</span>
|
||||
</li>
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 10 users</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
</div>
|
||||
<!-- End Grid -->
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
</div>
|
||||
<!-- End Grid -->
|
||||
</div>
|
||||
<!-- End Pricing -->
|
||||
|
@ -1,55 +1,57 @@
|
||||
---
|
||||
interface Item {
|
||||
name: string;
|
||||
value: string;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items?: Array<Item>;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
items?: Array<Item>;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
items = [],
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<div class="px-4 py-4 md:py-16 sm:px-6 mx-auto md:px-24 lg:px-8 lg:py-20 max-w-6xl">
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="max-w-xl mb-10 md:mx-auto sm:text-center lg:max-w-2xl md:mb-12">
|
||||
{highlight && (
|
||||
<p class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase">
|
||||
{highlight}
|
||||
</p>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="max-w-lg mb-4 text-3xl font-bold leading-none tracking-tight sm:text-4xl md:mx-auto font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class="grid grid-cols-2 row-gap-8 md:grid-cols-4">
|
||||
{
|
||||
items.map(({ name, value }) => (
|
||||
<div class="text-center md:border-r md:last:border-none dark:md:border-slate-500 mb-12 md:mb-0">
|
||||
<div class="text-[2.6rem] font-bold lg:text-5xl xl:text-6xl text-primary-800 dark:text-primary-600 font-heading">{value}</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
{name}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
{
|
||||
(title || subtitle || highlight) && (
|
||||
<div class="max-w-xl mb-10 md:mx-auto sm:text-center lg:max-w-2xl md:mb-12">
|
||||
{highlight && (
|
||||
<p class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase">
|
||||
{highlight}
|
||||
</p>
|
||||
)}
|
||||
{title && (
|
||||
<h2
|
||||
class="max-w-lg mb-4 text-3xl font-bold leading-none tracking-tight sm:text-4xl md:mx-auto font-heading"
|
||||
set:html={title}
|
||||
/>
|
||||
)}
|
||||
{subtitle && (
|
||||
<p class="max-w-3xl mx-auto text-center text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class="grid grid-cols-2 row-gap-8 md:grid-cols-4">
|
||||
{
|
||||
items.map(({ name, value }) => (
|
||||
<div class="text-center md:border-r md:last:border-none dark:md:border-slate-500 mb-12 md:mb-0">
|
||||
<div class="text-[2.6rem] font-bold lg:text-5xl xl:text-6xl text-primary-800 dark:text-primary-600 font-heading">
|
||||
{value}
|
||||
</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
{name}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,70 +3,70 @@ import { Icon } from 'astro-icon';
|
||||
import { Picture } from '@astrojs/image/components';
|
||||
|
||||
interface Item {
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
items: Array<Item>;
|
||||
image?: string | any; // TODO: find HTMLElementProps
|
||||
title?: string;
|
||||
items: Array<Item>;
|
||||
image?: string | any; // TODO: find HTMLElementProps
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
items = [],
|
||||
image = await Astro.slots.render('image'),
|
||||
title = await Astro.slots.render('title'),
|
||||
items = [],
|
||||
image = await Astro.slots.render('image'),
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class="px-4 py-16 sm:px-6 mx-auto lg:px-8 lg:py-20 max-w-6xl">
|
||||
<div class="grid gap-6 row-gap-10 md:grid-cols-2">
|
||||
<div class="md:py-4 md:pr-16 mb-4 md:mb-0">
|
||||
{title && <h2 class="mb-8 text-3xl lg:text-4xl font-bold font-heading" set:html={title} />}
|
||||
{
|
||||
items &&
|
||||
items.length &&
|
||||
items.map(({ title, description, icon }, index) => (
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
<div>
|
||||
{index !== items.length - 1 ? (
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-800 dark:border-primary-700 border-2">
|
||||
{icon && <Icon name={icon} class="w-6 h-6 text-primary-800 dark:text-slate-200" />}
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-800 border-2 bg-primary-800 dark:bg-primary-700 dark:border-primary-700">
|
||||
<Icon name={icon} class="w-6 h-6 text-white dark:text-slate-200" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div class="w-px h-full bg-gray-300 dark:bg-slate-500" />
|
||||
</div>
|
||||
<div class={`pt-1 ${index !== items.length - 1 ? 'pb-8' : ''}`}>
|
||||
{title && <p class="mb-2 text-xl font-bold text-gray-900 dark:text-slate-300" set:html={title} />}
|
||||
{description && <p class="text-gray-600 dark:text-slate-400" set:html={description} />}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="relative">
|
||||
{
|
||||
image &&
|
||||
(typeof image === 'string' ? (
|
||||
<Fragment set:html={image} />
|
||||
) : (
|
||||
<Picture
|
||||
class="inset-0 object-cover object-top w-full rounded-md shadow-lg md:absolute md:h-full bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 768]}
|
||||
sizes="(max-width: 768px) 100vw, 432px"
|
||||
aspectRatio="432:768"
|
||||
{...image}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-6 row-gap-10 md:grid-cols-2">
|
||||
<div class="md:py-4 md:pr-16 mb-4 md:mb-0">
|
||||
{title && <h2 class="mb-8 text-3xl lg:text-4xl font-bold font-heading" set:html={title} />}
|
||||
{
|
||||
items &&
|
||||
items.length &&
|
||||
items.map(({ title, description, icon }, index) => (
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
<div>
|
||||
{index !== items.length - 1 ? (
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-800 dark:border-primary-700 border-2">
|
||||
{icon && <Icon name={icon} class="w-6 h-6 text-primary-800 dark:text-slate-200" />}
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-800 border-2 bg-primary-800 dark:bg-primary-700 dark:border-primary-700">
|
||||
<Icon name={icon} class="w-6 h-6 text-white dark:text-slate-200" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div class="w-px h-full bg-gray-300 dark:bg-slate-500" />
|
||||
</div>
|
||||
<div class={`pt-1 ${index !== items.length - 1 ? 'pb-8' : ''}`}>
|
||||
{title && <p class="mb-2 text-xl font-bold text-gray-900 dark:text-slate-300" set:html={title} />}
|
||||
{description && <p class="text-gray-600 dark:text-slate-400" set:html={description} />}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="relative">
|
||||
{
|
||||
image &&
|
||||
(typeof image === 'string' ? (
|
||||
<Fragment set:html={image} />
|
||||
) : (
|
||||
<Picture
|
||||
class="inset-0 object-cover object-top w-full rounded-md shadow-lg md:absolute md:h-full bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 768]}
|
||||
sizes="(max-width: 768px) 100vw, 432px"
|
||||
aspectRatio="432:768"
|
||||
{...image}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -2,31 +2,31 @@
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
interface Item {
|
||||
title: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
interface CallToAction {
|
||||
text: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
text: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
callToAction?: string | CallToAction;
|
||||
items: Array<Item>;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
highlight?: string;
|
||||
callToAction?: string | CallToAction;
|
||||
items: Array<Item>;
|
||||
}
|
||||
|
||||
const {
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
callToAction = await Astro.slots.render('callToAction'),
|
||||
items = [],
|
||||
title = await Astro.slots.render('title'),
|
||||
subtitle = await Astro.slots.render('subtitle'),
|
||||
highlight,
|
||||
callToAction = await Astro.slots.render('callToAction'),
|
||||
items = [],
|
||||
} = Astro.props;
|
||||
|
||||
/**
|
||||
@ -64,64 +64,64 @@ const {
|
||||
---
|
||||
|
||||
<section>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 overflow-hidden">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="py-4 sm:py-6 lg:py-8">
|
||||
<div class="flex flex-wrap md:-mx-8">
|
||||
<div class="w-full lg:w-1/2 px-0 sm:px-8 mb-12">
|
||||
<div>
|
||||
{
|
||||
highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{title && <h2 class="mb-4 text-3xl lg:text-4xl font-bold font-heading" set:html={title} />}
|
||||
{subtitle && <p class="mb-8 text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />}
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 overflow-hidden">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="py-4 sm:py-6 lg:py-8">
|
||||
<div class="flex flex-wrap md:-mx-8">
|
||||
<div class="w-full lg:w-1/2 px-0 sm:px-8 mb-12">
|
||||
<div>
|
||||
{
|
||||
highlight && (
|
||||
<p
|
||||
class="text-base text-primary-800 dark:text-primary-200 font-semibold tracking-wide uppercase"
|
||||
set:html={highlight}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{title && <h2 class="mb-4 text-3xl lg:text-4xl font-bold font-heading" set:html={title} />}
|
||||
{subtitle && <p class="mb-8 text-xl text-gray-600 dark:text-slate-400" set:html={subtitle} />}
|
||||
|
||||
<div class="w-full">
|
||||
{
|
||||
typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
callToAction &&
|
||||
callToAction.text &&
|
||||
callToAction.href && (
|
||||
<a class="btn btn-primary mb-4 sm:mb-0" href={callToAction.href} target="_blank" rel="noopener">
|
||||
{callToAction.icon && <Icon name={callToAction.icon} class="w-5 h-5 mr-1 -ml-1.5" />}
|
||||
{callToAction.text}
|
||||
</a>
|
||||
)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 px-0 sm:px-8">
|
||||
<ul class="space-y-10">
|
||||
{
|
||||
items && items.length
|
||||
? items.map(({ title: title2, description, icon }, index) => (
|
||||
<li class="flex md:-mx-4">
|
||||
<div class="pr-4 sm:pl-4">
|
||||
<span class="flex w-16 h-16 mx-auto items-center justify-center text-2xl font-bold rounded-full bg-primary-100 text-primary-800">
|
||||
{icon ? <Icon name={icon} class="w-6 h-6 icon-bold" /> : index + 1}
|
||||
</span>
|
||||
</div>
|
||||
<div class="pl-4">
|
||||
<h3 class="mb-4 text-xl font-semibold font-heading" set:html={title2} />
|
||||
<p class="text-gray-500 dark:text-gray-400" set:html={description} />
|
||||
</div>
|
||||
</li>
|
||||
))
|
||||
: ''
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
{
|
||||
typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
callToAction &&
|
||||
callToAction.text &&
|
||||
callToAction.href && (
|
||||
<a class="btn btn-primary mb-4 sm:mb-0" href={callToAction.href} target="_blank" rel="noopener">
|
||||
{callToAction.icon && <Icon name={callToAction.icon} class="w-5 h-5 mr-1 -ml-1.5" />}
|
||||
{callToAction.text}
|
||||
</a>
|
||||
)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 px-0 sm:px-8">
|
||||
<ul class="space-y-10">
|
||||
{
|
||||
items && items.length
|
||||
? items.map(({ title: title2, description, icon }, index) => (
|
||||
<li class="flex md:-mx-4">
|
||||
<div class="pr-4 sm:pl-4">
|
||||
<span class="flex w-16 h-16 mx-auto items-center justify-center text-2xl font-bold rounded-full bg-primary-100 text-primary-800">
|
||||
{icon ? <Icon name={icon} class="w-6 h-6 icon-bold" /> : index + 1}
|
||||
</span>
|
||||
</div>
|
||||
<div class="pl-4">
|
||||
<h3 class="mb-4 text-xl font-semibold font-heading" set:html={title2} />
|
||||
<p class="text-gray-500 dark:text-gray-400" set:html={description} />
|
||||
</div>
|
||||
</li>
|
||||
))
|
||||
: ''
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
Reference in New Issue
Block a user