Initial commit
This commit is contained in:
52
components/blocks/content.tsx
Normal file
52
components/blocks/content.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import React from "react";
|
||||
import { Container } from "../util/container";
|
||||
import { Section } from "../util/section";
|
||||
import { TinaMarkdown } from "tinacms/dist/rich-text";
|
||||
import type { TinaTemplate } from "tinacms";
|
||||
import { PageBlocksContent } from "../../tina/__generated__/types";
|
||||
import { tinaField } from "tinacms/dist/react";
|
||||
|
||||
export const Content = ({ data }: { data: PageBlocksContent }) => {
|
||||
return (
|
||||
<Section color={data.color}>
|
||||
<Container
|
||||
className={`prose prose-lg ${
|
||||
data.color === "primary" ? `prose-primary` : `dark:prose-dark`
|
||||
}`}
|
||||
data-tina-field={tinaField(data, "body")}
|
||||
size="large"
|
||||
width="medium"
|
||||
>
|
||||
<TinaMarkdown content={data.body} />
|
||||
</Container>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const contentBlockSchema: TinaTemplate = {
|
||||
name: "content",
|
||||
label: "Content",
|
||||
ui: {
|
||||
previewSrc: "/blocks/content.png",
|
||||
defaultItem: {
|
||||
body: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.",
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "rich-text",
|
||||
label: "Body",
|
||||
name: "body",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Color",
|
||||
name: "color",
|
||||
options: [
|
||||
{ label: "Default", value: "default" },
|
||||
{ label: "Tint", value: "tint" },
|
||||
{ label: "Primary", value: "primary" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
130
components/blocks/features.tsx
Normal file
130
components/blocks/features.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import { Section } from "../util/section";
|
||||
import { Container } from "../util/container";
|
||||
import { Icon } from "../util/icon";
|
||||
import { iconSchema } from "../util/icon";
|
||||
import {
|
||||
PageBlocksFeatures,
|
||||
PageBlocksFeaturesItems,
|
||||
} from "../../tina/__generated__/types";
|
||||
import { tinaField } from "tinacms/dist/react";
|
||||
|
||||
export const Feature = ({
|
||||
featuresColor,
|
||||
data,
|
||||
}: {
|
||||
featuresColor: string;
|
||||
data: PageBlocksFeaturesItems;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
data-tina-field={tinaField(data)}
|
||||
className="flex-1 flex flex-col gap-6 text-center items-center lg:items-start lg:text-left max-w-xl mx-auto"
|
||||
style={{ flexBasis: "16rem" }}
|
||||
>
|
||||
{data.icon && (
|
||||
<Icon
|
||||
tinaField={tinaField(data, "icon")}
|
||||
parentColor={featuresColor}
|
||||
data={{ size: "large", ...data.icon }}
|
||||
/>
|
||||
)}
|
||||
{data.title && (
|
||||
<h3
|
||||
data-tina-field={tinaField(data, "title")}
|
||||
className="text-2xl font-semibold title-font"
|
||||
>
|
||||
{data.title}
|
||||
</h3>
|
||||
)}
|
||||
{data.text && (
|
||||
<p
|
||||
data-tina-field={tinaField(data, "text")}
|
||||
className="text-base opacity-80 leading-relaxed"
|
||||
>
|
||||
{data.text}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Features = ({ data }: { data: PageBlocksFeatures }) => {
|
||||
return (
|
||||
<Section color={data.color}>
|
||||
<Container
|
||||
className={`flex flex-wrap gap-x-10 gap-y-8 text-left`}
|
||||
size="large"
|
||||
>
|
||||
{data.items &&
|
||||
data.items.map(function (block, i) {
|
||||
return <Feature featuresColor={data.color} key={i} data={block} />;
|
||||
})}
|
||||
</Container>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const defaultFeature = {
|
||||
title: "Here's Another Feature",
|
||||
text: "This is where you might talk about the feature, if this wasn't just filler text.",
|
||||
icon: {
|
||||
color: "",
|
||||
style: "float",
|
||||
name: "",
|
||||
},
|
||||
};
|
||||
|
||||
export const featureBlockSchema = {
|
||||
name: "features",
|
||||
label: "Features",
|
||||
ui: {
|
||||
previewSrc: "/blocks/features.png",
|
||||
defaultItem: {
|
||||
items: [defaultFeature, defaultFeature, defaultFeature],
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "object",
|
||||
label: "Feature Items",
|
||||
name: "items",
|
||||
list: true,
|
||||
ui: {
|
||||
itemProps: (item) => {
|
||||
return {
|
||||
label: item?.title,
|
||||
};
|
||||
},
|
||||
defaultItem: {
|
||||
...defaultFeature,
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
iconSchema,
|
||||
{
|
||||
type: "string",
|
||||
label: "Title",
|
||||
name: "title",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Text",
|
||||
name: "text",
|
||||
ui: {
|
||||
component: "textarea",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Color",
|
||||
name: "color",
|
||||
options: [
|
||||
{ label: "Default", value: "default" },
|
||||
{ label: "Tint", value: "tint" },
|
||||
{ label: "Primary", value: "primary" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
184
components/blocks/hero.tsx
Normal file
184
components/blocks/hero.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
import * as React from "react";
|
||||
import { Actions } from "../util/actions";
|
||||
import { Container } from "../util/container";
|
||||
import { Section } from "../util/section";
|
||||
import { TinaMarkdown } from "tinacms/dist/rich-text";
|
||||
import type { TinaTemplate } from "tinacms";
|
||||
import { PageBlocksHero } from "../../tina/__generated__/types";
|
||||
import { tinaField } from "tinacms/dist/react";
|
||||
|
||||
export const Hero = ({ data }: { data: PageBlocksHero }) => {
|
||||
const headlineColorClasses = {
|
||||
blue: "from-blue-400 to-blue-600",
|
||||
teal: "from-teal-400 to-teal-600",
|
||||
green: "from-green-400 to-green-600",
|
||||
red: "from-red-400 to-red-600",
|
||||
pink: "from-pink-400 to-pink-600",
|
||||
purple: "from-purple-400 to-purple-600",
|
||||
orange: "from-orange-300 to-orange-600",
|
||||
yellow: "from-yellow-400 to-yellow-600",
|
||||
};
|
||||
|
||||
return (
|
||||
<Section color={data.color}>
|
||||
<Container
|
||||
size="large"
|
||||
className="grid grid-cols-1 md:grid-cols-5 gap-14 items-center justify-center"
|
||||
>
|
||||
<div className="row-start-2 md:row-start-1 md:col-span-3 text-center md:text-left">
|
||||
{data.tagline && (
|
||||
<h2
|
||||
data-tina-field={tinaField(data, "tagline")}
|
||||
className="relative inline-block px-3 py-1 mb-8 text-md font-bold tracking-wide title-font z-20"
|
||||
>
|
||||
{data.tagline}
|
||||
<span className="absolute w-full h-full left-0 top-0 rounded-full -z-1 bg-current opacity-7"></span>
|
||||
</h2>
|
||||
)}
|
||||
{data.headline && (
|
||||
<h3
|
||||
data-tina-field={tinaField(data, "headline")}
|
||||
className={`w-full relative mb-10 text-5xl font-extrabold tracking-normal leading-tight title-font`}
|
||||
>
|
||||
<span
|
||||
className={"bg-clip-text text-transparent bg-gradient-to-r from-white to-gray-100"}
|
||||
>
|
||||
{data.headline}
|
||||
</span>
|
||||
</h3>
|
||||
)}
|
||||
{data.text && (
|
||||
<div
|
||||
data-tina-field={tinaField(data, "text")}
|
||||
className={"prose prose-lg mx-auto md:mx-0 mb-10 prose-primary" }
|
||||
>
|
||||
<TinaMarkdown content={data.text} />
|
||||
</div>
|
||||
)}
|
||||
{data.actions && (
|
||||
<Actions
|
||||
className="justify-center md:justify-start py-2"
|
||||
parentColor={data.color}
|
||||
actions={data.actions}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{data.image && (
|
||||
<div
|
||||
data-tina-field={tinaField(data.image, "src")}
|
||||
className="relative row-start-1 md:col-span-2 flex justify-center"
|
||||
>
|
||||
<img
|
||||
className="absolute w-full rounded-lg max-w-xs md:max-w-none h-auto blur-2xl brightness-150 contrast-[0.9] dark:brightness-150 saturate-200 opacity-50 dark:opacity-30 mix-blend-multiply dark:mix-blend-hard-light"
|
||||
src={data.image.src}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<img
|
||||
className="relative z-10 w-full max-w-xs rounded-lg md:max-w-none h-auto"
|
||||
alt={data.image.alt}
|
||||
src={data.image.src}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Container>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const heroBlockSchema: TinaTemplate = {
|
||||
name: "hero",
|
||||
label: "Hero",
|
||||
ui: {
|
||||
previewSrc: "/blocks/hero.png",
|
||||
defaultItem: {
|
||||
tagline: "Here's some text above the other text",
|
||||
headline: "This Big Text is Totally Awesome",
|
||||
text: "Phasellus scelerisque, libero eu finibus rutrum, risus risus accumsan libero, nec molestie urna dui a leo.",
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Tagline",
|
||||
name: "tagline",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Headline",
|
||||
name: "headline",
|
||||
},
|
||||
{
|
||||
label: "Text",
|
||||
name: "text",
|
||||
type: "rich-text",
|
||||
},
|
||||
{
|
||||
label: "Actions",
|
||||
name: "actions",
|
||||
type: "object",
|
||||
list: true,
|
||||
ui: {
|
||||
defaultItem: {
|
||||
label: "Action Label",
|
||||
type: "button",
|
||||
icon: true,
|
||||
link: "/",
|
||||
},
|
||||
itemProps: (item) => ({ label: item.label }),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
label: "Label",
|
||||
name: "label",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: "Type",
|
||||
name: "type",
|
||||
type: "string",
|
||||
options: [
|
||||
{ label: "Button", value: "button" },
|
||||
{ label: "Link", value: "link" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Icon",
|
||||
name: "icon",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: "Link",
|
||||
name: "link",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
label: "Image",
|
||||
name: "image",
|
||||
fields: [
|
||||
{
|
||||
name: "src",
|
||||
label: "Image Source",
|
||||
type: "image",
|
||||
},
|
||||
{
|
||||
name: "alt",
|
||||
label: "Alt Text",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Color",
|
||||
name: "color",
|
||||
options: [
|
||||
{ label: "Default", value: "default" },
|
||||
{ label: "Tint", value: "tint" },
|
||||
{ label: "Primary", value: "primary" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
101
components/blocks/testimonial.tsx
Normal file
101
components/blocks/testimonial.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import React from "react";
|
||||
import { Container } from "../util/container";
|
||||
import { Section } from "../util/section";
|
||||
import type { TinaTemplate } from "tinacms";
|
||||
import { PageBlocksTestimonial } from "../../tina/__generated__/types";
|
||||
import { tinaField } from "tinacms/dist/react";
|
||||
|
||||
export const Testimonial = ({ data }: { data: PageBlocksTestimonial }) => {
|
||||
return (
|
||||
<Section color={data.color}>
|
||||
<Container size="large">
|
||||
<blockquote>
|
||||
<div
|
||||
className={`relative z-10 max-w-3xl mx-auto text-4xl lg:text-5xl font-bold tracking-normal text-center title-font ${
|
||||
data.color === "primary"
|
||||
? `text-white`
|
||||
: `text-gray-700 dark:text-gray-50`
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`block opacity-15 text-8xl absolute inset-y-1/2 transform translate-y-2 -left-4 leading-4 -z-1`}
|
||||
>
|
||||
“
|
||||
</span>
|
||||
<p
|
||||
data-tina-field={tinaField(data, `quote`)}
|
||||
className="relative opacity-95"
|
||||
>
|
||||
{data.quote}
|
||||
</p>
|
||||
<span
|
||||
className={`block opacity-15 text-8xl absolute inset-y-1/2 transform translate-y-3 -right-4 leading-4 -z-1`}
|
||||
>
|
||||
”
|
||||
</span>
|
||||
</div>
|
||||
<div className={`my-8 flex-grow-0`}>
|
||||
<span
|
||||
className={`block mx-auto h-0.5 w-1/6 ${
|
||||
data.color === "primary"
|
||||
? `bg-blue-600`
|
||||
: `bg-gray-200 dark:bg-gray-700`
|
||||
}`}
|
||||
></span>
|
||||
</div>
|
||||
<footer className="text-center">
|
||||
<p
|
||||
data-tina-field={tinaField(data, `author`)}
|
||||
className={`tracking-wide title-font font-bold text-lg ${
|
||||
data.color === "primary"
|
||||
? `text-blue-200`
|
||||
: `text-blue-500 dark:text-blue-300`
|
||||
}`}
|
||||
>
|
||||
{data.author}
|
||||
</p>
|
||||
</footer>
|
||||
</blockquote>
|
||||
</Container>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const testimonialBlockSchema: TinaTemplate = {
|
||||
name: "testimonial",
|
||||
label: "Testimonial",
|
||||
ui: {
|
||||
previewSrc: "/blocks/testimonial.png",
|
||||
defaultItem: {
|
||||
quote:
|
||||
"There are only two hard things in Computer Science: cache invalidation and naming things.",
|
||||
author: "Phil Karlton",
|
||||
color: "primary",
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
ui: {
|
||||
component: "textarea",
|
||||
},
|
||||
label: "Quote",
|
||||
name: "quote",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Author",
|
||||
name: "author",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Color",
|
||||
name: "color",
|
||||
options: [
|
||||
{ label: "Default", value: "default" },
|
||||
{ label: "Tint", value: "tint" },
|
||||
{ label: "Primary", value: "primary" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user