2
0

feat(editor): Team workspaces

This commit is contained in:
Baptiste Arnaud
2022-05-13 15:22:44 -07:00
parent 6c2986590b
commit f0fdf08b00
132 changed files with 3354 additions and 1228 deletions

View File

@@ -0,0 +1,15 @@
import Icon, { IconProps } from '@chakra-ui/icon'
import React from 'react'
export const CheckCircleIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
width="18px"
fill="white"
{...props}
>
<title>Checkmark Circle</title>
<path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm108.25 138.29l-134.4 160a16 16 0 01-12 5.71h-.27a16 16 0 01-11.89-5.3l-57.6-64a16 16 0 1123.78-21.4l45.29 50.32 122.59-145.91a16 16 0 0124.5 20.58z" />
</Icon>
)

View File

@@ -1,15 +1,15 @@
import Icon, { IconProps } from '@chakra-ui/icon'
import React from 'react'
import { featherIconsBaseProps } from '.'
export const CheckIcon = (props: IconProps) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
width="18px"
fill="white"
viewBox="0 0 24 24"
fill="currentcolor"
{...featherIconsBaseProps}
{...props}
>
<title>Checkmark Circle</title>
<path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm108.25 138.29l-134.4 160a16 16 0 01-12 5.71h-.27a16 16 0 01-11.89-5.3l-57.6-64a16 16 0 1123.78-21.4l45.29 50.32 122.59-145.91a16 16 0 0124.5 20.58z" />
<polyline points="20 6 9 17 4 12"></polyline>
</Icon>
)

View File

@@ -0,0 +1,10 @@
import { IconProps, Icon } from '@chakra-ui/react'
import { featherIconsBaseProps } from './HamburgerIcon'
export const HelpCircleIcon = (props: IconProps) => (
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
<circle cx="12" cy="12" r="10"></circle>
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
<line x1="12" y1="17" x2="12.01" y2="17"></line>
</Icon>
)

View File

@@ -0,0 +1,384 @@
import {
TableContainer,
Table,
Thead,
Tr,
Th,
Tbody,
Td,
Text,
Stack,
StackProps,
HStack,
Tooltip,
chakra,
Button,
Heading,
} from '@chakra-ui/react'
import { CheckIcon } from 'assets/icons/CheckIcon'
import { HelpCircleIcon } from 'assets/icons/HelpCircleIcon'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import React from 'react'
type Props = {
prices: {
personalPro: '$39' | '39€' | ''
team: '$99' | '99€' | ''
}
} & StackProps
export const PlanComparisonTables = ({ prices, ...props }: Props) => {
return (
<Stack spacing="12" {...props}>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th fontWeight="bold" color="white" w="400px">
Usage
</Th>
<Th>Personal</Th>
<Th color="orange.200">Personal Pro</Th>
<Th color="purple.200">Team</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Forms</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>Form submissions</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>Members</Td>
<Td>Just you</Td>
<Td>Just you</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>Guests</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>File uploads</Td>
<Td>5 MB</Td>
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th fontWeight="bold" color="white" w="400px">
Features
</Th>
<Th>Personal</Th>
<Th color="orange.200">Personal Pro</Th>
<Th color="purple.200">Team</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<TdWithTooltip
text="20+ blocks"
tooltip="Includes display bubbles (text, image, video, embed), question inputs (email, url, phone number...) and logic blocks (conditions, set variables...)"
/>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Starter templates</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Webhooks</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Google Sheets</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Google Analytics</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Send emails</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Zapier</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Pabbly Connect</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Make.com</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Custom Javascript & CSS</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Export CSV</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Custom domains</Td>
<Td />
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<TdWithTooltip
text="Folders"
tooltip="Organize your typebots into folders"
/>
<Td />
<Td>Unlimited</Td>
<Td>Unlimited</Td>
</Tr>
<Tr>
<Td>Remove branding</Td>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<TdWithTooltip
text="Incomplete submissions"
tooltip="You get to see the form submission even if it was not fully completed by your user."
/>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<TdWithTooltip
text="In-depth analytics"
tooltip="Analytics graph that shows your form drop-off rate, submission rate, and more."
/>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
<TableContainer>
<Table>
<Thead>
<Tr>
<Th fontWeight="bold" color="white" w="400px">
Support
</Th>
<Th>Personal</Th>
<Th color="orange.200">Personal Pro</Th>
<Th color="purple.200">Team</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>Priority support</Td>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
<Tr>
<Td>Feature request priority</Td>
<Td />
<Td>
<CheckIcon />
</Td>
<Td>
<CheckIcon />
</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
<Stack
direction={['column', 'row']}
spacing={4}
w="full"
justify="space-around"
>
<Stack spacing={4}>
<Heading as="h3" size="md">
Personal
</Heading>
<Heading as="h3">Free</Heading>
<NextChakraLink
href="https://app.typebot.io/register"
_hover={{ textDecor: 'none' }}
>
<Button variant="outline">Get started</Button>
</NextChakraLink>
</Stack>
<Stack spacing={4}>
<Heading as="h3" size="md" color="orange.200">
Personal Pro
</Heading>
<Heading as="h3">
{prices.personalPro}{' '}
<chakra.span fontSize="lg">/ month</chakra.span>
</Heading>
<NextChakraLink
href="https://app.typebot.io/register?subscribePlan=pro"
_hover={{ textDecor: 'none' }}
>
<Button>Subscribe</Button>
</NextChakraLink>
</Stack>
<Stack spacing={4}>
<Heading as="h3" size="md" color="purple.200">
Team
</Heading>
<Heading as="h3">
{prices.team} <chakra.span fontSize="lg">/ month</chakra.span>
</Heading>
<NextChakraLink
href="https://app.typebot.io/register?subscribePlan=team"
_hover={{ textDecor: 'none' }}
>
<Button>Subscribe</Button>
</NextChakraLink>
</Stack>
</Stack>
</Stack>
)
}
const TdWithTooltip = ({
text,
tooltip,
}: {
text: string
tooltip: string
}) => (
<Td as={HStack}>
<Text>{text}</Text>
<Tooltip hasArrow placement="top" label={tooltip}>
<chakra.span cursor="pointer">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</Td>
)

