📝 Improve blog capabilities and components
This commit is contained in:
@@ -1,9 +1,29 @@
|
||||
/* eslint-disable jsx-a11y/alt-text */
|
||||
'use client'
|
||||
|
||||
import { Link } from '@chakra-ui/next-js'
|
||||
import { Heading, Stack, Text } from '@chakra-ui/react'
|
||||
import {
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Heading,
|
||||
Stack,
|
||||
Table,
|
||||
TableCaption,
|
||||
TableContainer,
|
||||
Tbody,
|
||||
Td,
|
||||
Text,
|
||||
Tfoot,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
Image,
|
||||
} from '@chakra-ui/react'
|
||||
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'
|
||||
import { highlight } from 'sugar-high'
|
||||
import { Tweet } from './Tweet'
|
||||
import { Standard } from '@typebot.io/nextjs'
|
||||
import { EndCta } from '@/components/Homepage/EndCta'
|
||||
|
||||
type Props = {
|
||||
metadata: {
|
||||
@@ -14,7 +34,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const Post = ({ metadata, mdxSource }: Props) => (
|
||||
<Stack spacing={10} my="20">
|
||||
<Stack spacing={10} my="20" w="full">
|
||||
<Stack mx="auto" w="full" maxW="65ch">
|
||||
<Heading>{metadata.title}</Heading>
|
||||
<Text>{formatDate(metadata.publishedAt)}</Text>
|
||||
@@ -23,7 +43,7 @@ export const Post = ({ metadata, mdxSource }: Props) => (
|
||||
mx="auto"
|
||||
spacing={0}
|
||||
as="article"
|
||||
className="prose prose-quoteless prose-neutral prose-invert"
|
||||
className="prose prose-quoteless prose-neutral prose-invert max-w-none w-full px-3 sm:px-0"
|
||||
>
|
||||
<MDXRemote
|
||||
{...mdxSource}
|
||||
@@ -42,6 +62,87 @@ export const Post = ({ metadata, mdxSource }: Props) => (
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
link: (props: any) => <Link {...props} />,
|
||||
Image: (props) => (
|
||||
<Image rounded="md" maxW={['full', '65ch']} {...props} />
|
||||
),
|
||||
Callout: ({ children, ...props }) => (
|
||||
<Alert rounded="md" {...props}>
|
||||
<AlertIcon />
|
||||
{children}
|
||||
</Alert>
|
||||
),
|
||||
Tweet,
|
||||
Typebot: Standard,
|
||||
Youtube: ({ id }: { id: string }) => (
|
||||
<div className="w-full">
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
paddingBottom: '64.63195691202873%',
|
||||
height: 0,
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<iframe
|
||||
src={`https://www.youtube.com/embed/${id}`}
|
||||
allowFullScreen
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
Loom: ({ id }: { id: string }) => (
|
||||
<div className="w-full">
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
paddingBottom: '64.63195691202873%',
|
||||
height: 0,
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<iframe
|
||||
src={`https://www.loom.com/embed/${id}`}
|
||||
allowFullScreen
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
Cta: (props) => (
|
||||
<EndCta
|
||||
{...props}
|
||||
style={{ maxWidth: 'none' }}
|
||||
w="full"
|
||||
height="70vh"
|
||||
className="w-full"
|
||||
bgGradient={undefined}
|
||||
/>
|
||||
),
|
||||
table: (props) => (
|
||||
<TableContainer>
|
||||
<Table {...props} />
|
||||
</TableContainer>
|
||||
),
|
||||
thead: Thead,
|
||||
tbody: Tbody,
|
||||
th: Th,
|
||||
td: Td,
|
||||
tfoot: Tfoot,
|
||||
tr: Tr,
|
||||
caption: TableCaption,
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
36
apps/landing-page/app/blog/[slug]/Tweet.tsx
Normal file
36
apps/landing-page/app/blog/[slug]/Tweet.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { getTweet } from 'react-tweet/api'
|
||||
import { EmbeddedTweet, TweetNotFound, type TweetProps } from 'react-tweet'
|
||||
import './tweet.css'
|
||||
|
||||
const TweetContent = async ({ id, components, onError }: TweetProps) => {
|
||||
let error
|
||||
const tweet = id
|
||||
? await getTweet(id).catch((err) => {
|
||||
if (onError) {
|
||||
error = onError(err)
|
||||
} else {
|
||||
console.error(err)
|
||||
error = err
|
||||
}
|
||||
})
|
||||
: undefined
|
||||
|
||||
if (!tweet) {
|
||||
const NotFound = components?.TweetNotFound || TweetNotFound
|
||||
return <NotFound error={error} />
|
||||
}
|
||||
|
||||
return <EmbeddedTweet tweet={tweet} components={components} />
|
||||
}
|
||||
|
||||
export const ReactTweet = (props: TweetProps) => <TweetContent {...props} />
|
||||
|
||||
export async function Tweet({ id }: { id: string }) {
|
||||
return (
|
||||
<div className="tweet my-6">
|
||||
<div className={`flex justify-center`}>
|
||||
<ReactTweet id={id} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
63
apps/landing-page/app/blog/[slug]/tweet.css
Normal file
63
apps/landing-page/app/blog/[slug]/tweet.css
Normal file
@@ -0,0 +1,63 @@
|
||||
/* Light theme (default) */
|
||||
.tweet .react-tweet-theme {
|
||||
/* margin is handled by our wrappers */
|
||||
--tweet-container-margin: 0;
|
||||
--tweet-font-family: inherit;
|
||||
--tweet-font-color: inherit;
|
||||
|
||||
--tweet-bg-color: #222;
|
||||
--tweet-bg-color-hover: var(--tweet-bg-color);
|
||||
--tweet-quoted-bg-color-hover: rgba(255, 255, 255, 0.03);
|
||||
--tweet-border: 1px solid #333;
|
||||
--tweet-color-blue-secondary: theme('colors.white');
|
||||
--tweet-color-blue-secondary-hover: #333;
|
||||
--tweet-font-color-secondary: theme('colors.gray.400');
|
||||
|
||||
/* Common properties for both themes */
|
||||
--tweet-quoted-bg-color-hover: rgba(0, 0, 0, 0.03);
|
||||
--tweet-border: 1px solid rgb(64, 64, 64);
|
||||
--tweet-skeleton-gradient: linear-gradient(
|
||||
270deg,
|
||||
#fafafa,
|
||||
#eaeaea,
|
||||
#eaeaea,
|
||||
#fafafa
|
||||
);
|
||||
--tweet-color-red-primary: rgb(249, 24, 128);
|
||||
--tweet-color-red-primary-hover: rgba(249, 24, 128, 0.1);
|
||||
--tweet-color-green-primary: rgb(0, 186, 124);
|
||||
--tweet-color-green-primary-hover: rgba(0, 186, 124, 0.1);
|
||||
--tweet-twitter-icon-color: var(--tweet-font-color);
|
||||
--tweet-verified-old-color: rgb(130, 154, 171);
|
||||
--tweet-verified-blue-color: var(--tweet-color-blue-primary);
|
||||
|
||||
--tweet-actions-font-weight: 500;
|
||||
--tweet-replies-font-weight: 500;
|
||||
}
|
||||
|
||||
/* Common styles for both themes */
|
||||
.tweet .react-tweet-theme p {
|
||||
font-size: inherit;
|
||||
line-height: 1.3rem;
|
||||
}
|
||||
|
||||
.tweet .react-tweet-theme p a {
|
||||
@apply border-b transition-[border-color] border-gray-500 text-white hover:border-white;
|
||||
}
|
||||
|
||||
/* Remove link underline on hover for both themes */
|
||||
.tweet .react-tweet-theme p a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tweet a div {
|
||||
@apply font-medium tracking-tight;
|
||||
}
|
||||
|
||||
.tweet div[class*='mediaWrapper'] {
|
||||
max-height: 250px;
|
||||
}
|
||||
|
||||
.tweet .react-tweet-theme img {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import type { Metadata } from 'next'
|
||||
import { Header } from 'components/common/Header/Header'
|
||||
import { Footer } from 'components/common/Footer'
|
||||
import { Providers } from './providers'
|
||||
import { EndCta } from '@/components/Homepage/EndCta'
|
||||
import 'assets/style.css'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -33,7 +32,6 @@ export default function RootLayout({
|
||||
<Providers>
|
||||
<Header />
|
||||
{children}
|
||||
<EndCta />
|
||||
<Footer />
|
||||
</Providers>
|
||||
</body>
|
||||
|
||||
@@ -13,3 +13,9 @@
|
||||
--sh-keyword: #f47067;
|
||||
--sh-comment: #a19595;
|
||||
}
|
||||
|
||||
.prose > * {
|
||||
max-width: 65ch;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import { Heading, Button, Text, Flex, VStack } from '@chakra-ui/react'
|
||||
import {
|
||||
Heading,
|
||||
Button,
|
||||
Text,
|
||||
Flex,
|
||||
VStack,
|
||||
StackProps,
|
||||
} from '@chakra-ui/react'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { BackgroundPolygons } from './Hero/BackgroundPolygons'
|
||||
|
||||
export const EndCta = () => {
|
||||
export const EndCta = (props: StackProps) => {
|
||||
return (
|
||||
<VStack
|
||||
as="section"
|
||||
@@ -14,6 +21,7 @@ export const EndCta = () => {
|
||||
bgGradient="linear(to-b, gray.900, gray.800)"
|
||||
height="100vh"
|
||||
justifyContent="center"
|
||||
{...props}
|
||||
>
|
||||
<BackgroundPolygons />
|
||||
<VStack
|
||||
@@ -29,7 +37,7 @@ export const EndCta = () => {
|
||||
letterSpacing="tight"
|
||||
data-aos="fade-up"
|
||||
>
|
||||
Take your forms to the next level
|
||||
Improve conversion and user engagement with typebots
|
||||
</Heading>
|
||||
<Flex>
|
||||
<Button
|
||||
@@ -46,7 +54,7 @@ export const EndCta = () => {
|
||||
</Flex>
|
||||
|
||||
<Text color="gray.400" data-aos="fade-up" data-aos-delay="400">
|
||||
No trial. Generous, unlimited <strong>free</strong> plan.
|
||||
No trial. Generous <strong>free</strong> plan.
|
||||
</Text>
|
||||
</VStack>
|
||||
</VStack>
|
||||
|
||||
@@ -3,6 +3,18 @@ title: 'Blog post example'
|
||||
summary: 'A short summary of the blog post.'
|
||||
---
|
||||
|
||||
This is a blog post example.
|
||||
<Image src="/images/builder-screenshot.png" alt="awesome image" />
|
||||
|
||||
This can be deleted once we published the first blog post.
|
||||
<Callout rounded='md'>
|
||||
|
||||
This is a callout. It can be used to highlight important information.
|
||||
|
||||
</Callout>
|
||||
|
||||
<Tweet id="1780513200565285038" />
|
||||
|
||||
Occaecat nostrud fugiat aliqua non deserunt ad adipisicing amet anim do commodo aliquip ipsum esse. Aute nisi voluptate nisi excepteur nulla velit incididunt aute laborum culpa Lorem magna reprehenderit. Aliqua cupidatat nisi ut nisi. Cillum irure enim officia aute nulla. Sunt culpa deserunt sunt. Laborum ipsum ad proident cillum officia culpa enim do id quis eiusmod.
|
||||
|
||||
<Cta />
|
||||
|
||||
Occaecat nostrud fugiat aliqua non deserunt ad adipisicing amet anim do commodo aliquip ipsum esse. Aute nisi voluptate nisi excepteur nulla velit incididunt aute laborum culpa Lorem magna reprehenderit. Aliqua cupidatat nisi ut nisi. Cillum irure enim officia aute nulla. Sunt culpa deserunt sunt. Laborum ipsum ad proident cillum officia culpa enim do id quis eiusmod.
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"next-mdx-remote": "4.4.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-tweet": "3.2.1",
|
||||
"sugar-high": "0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Reference in New Issue
Block a user