Start rearranging and simplifying widgets
This commit is contained in:
@ -11,7 +11,7 @@ interface Item {
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
highlight?: string;
|
tagline?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
items?: Array<Item>;
|
items?: Array<Item>;
|
||||||
image?: string | any; // TODO: find HTMLElementProps
|
image?: string | any; // TODO: find HTMLElementProps
|
||||||
@ -22,7 +22,7 @@ export interface Props {
|
|||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = await Astro.slots.render('title'),
|
||||||
subtitle = await Astro.slots.render('subtitle'),
|
subtitle = await Astro.slots.render('subtitle'),
|
||||||
highlight,
|
tagline,
|
||||||
content = await Astro.slots.render('content'),
|
content = await Astro.slots.render('content'),
|
||||||
items = [],
|
items = [],
|
||||||
image = await Astro.slots.render('image'),
|
image = await Astro.slots.render('image'),
|
||||||
@ -34,12 +34,12 @@ const {
|
|||||||
<section class:list={[{ 'pt-0 md:pt-0': isAfterContent }, 'bg-blue-50 dark:bg-slate-800 py-16 md:py-20 not-prose']}>
|
<section class:list={[{ 'pt-0 md:pt-0': isAfterContent }, 'bg-blue-50 dark:bg-slate-800 py-16 md:py-20 not-prose']}>
|
||||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
||||||
{
|
{
|
||||||
(title || subtitle || highlight) && (
|
(title || subtitle || tagline) && (
|
||||||
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
||||||
{highlight && (
|
{tagline && (
|
||||||
<p
|
<p
|
||||||
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
||||||
set:html={highlight}
|
set:html={tagline}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{title && (
|
{title && (
|
||||||
|
@ -1,66 +1,37 @@
|
|||||||
---
|
---
|
||||||
import { Icon } from 'astro-icon/components';
|
import Headline from "~/components/ui/Headline.astro";
|
||||||
|
import ItemGrid from "~/components/ui/ItemGrid.astro";
|
||||||
interface Item {
|
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
|
||||||
question: string;
|
import type { Faqs } from "~/types";
|
||||||
answer: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
title?: string;
|
|
||||||
subtitle?: string;
|
|
||||||
highlight?: string;
|
|
||||||
items: Array<Array<Item>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = "",
|
||||||
subtitle = await Astro.slots.render('subtitle'),
|
subtitle = "",
|
||||||
highlight,
|
tagline = "",
|
||||||
items = [],
|
items = [],
|
||||||
} = Astro.props;
|
columns = 2,
|
||||||
|
|
||||||
|
id,
|
||||||
|
isDark = false,
|
||||||
|
classes = {},
|
||||||
|
bg = await Astro.slots.render("bg"),
|
||||||
|
} = Astro.props as Faqs;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:py-20 not-prose">
|
<WidgetWrapper
|
||||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
id={id}
|
||||||
{
|
isDark={isDark}
|
||||||
(title || subtitle || highlight) && (
|
containerClass={`max-w-screen-xl mx-auto ${classes?.container ?? ""}`}
|
||||||
<div class="max-w-xl mb-10 md:mx-auto md:text-center lg:max-w-2xl md:mb-12">
|
bg={bg}
|
||||||
{highlight && (
|
>
|
||||||
<p
|
<Headline title={title} subtitle={subtitle} tagline={tagline} />
|
||||||
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
<ItemGrid
|
||||||
set:html={highlight}
|
items={items}
|
||||||
/>
|
columns={columns}
|
||||||
)}
|
defaultIcon="tabler:chevron-right"
|
||||||
{title && (
|
classes={{
|
||||||
<h2
|
panel: 'max-w-none',
|
||||||
class="max-w-lg mb-4 text-3xl font-bold leading-none md:tracking-tight sm:text-4xl md:mx-auto font-heading"
|
icon: "flex-shrink-0 mt-1 w-6 h-6 text-primary",
|
||||||
set:html={title}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
</WidgetWrapper>
|
||||||
{subtitle && <p class="max-w-3xl mx-auto text-xl text-muted dark:text-slate-400" set:html={subtitle} />}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="max-w-7xl 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 inline-block" />
|
|
||||||
{question}
|
|
||||||
</h3>
|
|
||||||
{answer && <div class="text-muted dark:text-gray-400" set:html={answer} />}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
@ -1,71 +1,43 @@
|
|||||||
---
|
---
|
||||||
import { Icon } from 'astro-icon/components';
|
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
|
||||||
|
import ItemGrid from "~/components/ui/ItemGrid.astro";
|
||||||
interface Item {
|
import Headline from "~/components/ui/Headline.astro";
|
||||||
title: string;
|
import type { Features } from "~/types";
|
||||||
description: string;
|
|
||||||
icon?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
title?: string;
|
|
||||||
subtitle?: string;
|
|
||||||
highlight?: string;
|
|
||||||
items: Array<Array<Item>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = await Astro.slots.render("title"),
|
||||||
subtitle = await Astro.slots.render('subtitle'),
|
subtitle = await Astro.slots.render("subtitle"),
|
||||||
highlight,
|
tagline = await Astro.slots.render("tagline"),
|
||||||
items = [],
|
items = [],
|
||||||
} = Astro.props;
|
columns = 2,
|
||||||
|
|
||||||
|
id,
|
||||||
|
isDark = false,
|
||||||
|
classes = {},
|
||||||
|
bg = await Astro.slots.render("bg"),
|
||||||
|
} = Astro.props as Features;
|
||||||
---
|
---
|
||||||
|
|
||||||
<section class="scroll-mt-16 not-prose" id="features">
|
<WidgetWrapper
|
||||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:px-8 lg:py-20">
|
id={id}
|
||||||
{
|
isDark={isDark}
|
||||||
(title || subtitle || highlight) && (
|
containerClass={`max-w-5xl ${classes?.container ?? ""}`}
|
||||||
<div class="mb-10 md:mx-auto text-center md:mb-12 max-w-3xl">
|
bg={bg}
|
||||||
{highlight && (
|
>
|
||||||
<p
|
<Headline
|
||||||
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
title={title}
|
||||||
set:html={highlight}
|
subtitle={subtitle}
|
||||||
/>
|
tagline={tagline}
|
||||||
)}
|
classes={classes?.headline}
|
||||||
{title && (
|
/>
|
||||||
<h2
|
<ItemGrid
|
||||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
items={items}
|
||||||
set:html={title}
|
columns={columns}
|
||||||
/>
|
classes={{
|
||||||
)}
|
container: "",
|
||||||
|
title: "md:text-[1.3rem]",
|
||||||
{subtitle && (
|
icon: "text-white bg-primary rounded-full w-10 h-10 p-2 md:w-12 md:h-12 md:p-3 mr-4 rtl:ml-4 rtl:mr-0",
|
||||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-muted dark:text-slate-400" set:html={subtitle} />
|
...((classes?.items as {}) ?? {}),
|
||||||
)}
|
}}
|
||||||
</div>
|
/>
|
||||||
)
|
</WidgetWrapper>
|
||||||
}
|
|
||||||
<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 dark:bg-blue-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-muted dark:text-slate-400" set:html={description} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
@ -1,69 +1,46 @@
|
|||||||
---
|
---
|
||||||
import { Icon } from 'astro-icon/components';
|
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
|
||||||
|
import Headline from "~/components/ui/Headline.astro";
|
||||||
interface Item {
|
import ItemGrid2 from "~/components/ui/ItemGrid2.astro";
|
||||||
title?: string;
|
import type { Features } from "~/types";
|
||||||
description?: string;
|
|
||||||
icon?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
title?: string;
|
|
||||||
subtitle?: string;
|
|
||||||
highlight?: string;
|
|
||||||
items: Array<Item>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = await Astro.slots.render("title"),
|
||||||
subtitle = await Astro.slots.render('subtitle'),
|
subtitle = await Astro.slots.render("subtitle"),
|
||||||
highlight,
|
tagline = await Astro.slots.render("tagline"),
|
||||||
items = [],
|
items = [],
|
||||||
} = Astro.props;
|
columns = 3,
|
||||||
|
|
||||||
|
id,
|
||||||
|
isDark = false,
|
||||||
|
classes = {},
|
||||||
|
bg = await Astro.slots.render("bg"),
|
||||||
|
} = Astro.props as Features;
|
||||||
---
|
---
|
||||||
|
|
||||||
<section class="relative not-prose">
|
<WidgetWrapper
|
||||||
<div class="absolute inset-0 bg-blue-50 dark:bg-slate-800 pointer-events-none mb-32" aria-hidden="true"></div>
|
id={id}
|
||||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 -mb-12">
|
isDark={isDark}
|
||||||
<div class="py-4 pt-8 sm:py-6 lg:py-8 lg:pt-12">
|
containerClass={classes?.container}
|
||||||
{
|
bg={bg}
|
||||||
(title || subtitle || highlight) && (
|
>
|
||||||
<div class="mb-8 md:mx-auto text-center max-w-3xl">
|
<Headline
|
||||||
{highlight && (
|
title={title}
|
||||||
<p
|
subtitle={subtitle}
|
||||||
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
tagline={tagline}
|
||||||
set:html={highlight}
|
classes={classes?.headline}
|
||||||
/>
|
/>
|
||||||
)}
|
<ItemGrid2
|
||||||
{title && (
|
items={items}
|
||||||
<h2
|
columns={columns}
|
||||||
class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading"
|
classes={{
|
||||||
set:html={title}
|
container: "gap-4 md:gap-6",
|
||||||
/>
|
panel:
|
||||||
)}
|
'rounded-lg shadow-[0_4px_30px_rgba(0,0,0,0.1)] dark:shadow-[0_4px_30px_rgba(0,0,0,0.1)] backdrop-blur border border-[#ffffff29] bg-white dark:bg-slate-900 p-6',
|
||||||
|
// panel:
|
||||||
{subtitle && (
|
// "text-center bg-page items-center md:text-left rtl:md:text-right md:items-start p-6 p-6 rounded-md shadow-xl dark:shadow-none dark:border dark:border-slate-800",
|
||||||
<p
|
icon: "w-12 h-12 mb-6 text-primary",
|
||||||
class="max-w-3xl mx-auto sm:text-center text-xl text-muted dark:text-slate-400"
|
...((classes?.items as {}) ?? {}),
|
||||||
set:html={subtitle}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
</WidgetWrapper>
|
||||||
</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-muted dark:text-gray-400 text-md mt-4" set:html={description} />}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
@ -16,6 +16,7 @@ interface Link {
|
|||||||
|
|
||||||
interface ActionLink extends Link {
|
interface ActionLink extends Link {
|
||||||
class?: string;
|
class?: string;
|
||||||
|
type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MenuLink extends Link {
|
interface MenuLink extends Link {
|
||||||
|
98
src/components/widgets/Pricing.astro
Normal file
98
src/components/widgets/Pricing.astro
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
import { Icon } from "astro-icon/components";
|
||||||
|
import CTA from "~/components/ui/CTA.astro";
|
||||||
|
import Headline from "~/components/ui/Headline.astro";
|
||||||
|
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
|
||||||
|
import type { Pricing } from "~/types";
|
||||||
|
|
||||||
|
const {
|
||||||
|
title = "",
|
||||||
|
subtitle = "",
|
||||||
|
tagline = "",
|
||||||
|
prices = [],
|
||||||
|
|
||||||
|
id,
|
||||||
|
isDark = false,
|
||||||
|
classes = {},
|
||||||
|
bg = await Astro.slots.render("bg"),
|
||||||
|
} = Astro.props as Pricing;
|
||||||
|
---
|
||||||
|
|
||||||
|
<WidgetWrapper
|
||||||
|
id={id}
|
||||||
|
isDark={isDark}
|
||||||
|
containerClass={`max-w-6xl mx-auto ${classes?.container ?? ""}`}
|
||||||
|
bg={bg}
|
||||||
|
>
|
||||||
|
<Headline title={title} subtitle={subtitle} tagline={tagline} />
|
||||||
|
<div class="flex items-stretch justify-center">
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-3 gap-3 dark:text-white sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
prices &&
|
||||||
|
prices.map(
|
||||||
|
({
|
||||||
|
title,
|
||||||
|
price,
|
||||||
|
period,
|
||||||
|
items,
|
||||||
|
callToAction,
|
||||||
|
hasRibbon = false,
|
||||||
|
ribbonTitle,
|
||||||
|
}) => (
|
||||||
|
<div class="col-span-3 mx-auto flex w-full sm:col-span-1 md:col-span-1 lg:col-span-1 xl:col-span-1">
|
||||||
|
<div class="rounded-md border-gray-200 bg-white px-6 pt-10 pb-8 shadow-xl transition duration-300 ease-in-out dark:border dark:border-slate-800 dark:bg-slate-900 relative flex w-full max-w-sm flex-col justify-between text-center">
|
||||||
|
{hasRibbon && ribbonTitle && (
|
||||||
|
<div class="absolute right-[-5px] top-[-5px] z-[1] h-[100px] w-[100px] overflow-hidden text-right">
|
||||||
|
<span class="absolute top-[19px] right-[-21px] block w-full rotate-45 bg-green-700 text-center text-[10px] font-bold uppercase leading-5 text-white shadow-[0_3px_10px_-5px_rgba(0,0,0,0.3)] before:absolute before:left-0 before:top-full before:z-[-1] before:border-[3px] before:border-r-transparent before:border-b-transparent before:border-l-green-800 before:border-t-green-800 before:content-[''] after:absolute after:right-0 after:top-full after:z-[-1] after:border-[3px] after:border-l-transparent after:border-b-transparent after:border-r-green-800 after:border-t-green-800 after:content-['']">
|
||||||
|
{ribbonTitle}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<ul class="px-2 py-0">
|
||||||
|
<li class="text-center text-xl font-medium uppercase leading-6 tracking-wider text-gray-800 dark:text-slate-400">
|
||||||
|
{title}
|
||||||
|
</li>
|
||||||
|
<li class="mt-5 mb-2.5 flex items-center justify-center text-center font-semibold">
|
||||||
|
<span class="text-5xl">$</span>
|
||||||
|
<span class="text-6xl">{price}</span>
|
||||||
|
</li>
|
||||||
|
<li class="mb-7 text-center text-base font-medium capitalize leading-6 text-gray-600 dark:text-slate-400">
|
||||||
|
{period}
|
||||||
|
</li>
|
||||||
|
{items &&
|
||||||
|
items.map(({ description, icon }) => (
|
||||||
|
<li class="mb-1.5 flex items-start text-left text-base leading-7">
|
||||||
|
<div class="mt-1.5 mr-1.5 flex h-4 w-4 items-center justify-center rounded-full border-2 border-primary bg-primary">
|
||||||
|
{icon && (
|
||||||
|
<Icon
|
||||||
|
name={icon}
|
||||||
|
class="w-5 h-5 font-bold text-white"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{description}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
{callToAction && (
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<CTA
|
||||||
|
callToAction={callToAction}
|
||||||
|
class={`mt-8 ${
|
||||||
|
hasRibbon
|
||||||
|
? "border-primary-600 bg-primary-600 font-semibold text-white hover:border-primary-800 hover:bg-primary-800 hover:text-white dark:border-primary-700 dark:bg-primary-700 dark:text-white dark:hover:border-primary-900 dark:hover:bg-primary-900"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WidgetWrapper>
|
@ -7,25 +7,25 @@ interface Item {
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
highlight?: string;
|
tagline?: string;
|
||||||
items?: Array<Item>;
|
items?: Array<Item>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = await Astro.slots.render('title'),
|
||||||
subtitle = await Astro.slots.render('subtitle'),
|
subtitle = await Astro.slots.render('subtitle'),
|
||||||
highlight,
|
tagline,
|
||||||
items = [],
|
items = [],
|
||||||
} = Astro.props;
|
} = 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 not-prose">
|
<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 not-prose">
|
||||||
{
|
{
|
||||||
(title || subtitle || highlight) && (
|
(title || subtitle || tagline) && (
|
||||||
<div class="max-w-xl mb-10 md:mx-auto sm:text-center lg:max-w-2xl md:mb-12">
|
<div class="max-w-xl mb-10 md:mx-auto sm:text-center lg:max-w-2xl md:mb-12">
|
||||||
{highlight && (
|
{tagline && (
|
||||||
<p class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase">
|
<p class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase">
|
||||||
{highlight}
|
{tagline}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{title && (
|
{title && (
|
||||||
|
@ -1,58 +1,37 @@
|
|||||||
---
|
---
|
||||||
import { Icon } from 'astro-icon/components';
|
|
||||||
import { Picture } from '@astrojs/image/components';
|
import { Picture } from '@astrojs/image/components';
|
||||||
|
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
|
||||||
interface Item {
|
import Timeline from "~/components/ui/Timeline.astro";
|
||||||
title: string;
|
import Headline from "~/components/ui/Headline.astro";
|
||||||
description?: string;
|
import type { Steps } from "~/types";
|
||||||
icon?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
title?: string;
|
|
||||||
items: Array<Item>;
|
|
||||||
image?: string | any; // TODO: find HTMLElementProps
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = await Astro.slots.render("title"),
|
||||||
|
subtitle = await Astro.slots.render("subtitle"),
|
||||||
|
tagline = await Astro.slots.render("tagline"),
|
||||||
items = [],
|
items = [],
|
||||||
image = await Astro.slots.render('image'),
|
image = await Astro.slots.render("image"),
|
||||||
} = Astro.props;
|
isReversed = false,
|
||||||
|
|
||||||
|
id,
|
||||||
|
isDark = false,
|
||||||
|
classes = {},
|
||||||
|
bg = await Astro.slots.render("bg"),
|
||||||
|
} = Astro.props as Steps;
|
||||||
---
|
---
|
||||||
|
|
||||||
<section class="px-4 py-16 sm:px-6 mx-auto lg:px-8 lg:py-20 max-w-6xl not-prose">
|
<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl ${classes?.container ?? ""}`} bg={bg}>
|
||||||
<div class="grid gap-6 row-gap-10 md:grid-cols-2">
|
<div class:list={["flex flex-col gap-8 md:gap-12 md:flex-row", { "md:flex-row-reverse": isReversed }]}>
|
||||||
<div class="md:py-4 md:pr-16 mb-4 md:mb-0">
|
<div class="md:py-4 md:basis-1/2 md:self-center">
|
||||||
{title && <h2 class="mb-8 text-3xl lg:text-4xl font-bold font-heading" set:html={title} />}
|
<Headline
|
||||||
{
|
title={title}
|
||||||
items &&
|
subtitle={subtitle}
|
||||||
items.length &&
|
tagline={tagline}
|
||||||
items.map(({ title, description, icon }, index) => (
|
classes={{ container: "text-left", title: "text-3xl lg:text-4xl", ...((classes?.headline as {}) ?? {}) }}
|
||||||
<div class="flex">
|
/>
|
||||||
<div class="flex flex-col items-center mr-4">
|
<Timeline items={items} classes={classes?.items as {}} />
|
||||||
<div>
|
|
||||||
{index !== items.length - 1 ? (
|
|
||||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary dark:border-blue-700 border-2">
|
|
||||||
{icon && <Icon name={icon} class="w-6 h-6 text-primary dark:text-slate-200" />}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary border-2 bg-primary dark:bg-blue-700 dark:border-blue-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 dark:text-slate-300" set:html={title} />}
|
|
||||||
{description && <p class="text-muted dark:text-slate-400" set:html={description} />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="relative">
|
<div class="relative md:basis-1/2">
|
||||||
{
|
{
|
||||||
image &&
|
image &&
|
||||||
(typeof image === 'string' ? (
|
(typeof image === 'string' ? (
|
||||||
@ -71,4 +50,4 @@ const {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</WidgetWrapper>
|
||||||
|
@ -11,7 +11,7 @@ interface Item {
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
highlight?: string;
|
tagline?: string;
|
||||||
callToAction?: string | CallToAction;
|
callToAction?: string | CallToAction;
|
||||||
items: Array<Item>;
|
items: Array<Item>;
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ export interface Props {
|
|||||||
const {
|
const {
|
||||||
title = await Astro.slots.render('title'),
|
title = await Astro.slots.render('title'),
|
||||||
subtitle = await Astro.slots.render('subtitle'),
|
subtitle = await Astro.slots.render('subtitle'),
|
||||||
highlight,
|
tagline,
|
||||||
callToAction = await Astro.slots.render('callToAction'),
|
callToAction = await Astro.slots.render('callToAction'),
|
||||||
items = [],
|
items = [],
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
@ -66,10 +66,10 @@ const {
|
|||||||
<div class="w-full lg:w-1/2 px-0 sm:px-8 mb-12">
|
<div class="w-full lg:w-1/2 px-0 sm:px-8 mb-12">
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
highlight && (
|
tagline && (
|
||||||
<p
|
<p
|
||||||
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
|
||||||
set:html={highlight}
|
set:html={tagline}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -49,57 +49,54 @@ const meta = {
|
|||||||
<!-- Features Widget *************** -->
|
<!-- Features Widget *************** -->
|
||||||
|
|
||||||
<Features
|
<Features
|
||||||
highlight="Features"
|
id="features"
|
||||||
|
tagline="Features"
|
||||||
title="What you get with AstroWind"
|
title="What you get with AstroWind"
|
||||||
subtitle="Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque rem aperiam, eaque ipsa quae."
|
subtitle="Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque rem aperiam, eaque ipsa quae."
|
||||||
items={[
|
items={[
|
||||||
[
|
{
|
||||||
{
|
title: 'Astro + Tailwind CSS Integration',
|
||||||
title: 'Astro + Tailwind CSS Integration',
|
description:
|
||||||
description:
|
'A seamless integration between two great frameworks that offer high productivity, performance and versatility.',
|
||||||
'A seamless integration between two great frameworks that offer high productivity, performance and versatility.',
|
icon: 'tabler:brand-tailwind',
|
||||||
icon: 'tabler:brand-tailwind',
|
},
|
||||||
},
|
{
|
||||||
{
|
title: 'Ready-to-use Components',
|
||||||
title: 'Ready-to-use Components',
|
description:
|
||||||
description:
|
'Widgets made with Tailwind CSS ready to be used in Marketing Websites, SaaS, Blogs, Personal Profiles, Small Business...',
|
||||||
'Widgets made with Tailwind CSS ready to be used in Marketing Websites, SaaS, Blogs, Personal Profiles, Small Business...',
|
icon: 'tabler:components',
|
||||||
icon: 'tabler:components',
|
},
|
||||||
},
|
{
|
||||||
{
|
title: 'Best Practices',
|
||||||
title: 'Best Practices',
|
description:
|
||||||
description:
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
icon: 'tabler:list-check',
|
||||||
icon: 'tabler:list-check',
|
},
|
||||||
},
|
{
|
||||||
],
|
title: 'Excellent Page Speed',
|
||||||
[
|
description:
|
||||||
{
|
'Having a good page speed impacts organic search ranking, improves user experience (UI/UX) and increase conversion rates.',
|
||||||
title: 'Excellent Page Speed',
|
icon: 'tabler:rocket',
|
||||||
description:
|
},
|
||||||
'Having a good page speed impacts organic search ranking, improves user experience (UI/UX) and increase conversion rates.',
|
{
|
||||||
icon: 'tabler:rocket',
|
title: 'Search Engine Optimization (SEO)',
|
||||||
},
|
description:
|
||||||
{
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||||
title: 'Search Engine Optimization (SEO)',
|
icon: 'tabler:arrows-right-left',
|
||||||
description:
|
},
|
||||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
{
|
||||||
icon: 'tabler:arrows-right-left',
|
title: 'Open to new ideas and contributions',
|
||||||
},
|
description:
|
||||||
{
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||||
title: 'Open to new ideas and contributions',
|
icon: 'tabler:bulb',
|
||||||
description:
|
},
|
||||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
|
||||||
icon: 'tabler:bulb',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Content Widget **************** -->
|
<!-- Content Widget **************** -->
|
||||||
|
|
||||||
<Content
|
<Content
|
||||||
highlight="Inside template"
|
tagline="Inside template"
|
||||||
title="And what's inside? ..."
|
title="And what's inside? ..."
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
@ -200,7 +197,7 @@ const meta = {
|
|||||||
<Features2
|
<Features2
|
||||||
title="Most used widgets"
|
title="Most used widgets"
|
||||||
subtitle="Provides frequently used components for building websites using Tailwind CSS"
|
subtitle="Provides frequently used components for building websites using Tailwind CSS"
|
||||||
highlight="Components"
|
tagline="Components"
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
title: 'Headers',
|
title: 'Headers',
|
||||||
@ -257,7 +254,11 @@ const meta = {
|
|||||||
icon: 'flat-color-icons:database',
|
icon: 'flat-color-icons:database',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
>
|
||||||
|
<Fragment slot="bg">
|
||||||
|
<div class="absolute inset-0 bg-blue-50 dark:bg-transparent"></div>
|
||||||
|
</Fragment>
|
||||||
|
</Features2>
|
||||||
|
|
||||||
<!-- HighlightedPosts Widget ******* -->
|
<!-- HighlightedPosts Widget ******* -->
|
||||||
|
|
||||||
@ -274,42 +275,38 @@ const meta = {
|
|||||||
<FAQs
|
<FAQs
|
||||||
title="Frequently Asked Questions"
|
title="Frequently Asked Questions"
|
||||||
subtitle="Duis turpis dui, fringilla mattis sem nec, fringilla euismod neque. Morbi tincidunt lacus nec tortor scelerisque pulvinar."
|
subtitle="Duis turpis dui, fringilla mattis sem nec, fringilla euismod neque. Morbi tincidunt lacus nec tortor scelerisque pulvinar."
|
||||||
highlight="FAQs"
|
tagline="FAQs"
|
||||||
items={[
|
items={[
|
||||||
[
|
{
|
||||||
{
|
title: 'What do I need to start?',
|
||||||
question: 'What do I need to start?',
|
description:
|
||||||
answer:
|
'Space, the final frontier. These are the voyages of the Starship Enterprise. Its five-year mission: to explore strange new worlds. Many say exploration is part of our destiny, but it’s actually our duty to future generations.',
|
||||||
'Space, the final frontier. These are the voyages of the Starship Enterprise. Its five-year mission: to explore strange new worlds. Many say exploration is part of our destiny, but it’s actually our duty to future generations.',
|
},
|
||||||
},
|
{
|
||||||
{
|
title: 'How to install the Astro + Tailwind CSS template?',
|
||||||
question: 'How to install the Astro + Tailwind CSS template?',
|
description:
|
||||||
answer:
|
"Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.",
|
||||||
"Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows. Some pilots get picked and become television programs. Some don't, become nothing. She starred in one of the ones that became nothing.",
|
},
|
||||||
},
|
{
|
||||||
{
|
title: "What's something that you don't understand?",
|
||||||
question: "What's something that you don't understand?",
|
description:
|
||||||
answer:
|
"A flower in my garden, a mystery in my panties. Heart attack never stopped old Big Bear. I didn't even know we were calling him Big Bear.",
|
||||||
"A flower in my garden, a mystery in my panties. Heart attack never stopped old Big Bear. I didn't even know we were calling him Big Bear.",
|
},
|
||||||
},
|
{
|
||||||
],
|
title: "What's an example of when you changed your mind?",
|
||||||
[
|
description:
|
||||||
{
|
"Michael Knight a young loner on a crusade to champion the cause of the innocent. The helpless. The powerless in a world of criminals who operate above the law. Here he comes Here comes Speed Racer. He's a demon on wheels.",
|
||||||
question: "What's an example of when you changed your mind?",
|
},
|
||||||
answer:
|
{
|
||||||
"Michael Knight a young loner on a crusade to champion the cause of the innocent. The helpless. The powerless in a world of criminals who operate above the law. Here he comes Here comes Speed Racer. He's a demon on wheels.",
|
title: 'What is something that you would like to try again?',
|
||||||
},
|
description:
|
||||||
{
|
"A business big enough that it could be listed on the NASDAQ goes belly up. Disappears! It ceases to exist without me. No, you clearly don't know who you're talking to, so let me clue you in.",
|
||||||
question: 'What is something that you would like to try again?',
|
},
|
||||||
answer:
|
{
|
||||||
"A business big enough that it could be listed on the NASDAQ goes belly up. Disappears! It ceases to exist without me. No, you clearly don't know who you're talking to, so let me clue you in.",
|
title: 'If you could only ask one question to each person you meet, what would that question be?',
|
||||||
},
|
description:
|
||||||
{
|
"This is not about revenge. This is about justice. A lot of things can change in twelve years, Admiral. Well, that's certainly good to know. About four years. I got tired of hearing how young I looked.",
|
||||||
question: 'If you could only ask one question to each person you meet, what would that question be?',
|
},
|
||||||
answer:
|
|
||||||
"This is not about revenge. This is about justice. A lot of things can change in twelve years, Admiral. Well, that's certainly good to know. About four years. I got tired of hearing how young I looked.",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -1,11 +1,105 @@
|
|||||||
---
|
---
|
||||||
import Layout from '~/layouts/PageLayout.astro';
|
import Layout from '~/layouts/PageLayout.astro';
|
||||||
|
|
||||||
|
import Pricing from '~/components/widgets/Pricing.astro';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: "Pricing",
|
title: "Pricing",
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout {meta}>
|
<Layout {meta}>
|
||||||
Pricing
|
<Pricing
|
||||||
|
title="Basic Pricing"
|
||||||
|
tagline="Pricing"
|
||||||
|
subtitle="Our prices"
|
||||||
|
prices={[
|
||||||
|
{
|
||||||
|
"title": "basic",
|
||||||
|
"price": 29,
|
||||||
|
"period": "Per Month",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"description": "Etiam in libero",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Aenean ac nunc",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Cras scelerisque accumsan libero, et volutpat dolor tristique at",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "In hac habitasse",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callToAction": {
|
||||||
|
"targetBlank": true,
|
||||||
|
"text": "Free 7-day trial",
|
||||||
|
"href": "#"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "standard",
|
||||||
|
"price": 69,
|
||||||
|
"period": "Per Month",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"description": "Proin vel laoreet",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Ut efficitur egestas",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Pellentesque ut nibh",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Donec fringilla sem",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callToAction": {
|
||||||
|
"targetBlank": true,
|
||||||
|
"text": "Free 15-day trial",
|
||||||
|
"href": "#"
|
||||||
|
},
|
||||||
|
"hasRibbon": true,
|
||||||
|
"ribbonTitle": "popular"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "premium",
|
||||||
|
"price": 199,
|
||||||
|
"period": "Per Month",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"description": "Curabitur suscipit risus",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Aliquam blandit malesuada",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Suspendisse sit amet",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Suspendisse auctor dui",
|
||||||
|
"icon": "tabler:check"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"callToAction": {
|
||||||
|
"targetBlank": true,
|
||||||
|
"text": "Free 30-day trial",
|
||||||
|
"href": "#"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
Reference in New Issue
Block a user