View File

@@ -9,13 +9,14 @@ import {
VStack,
} from '@chakra-ui/react'
import * as React from 'react'
import { CheckIcon } from '../../../assets/icons/CheckIcon'
import { CheckCircleIcon } from '../../../assets/icons/CheckCircleIcon'
import { Card, CardProps } from './Card'
export interface PricingCardData {
features: string[]
name: string
price: string
featureLabel?: string
}
interface PricingCardProps extends CardProps {
@@ -35,7 +36,7 @@ export const PricingCard = (props: PricingCardProps) => {
<Flex flexDir="column">
<VStack spacing={6}>
{icon}
<Heading size="md" fontWeight="extrabold">
<Heading size="md" fontWeight="extrabold" color={rest.borderColor}>
{name}
</Heading>
</VStack>
@@ -55,15 +56,19 @@ export const PricingCard = (props: PricingCardProps) => {
</Text>
)}
</Flex>
<List spacing="4" mb="8" maxW="30ch" mx="auto">
{data.featureLabel && (
<Text fontWeight="bold">{data.featureLabel}</Text>
)}
{features.map((feature, index) => (
<ListItem fontWeight="medium" key={index}>
<ListIcon
fontSize="xl"
as={CheckIcon}
as={CheckCircleIcon}
marginEnd={2}
color={accentColor}
fill="blue.200"
fill={rest.borderColor}
/>
{feature}
</ListItem>

View File

@@ -1,11 +1,11 @@
import { CheckIcon } from 'assets/icons/CheckIcon'
import { CheckCircleIcon } from 'assets/icons/CheckCircleIcon'
import { CloseIcon } from 'assets/icons/CloseIcon'
import { Td, Text } from '@chakra-ui/react'
import React, { ReactNode } from 'react'
export const Yes = (props: { children?: ReactNode }) => (
<Td display={props.children ? 'flex' : ''}>
<CheckIcon fill="#0042da" width="25px" />
<CheckCircleIcon fill="#0042da" width="25px" />
{props.children && (
<Text ml={1} fontSize="sm">
{props.children}

View File

@@ -64,7 +64,7 @@ const AboutPage = () => {
<br /> You can use the tool for free but your forms will contain a
"Made with Typebot" small badge that potentially gets people to know
about the product. If you want to remove it and also have access to
other advanced features, you have to subscribe for $30 per month.
other advanced features, you have to subscribe for $39 per month.
</Text>
<Text>
If you have any questions, feel free to reach out to me at{' '}

View File

@@ -14,15 +14,26 @@ import { Header } from 'components/common/Header/Header'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
import { BackgroundPolygons } from 'components/Homepage/Hero/BackgroundPolygons'
import { PlanComparisonTables } from 'components/PricingPage/PlanComparisonTables'
import { PricingCard } from 'components/PricingPage/PricingCard'
import { ActionButton } from 'components/PricingPage/PricingCard/ActionButton'
import { useEffect, useState } from 'react'
const Pricing = () => {
const [price, setPrice] = useState<'$30' | '25€' | ''>('')
const [price, setPrice] = useState<{
personalPro: '$39' | '39€' | ''
team: '$99' | '99€' | ''
}>({
personalPro: '',
team: '',
})
useEffect(() => {
setPrice(navigator.languages.find((l) => l.includes('fr')) ? '25€' : '$30')
setPrice(
navigator.languages.find((l) => l.includes('fr'))
? { personalPro: '39€', team: '99€' }
: { personalPro: '$39', team: '$99' }
)
}, [])
return (
@@ -49,12 +60,12 @@ const Pricing = () => {
px={[4, 0]}
mt={[20, 32]}
w="full"
maxW="900px"
maxW="1200px"
>
<PricingCard
data={{
price: 'Free',
name: 'Basic',
name: 'Personal',
features: [
'Unlimited typebots',
'Unlimited responses',
@@ -68,16 +79,16 @@ const Pricing = () => {
href="https://app.typebot.io/register"
_hover={{ textDecor: 'none' }}
>
<ActionButton variant="outline">Try now</ActionButton>
<ActionButton variant="outline">Get started</ActionButton>
</NextChakraLink>
}
/>
<PricingCard
data={{
price,
name: 'Pro',
price: price.personalPro,
name: 'Personal Pro',
featureLabel: 'Everything in Personal, plus:',
features: [
'Everything in Basic',
'Branding removed',
'View incomplete submissions',
'In-depth drop off analytics',
@@ -90,7 +101,7 @@ const Pricing = () => {
borderColor="orange.200"
button={
<NextChakraLink
href="https://app.typebot.io/register?subscribe=true"
href="https://app.typebot.io/register?subscribePlan=pro"
_hover={{ textDecor: 'none' }}
>
<ActionButton colorScheme="orange">
@@ -99,10 +110,38 @@ const Pricing = () => {
</NextChakraLink>
}
/>
<PricingCard
data={{
price: price.team,
name: 'Team',
featureLabel: 'Everything in Pro, plus:',
features: [
'Unlimited team members',
'Collaborative workspace',
'Custom roles',
],
}}
borderWidth="3px"
borderColor="purple.200"
button={
<NextChakraLink
href="https://app.typebot.io/register?subscribePlan=team"
_hover={{ textDecor: 'none' }}
>
<ActionButton>Subscribe now</ActionButton>
</NextChakraLink>
}
/>
</Stack>
<VStack w="full" maxW="900px" spacing="10" px="4">
<Heading textAlign="center">Frequently asked questions</Heading>
<Faq />
<VStack maxW="1200px" w="full" spacing={[12, 20]} px="4">
<Stack w="full" spacing={10} display={['none', 'flex']}>
<Heading>Compare plans & features</Heading>
<PlanComparisonTables prices={price} />
</Stack>
<VStack w="full" spacing="10">
<Heading textAlign="center">Frequently asked questions</Heading>
<Faq />
</VStack>
</VStack>
</VStack>
</Flex>
@@ -114,39 +153,6 @@ const Pricing = () => {
const Faq = () => {
return (
<Accordion w="full" allowToggle defaultIndex={0}>
<AccordionItem>
<Heading as="h2">
<AccordionButton py="6">
<Box flex="1" textAlign="left" fontSize="2xl">
How can I use Typebot with my team?
</Box>
<AccordionIcon />
</AccordionButton>
</Heading>
<AccordionPanel pb={4}>
Typebot allows you to invite your colleagues to collaborate on any of
your typebot. You can give him access as a reader or an editor. Your
colleague's account can be a free account. <br />
<br />
I'm working on a better solution for teams with shared workspaces and
other team-oriented features.
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<Heading as="h2">
<AccordionButton py="6">
<Box flex="1" textAlign="left" fontSize="2xl">
How many seats will I have with the Pro plan?
</Box>
<AccordionIcon />
</AccordionButton>
</Heading>
<AccordionPanel pb={4}>
You'll have only one seat. You can invite your colleagues to
collaborate on your typebots even though they have a free account.
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<Heading as="h2">
<AccordionButton py="6">