Add useful components for ui

This commit is contained in:
prototypa
2023-07-27 14:51:09 -04:00
parent d20b298028
commit b51e3bdebc
7 changed files with 393 additions and 0 deletions

View File

@ -0,0 +1,7 @@
---
const { isDark = false } = Astro.props;
---
<div class:list={["absolute inset-0", { "bg-dark dark:bg-transparent": isDark }]}>
<slot />
</div>

View File

@ -0,0 +1,38 @@
---
import { Icon } from "astro-icon/components";
import type { CallToAction } from "~/types";
const { callToAction } = Astro.props;
const {
targetBlank,
text = "",
icon = "",
href = "",
} = callToAction as CallToAction;
---
<div class="flex w-auto">
{
targetBlank ? (
<a
class="inline-flex items-center justify-center"
href={href}
target="_blank"
rel="noopener noreferrer"
>
{text}
{icon && (
<Icon name={icon} class="w-5 h-5 ml-1 -mr-1.5 rtl:ml-1 rtl:-mr-1.5" />
)}
</a>
) : (
<a class="inline-flex items-center justify-center" href={href}>
{text}
{icon && (
<Icon name={icon} class="w-5 h-5 ml-1 -mr-1.5 rtl:ml-1 rtl:-mr-1.5" />
)}
</a>
)
}
</div>

View File

@ -0,0 +1,48 @@
---
import type { Headline } from "~/types";
import { twMerge } from "tailwind-merge";
const {
title = await Astro.slots.render("title"),
subtitle = await Astro.slots.render("subtitle"),
tagline,
classes = {},
} = Astro.props as Headline;
const {
container: containerClass = "max-w-3xl",
title: titleClass = "text-3xl md:text-4xl ",
subtitle: subtitleClass = "text-xl",
} = classes;
---
{
(title || subtitle || tagline) && (
<div
class={twMerge("mb-8 md:mx-auto md:mb-12 text-center", containerClass)}
>
{tagline && (
<p
class="text-base text-secondary dark:text-blue-200 font-bold tracking-wide uppercase"
set:html={tagline}
/>
)}
{title && (
<h2
class={twMerge(
"font-bold leading-tighter tracking-tighter font-heading text-heading text-3xl",
titleClass
)}
set:html={title}
/>
)}
{subtitle && (
<p
class={twMerge("mt-4 text-muted", subtitleClass)}
set:html={subtitle}
/>
)}
</div>
)
}

View File

@ -0,0 +1,100 @@
---
import { Icon } from "astro-icon/components";
import { twMerge } from "tailwind-merge";
import type { ItemGrid } from "~/types";
import CTA from "./CTA.astro";
const {
items = [],
columns,
defaultIcon = "",
classes = {},
} = Astro.props as ItemGrid;
const {
container: containerClass = "",
// container: containerClass = "md:grid-cols-2",
panel: panelClass = "",
title: titleClass = "",
description: descriptionClass = "",
icon: defaultIconClass = "text-primary",
} = classes;
---
{
items && (
<div
class={twMerge(
`grid mx-auto gap-8 gap-y-12 ${
columns === 4
? "lg:grid-cols-4 md:grid-cols-3 sm:grid-cols-2"
: columns === 3
? "lg:grid-cols-3 sm:grid-cols-2"
: columns === 2
? "sm:grid-cols-2 "
: ""
}`,
containerClass
)}
>
{items.map(
({
title,
description,
icon,
callToAction,
classes: itemClasses = {},
}) => (
<div>
<div
class={twMerge(
"flex flex-row max-w-md",
panelClass,
itemClasses?.panel
)}
>
<div class="flex justify-center">
{(icon || defaultIcon) && (
<Icon
name={icon || defaultIcon}
class={twMerge(
"w-7 h-7 mr-2 rtl:mr-0 rtl:ml-2",
defaultIconClass,
itemClasses?.icon
)}
/>
)}
</div>
<div>
<h3
class={twMerge(
"text-xl font-bold",
titleClass,
itemClasses?.title
)}
>
{title}
</h3>
{description && (
<p
class={twMerge(
`${title ? "mt-3" : ""} text-muted`,
descriptionClass,
itemClasses?.description
)}
set:html={description}
/>
)}
{callToAction && (
<div class="mt-2 text-primary cursor-pointer">
<CTA callToAction={callToAction} />
</div>
)}
</div>
</div>
</div>
)
)}
</div>
)
}

