Start rearranging and simplifying widgets

This commit is contained in:
prototypa
2023-07-27 14:51:46 -04:00
parent b51e3bdebc
commit 15ef9ee3e0
11 changed files with 419 additions and 330 deletions

View File

@ -11,7 +11,7 @@ interface Item {
export interface Props {
title?: string;
subtitle?: string;
highlight?: string;
tagline?: string;
content?: string;
items?: Array<Item>;
image?: string | any; // TODO: find HTMLElementProps
@ -22,7 +22,7 @@ export interface Props {
const {
title = await Astro.slots.render('title'),
subtitle = await Astro.slots.render('subtitle'),
highlight,
tagline,
content = await Astro.slots.render('content'),
items = [],
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']}>
<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">
{highlight && (
{tagline && (
<p
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
set:html={highlight}
set:html={tagline}
/>
)}
{title && (

View File

@ -1,66 +1,37 @@
---
import { Icon } from 'astro-icon/components';
interface Item {
question: string;
answer: string;
}
export interface Props {
title?: string;
subtitle?: string;
highlight?: string;
items: Array<Array<Item>>;
}
import Headline from "~/components/ui/Headline.astro";
import ItemGrid from "~/components/ui/ItemGrid.astro";
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
import type { Faqs } from "~/types";
const {
title = await Astro.slots.render('title'),
subtitle = await Astro.slots.render('subtitle'),
highlight,
title = "",
subtitle = "",
tagline = "",
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">
<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 dark:text-blue-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-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>
<WidgetWrapper
id={id}
isDark={isDark}
containerClass={`max-w-screen-xl mx-auto ${classes?.container ?? ""}`}
bg={bg}
>
<Headline title={title} subtitle={subtitle} tagline={tagline} />
<ItemGrid
items={items}
columns={columns}
defaultIcon="tabler:chevron-right"
classes={{
panel: 'max-w-none',
icon: "flex-shrink-0 mt-1 w-6 h-6 text-primary",
}}
/>
</WidgetWrapper>

View File

@ -1,71 +1,43 @@
---
import { Icon } from 'astro-icon/components';
interface Item {
title: string;
description: string;
icon?: string;
}
export interface Props {
title?: string;
subtitle?: string;
highlight?: string;
items: Array<Array<Item>>;
}
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
import ItemGrid from "~/components/ui/ItemGrid.astro";
import Headline from "~/components/ui/Headline.astro";
import type { Features } from "~/types";
const {
title = await Astro.slots.render('title'),
subtitle = await Astro.slots.render('subtitle'),
highlight,
title = await Astro.slots.render("title"),
subtitle = await Astro.slots.render("subtitle"),
tagline = await Astro.slots.render("tagline"),
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">
<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 dark:text-blue-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-muted 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 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>
<WidgetWrapper
id={id}
isDark={isDark}
containerClass={`max-w-5xl ${classes?.container ?? ""}`}
bg={bg}
>
<Headline
title={title}
subtitle={subtitle}
tagline={tagline}
classes={classes?.headline}
/>
<ItemGrid
items={items}
columns={columns}
classes={{
container: "",
title: "md:text-[1.3rem]",
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",
...((classes?.items as {}) ?? {}),
}}
/>
</WidgetWrapper>

View File

@ -1,69 +1,46 @@
---
import { Icon } from 'astro-icon/components';
interface Item {
title?: string;
description?: string;
icon?: string;
}
export interface Props {
title?: string;
subtitle?: string;
highlight?: string;
items: Array<Item>;
}
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
import Headline from "~/components/ui/Headline.astro";
import ItemGrid2 from "~/components/ui/ItemGrid2.astro";
import type { Features } from "~/types";
const {
title = await Astro.slots.render('title'),
subtitle = await Astro.slots.render('subtitle'),
highlight,
title = await Astro.slots.render("title"),
subtitle = await Astro.slots.render("subtitle"),
tagline = await Astro.slots.render("tagline"),
items = [],
} = Astro.props;
columns = 3,
id,
isDark = false,
classes = {},
bg = await Astro.slots.render("bg"),
} = Astro.props as Features;
---
<section class="relative not-prose">
<div class="absolute inset-0 bg-blue-50 dark:bg-slate-800 pointer-events-none mb-32" aria-hidden="true"></div>
<div class="relative max-w-7xl 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 dark:text-blue-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-muted 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-muted dark:text-gray-400 text-md mt-4" set:html={description} />}
</div>
))
}
</div>
</div>
</div>
</section>
<WidgetWrapper
id={id}
isDark={isDark}
containerClass={classes?.container}
bg={bg}
>
<Headline
title={title}
subtitle={subtitle}
tagline={tagline}
classes={classes?.headline}
/>
<ItemGrid2
items={items}
columns={columns}
classes={{
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:
// "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",
icon: "w-12 h-12 mb-6 text-primary",
...((classes?.items as {}) ?? {}),
}}
/>
</WidgetWrapper>

View File

@ -16,6 +16,7 @@ interface Link {
interface ActionLink extends Link {
class?: string;
type?: string;
}
interface MenuLink extends Link {

View 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>

View File

@ -7,25 +7,25 @@ interface Item {
export interface Props {
title?: string;
subtitle?: string;
highlight?: string;
tagline?: string;
items?: Array<Item>;
}
const {
title = await Astro.slots.render('title'),
subtitle = await Astro.slots.render('subtitle'),
highlight,
tagline,
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 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">
{highlight && (
{tagline && (
<p class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase">
{highlight}
{tagline}
</p>
)}
{title && (

View File

@ -1,58 +1,37 @@
---
import { Icon } from 'astro-icon/components';
import { Picture } from '@astrojs/image/components';
interface Item {
title: string;
description?: string;
icon?: string;
}
export interface Props {
title?: string;
items: Array<Item>;
image?: string | any; // TODO: find HTMLElementProps
}
import WidgetWrapper from "~/components/ui/WidgetWrapper.astro";
import Timeline from "~/components/ui/Timeline.astro";
import Headline from "~/components/ui/Headline.astro";
import type { Steps } from "~/types";
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 = [],
image = await Astro.slots.render('image'),
} = Astro.props;
image = await Astro.slots.render("image"),
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">
<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 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>
))
}
<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-6xl ${classes?.container ?? ""}`} bg={bg}>
<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:basis-1/2 md:self-center">
<Headline
title={title}
subtitle={subtitle}
tagline={tagline}
classes={{ container: "text-left", title: "text-3xl lg:text-4xl", ...((classes?.headline as {}) ?? {}) }}
/>
<Timeline items={items} classes={classes?.items as {}} />
</div>
<div class="relative">
<div class="relative md:basis-1/2">
{
image &&
(typeof image === 'string' ? (
@ -71,4 +50,4 @@ const {
}
</div>
</div>
</section>
</WidgetWrapper>

View File

@ -11,7 +11,7 @@ interface Item {
export interface Props {
title?: string;
subtitle?: string;
highlight?: string;
tagline?: string;
callToAction?: string | CallToAction;
items: Array<Item>;
}
@ -19,7 +19,7 @@ export interface Props {
const {
title = await Astro.slots.render('title'),
subtitle = await Astro.slots.render('subtitle'),
highlight,
tagline,
callToAction = await Astro.slots.render('callToAction'),
items = [],
} = Astro.props;
@ -66,10 +66,10 @@ const {
<div class="w-full lg:w-1/2 px-0 sm:px-8 mb-12">
<div>
{
highlight && (
tagline && (
<p
class="text-base text-primary dark:text-blue-200 font-semibold tracking-wide uppercase"
set:html={highlight}
set:html={tagline}
/>
)
}