View File

@ -0,0 +1,94 @@
---
import { Icon } from "astro-icon/components";
import { twMerge } from "tailwind-merge";
import type { ItemGrid } from "~/types";
import CTA from "./CTA.astro";
const {
items = [],
columns,
defaultIcon = "",
classes = {},
} = Astro.props as ItemGrid;
const {
container: containerClass = "",
// container: containerClass = "sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
panel: panelClass = "",
title: titleClass = "",
description: descriptionClass = "",
icon: defaultIconClass = "text-primary",
} = classes;
---
{
items && (
<div
class={twMerge(
`grid gap-8 gap-x-12 sm:gap-y-8 ${
columns === 4
? "lg:grid-cols-4 md:grid-cols-3 sm:grid-cols-2"
: columns === 3
? "lg:grid-cols-3 sm:grid-cols-2"
: columns === 2
? "sm:grid-cols-2 "
: ""
}`,
containerClass
)}
>
{items.map(
({
title,
description,
icon,
callToAction,
classes: itemClasses = {},
}) => (
<div
class={twMerge(
"relative flex flex-col",
panelClass,
itemClasses?.panel
)}
>
{(icon || defaultIcon) && (
<Icon
name={icon || defaultIcon}
class={twMerge(
"mb-2 w-10 h-10",
defaultIconClass,
itemClasses?.icon
)}
/>
)}
<div
class={twMerge(
"text-xl font-bold",
titleClass,
itemClasses?.title
)}
>
{title}
</div>
{description && (
<p
class={twMerge(
"text-muted mt-2",
descriptionClass,
itemClasses?.description
)}
set:html={description}
/>
)}
{callToAction && (
<div class="mt-2 text-primary cursor-pointer">
<CTA callToAction={callToAction} />
</div>
)}
</div>
)
)}
</div>
)
}

View File

@ -0,0 +1,82 @@
---
import { Icon } from "astro-icon/components";
import { twMerge } from "tailwind-merge";
import type { Item } from "~/types";
export interface Props {
items?: Array<Item>;
defaultIcon?: string;
classes?: Record<string, string>;
}
const { items = [], classes = {}, defaultIcon } = Astro.props as Props;
const {
container: containerClass = "",
panel: panelClass = "",
title: titleClass = "",
description: descriptionClass = "",
icon: defaultIconClass = "text-primary dark:text-slate-200 border-primary dark:border-blue-700",
} = classes;
---
{
items && items.length && (
<div class={containerClass}>
{items.map(
(
{ title, description, icon, classes: itemClasses = {} },
index = 0
) => (
<div class={twMerge("flex", panelClass, itemClasses?.panel)}>
<div class="flex flex-col items-center mr-4">
<div>
<div class="flex items-center justify-center">
{(icon || defaultIcon) && (
<Icon
name={icon || defaultIcon}
class={twMerge(
"w-10 h-10 p-2 rounded-full border-2",
defaultIconClass,
itemClasses?.icon
)}
/>
)}
</div>
</div>
{index !== items.length - 1 && (
<div class="w-px h-full bg-black/10 dark:bg-slate-400/50" />
)}
</div>
<div
class={`max-w-md pt-1 ${
index !== items.length - 1 ? "pb-8" : ""
}`}
>
{title && (
<p
class={twMerge(
"text-xl font-bold",
titleClass,
itemClasses?.title
)}
set:html={title}
/>
)}
{description && (
<p
class={twMerge(
"text-muted mt-2",
descriptionClass,
itemClasses?.description
)}
set:html={description}
/>
)}
</div>
</div>
)
)}
</div>
)
}

View File

@ -0,0 +1,24 @@
---
import { twMerge } from "tailwind-merge";
import Background from "./Background.astro";
const { id, isDark = false, containerClass = "", bg, as = "section" } = Astro.props;
const WrapperTag = as;
---
<WrapperTag class="relative not-prose" {...id ? { id } : {}}>
<div class="absolute inset-0 pointer-events-none -z-[1]" aria-hidden="true">
<slot name="bg">
{bg ? <Fragment set:html={bg} /> : <Background isDark={isDark} />}
</slot>
</div>
<div
class:list={[
twMerge("relative mx-auto max-w-7xl px-4 md:px-6 py-12 md:py-16 lg:py-20 text-default", containerClass),
{ dark: isDark },
]}
>
<slot />
</div>
</WrapperTag>