♻️ Migrate Accordion to Base UI
Some checks failed
Create Tag / create-tag (push) Has been cancelled
Deploy Partykit server / deploy (push) Has been cancelled

This commit is contained in:
Baptiste Arnaud 2025-10-10 16:06:41 +02:00
parent d4f4a3dbb5
commit ebd3ee6809
No known key found for this signature in database
31 changed files with 506 additions and 701 deletions

View File

@ -105,8 +105,8 @@ export const TableList = <T extends object>({
in={showDeleteIndex === itemIndex}
style={{
position: "absolute",
left: "-15px",
top: "-15px",
left: "-8px",
top: "-8px",
}}
unmountOnExit
>

View File

@ -1,13 +0,0 @@
import type { ReactNode } from "react";
export type Item = string | { label: string; value: string; icon?: ReactNode };
export const getItemLabel = (item: Item): string => {
if (typeof item === "string") return item;
return item.label;
};
export const getItemValue = (item: Item): string => {
if (typeof item === "string") return item;
return item.value;
};

View File

@ -12,7 +12,7 @@ import {
import { githubLight } from "@uiw/codemirror-theme-github";
import { tokyoNight } from "@uiw/codemirror-theme-tokyo-night";
import CodeMirror, { type ReactCodeMirrorRef } from "@uiw/react-codemirror";
import { useEffect, useRef, useState } from "react";
import { type CSSProperties, useEffect, useRef, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { useOpenControls } from "@/hooks/useOpenControls";
import { CopyButton } from "../CopyButton";
@ -120,17 +120,24 @@ export const CodeEditor = ({
return (
<div
style={
{
"--editor-min-height": minHeight,
"--editor-max-height": maxHeight,
} as CSSProperties
}
className={cn(
"group relative isolate border rounded-md [&_.cm-editor]:font-mono [&_.cm-editor]:text-sm",
"group relative isolate border rounded-md [&_.cm-editor]:font-mono [&_.cm-editor]:text-sm min-h-[var(--editor-min-height)]",
!withLineNumbers && "[&_.cm-gutters]:hidden",
"[&_.cm-editor]:rounded-md [&_.cm-editor]:outline-none has-[.cm-focused]:ring-2 transition-[box-shadow,border-color] has-[.cm-focused]:border-transparent ring-orange-7 [&_.cm-scroller]:rounded-md [&_.cm-scroller]:overflow-auto",
isReadOnly
? undefined
: "[&_.cm-editor]:max-h-[var(--editor-max-height)]",
className,
)}
>
<CodeMirror
data-testid="code-editor"
minHeight={isReadOnly ? undefined : minHeight}
maxHeight={isReadOnly ? undefined : maxHeight}
ref={codeEditor}
value={props.value ?? value}
onChange={handleChange}

View File

@ -1,17 +1,11 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
} from "@chakra-ui/react";
import { Stack } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import {
defaultFileInputOptions,
fileVisibilityOptions,
} from "@typebot.io/blocks-inputs/file/constants";
import type { FileInputBlock } from "@typebot.io/blocks-inputs/file/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { MoreInfoTooltip } from "@typebot.io/ui/components/MoreInfoTooltip";
import type { Variable } from "@typebot.io/variables/schemas";
@ -151,13 +145,12 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
/>
</Field.Root>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
{t("blocks.inputs.file.settings.labels")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} spacing={4}>
</Accordion.Trigger>
<Accordion.Panel>
<Field.Root>
<Field.Label>
{t("blocks.inputs.settings.placeholder.label")}
@ -221,9 +214,9 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
withVariableButton={false}
/>
)}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,14 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
FormControl,
FormLabel,
Stack,
Text,
} from "@chakra-ui/react";
import { FormControl, FormLabel, Stack, Text } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import {
defaultNumberInputButtonLabel,
@ -24,6 +14,7 @@ import {
type NumberInputBlock,
numberInputOptionsSchema,
} from "@typebot.io/blocks-inputs/number/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import type { Variable } from "@typebot.io/variables/schemas";
import { useEffect } from "react";
@ -127,15 +118,14 @@ export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
onValueChange={handleStepChange}
/>
</Field.Root>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
{t("blocks.inputs.number.settings.format.label")}
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</Accordion.Trigger>
<Accordion.Panel>
<BasicSelect
items={Object.values(NumberInputStyle).map((style) => ({
label: t(numberStyleTranslationKeys[style]),
@ -186,9 +176,9 @@ export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
onChange={handleLocaleChange}
/>
</FormControl>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
<Field.Root>
<Field.Label>
{t("blocks.inputs.settings.saveAnswer.label")}

View File

@ -1,13 +1,6 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
} from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import type { PaymentAddress } from "@typebot.io/blocks-inputs/payment/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { TextInput } from "@/components/inputs/TextInput";
type Props = {
@ -55,13 +48,12 @@ export const PaymentAddressSettings = ({ address, onAddressChange }: Props) => {
});
return (
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
{t("blocks.inputs.payment.settings.address.label")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel py={4} as={Stack} spacing="4">
</Accordion.Trigger>
<Accordion.Panel>
<TextInput
label={t("blocks.inputs.payment.settings.address.country.label")}
defaultValue={address?.country ?? ""}
@ -96,8 +88,8 @@ export const PaymentAddressSettings = ({ address, onAddressChange }: Props) => {
defaultValue={address?.postalCode ?? ""}
onChange={updatePostalCode}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
);
};

View File

@ -1,14 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
HStack,
Stack,
Text,
useDisclosure,
} from "@chakra-ui/react";
import { HStack, Stack, Text, useDisclosure } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import {
defaultPaymentInputOptions,
@ -18,6 +8,7 @@ import type {
PaymentAddress,
PaymentInputBlock,
} from "@typebot.io/blocks-inputs/payment/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { useMemo } from "react";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { TextInput } from "@/components/inputs/TextInput";
@ -174,13 +165,12 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
options?.labels?.success ?? defaultPaymentInputOptions.labels.success
}
/>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
{t("blocks.inputs.payment.settings.additionalInformation.label")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel py={4} as={Stack} spacing="6">
</Accordion.Trigger>
<Accordion.Panel>
<TextInput
label={t("blocks.inputs.settings.description.label")}
defaultValue={options?.additionalInformation?.description}
@ -217,9 +207,9 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
address={options?.additionalInformation?.address}
onAddressChange={updateAddress}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
<CreateStripeCredentialsDialog
isOpen={isOpen}

View File

@ -1,16 +1,10 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
} from "@chakra-ui/react";
import { Stack } from "@chakra-ui/react";
import {
chatwootTasks,
defaultChatwootOptions,
} from "@typebot.io/blocks-integrations/chatwoot/constants";
import type { ChatwootBlock } from "@typebot.io/blocks-integrations/chatwoot/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { TextInput } from "@/components/inputs/TextInput";
@ -54,13 +48,10 @@ export const ChatwootSettings = ({ options, onOptionsChange }: Props) => {
}
moreInfoTooltip="Can be found in Chatwoot under Settings > Inboxes > Settings > Configuration, in the code snippet."
/>
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Set user details
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="4">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Set user details</Accordion.Trigger>
<Accordion.Panel>
<TextInput
label="ID"
defaultValue={options?.user?.id}
@ -111,9 +102,9 @@ export const ChatwootSettings = ({ options, onOptionsChange }: Props) => {
});
}}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</>
)}
</Stack>

View File

@ -1,13 +1,6 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
Stack,
} from "@chakra-ui/react";
import { Box, Stack } from "@chakra-ui/react";
import type { GoogleAnalyticsBlock } from "@typebot.io/blocks-integrations/googleAnalytics/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { BasicNumberInput } from "@/components/inputs/BasicNumberInput";
import { TextInput } from "@/components/inputs/TextInput";
@ -59,17 +52,14 @@ export const GoogleAnalyticsSettings = ({
placeholder="Example: conversion"
onChange={updateAction}
/>
<Accordion allowToggle>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Advanced
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4} as={Stack} spacing="6">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
<Box flex="1" textAlign="left">
Advanced
</Box>
</Accordion.Trigger>
<Accordion.Panel>
<TextInput
label="Event category:"
defaultValue={options?.category}
@ -97,9 +87,9 @@ export const GoogleAnalyticsSettings = ({
placeholder="Example: AW-123456789"
onChange={updateSendTo}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,5 +1,7 @@
import { Stack } from "@chakra-ui/react";
import type { Cell } from "@typebot.io/blocks-integrations/googleSheets/schema";
import { Button } from "@typebot.io/ui/components/Button";
import { MoreVerticalIcon } from "@/components/icons";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { TextInput } from "@/components/inputs/TextInput";
import type { TableListItemProps } from "@/components/TableList";
@ -18,7 +20,21 @@ export const CellWithValueStack = ({
onItemChange({ ...item, value });
};
return (
<Stack p="4" rounded="md" flex="1" borderWidth="1px" w="full">
<Stack
p="4"
rounded="md"
flex="1"
borderWidth="1px"
w="full"
pos="relative"
>
<Button
size="icon"
variant="secondary"
className="absolute top-2 right-2"
>
<MoreVerticalIcon />
</Button>
<BasicSelect
value={item.column}
onChange={handleColumnSelect}

View File

@ -1,13 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
Text,
useDisclosure,
} from "@chakra-ui/react";
import { Stack, Text, useDisclosure } from "@chakra-ui/react";
import {
defaultGoogleSheetsOptions,
GoogleSheetsAction,
@ -23,6 +14,7 @@ import type {
GoogleSheetsUpdateRowOptionsV6,
} from "@typebot.io/blocks-integrations/googleSheets/schema";
import { isDefined } from "@typebot.io/lib/utils";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { useMemo } from "react";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { TableList } from "@/components/TableList";
@ -202,32 +194,30 @@ const ActionOptions = ({
);
case GoogleSheetsAction.UPDATE_ROW:
return (
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
Row(s) to update
</Text>
<AccordionIcon />
</AccordionButton>
</Accordion.Trigger>
<AccordionPanel pt="4">
<Accordion.Panel>
<RowsFilterTableList
columns={sheet?.columns ?? []}
filter={options.filter}
onFilterChange={handleFilterChange}
/>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
Cells to update
</Text>
<AccordionIcon />
</AccordionButton>
</Accordion.Trigger>
<AccordionPanel pt="4">
<Accordion.Panel>
<TableList<Cell>
initialItems={options.cellsToUpsert}
onItemsChange={handleUpsertColumnsChange}
@ -241,66 +231,57 @@ const ActionOptions = ({
/>
)}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
);
case GoogleSheetsAction.GET:
return (
<Accordion allowMultiple>
<Stack>
<AccordionItem>
<AccordionButton>
<Text w="full" textAlign="left">
Select row(s)
</Text>
<AccordionIcon />
</AccordionButton>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
Select row(s)
</Text>
</Accordion.Trigger>
<AccordionPanel pt="4" as={Stack}>
<BasicSelect
items={totalRowsToExtractOptions}
value={
options.totalRowsToExtract ??
defaultGoogleSheetsOptions.totalRowsToExtract
}
onChange={updateTotalRowsToExtract}
/>
<RowsFilterTableList
columns={sheet?.columns ?? []}
filter={options.filter}
onFilterChange={handleFilterChange}
/>
</AccordionPanel>
</AccordionItem>
<Accordion.Panel>
<BasicSelect
items={totalRowsToExtractOptions}
value={
options.totalRowsToExtract ??
defaultGoogleSheetsOptions.totalRowsToExtract
}
onChange={updateTotalRowsToExtract}
/>
<RowsFilterTableList
columns={sheet?.columns ?? []}
filter={options.filter}
onFilterChange={handleFilterChange}
/>
</Accordion.Panel>
</Accordion.Item>
<AccordionItem>
<AccordionButton>
<Text w="full" textAlign="left">
Columns to extract
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
<TableList<ExtractingCell>
initialItems={options.cellsToExtract}
onItemsChange={handleExtractingCellsChange}
addLabel="Add a value"
hasDefaultItem
>
{({ item, onItemChange }) => (
<CellWithVariableIdStack
item={item}
onItemChange={onItemChange}
columns={sheet?.columns ?? []}
/>
)}
</TableList>
</AccordionPanel>
</AccordionItem>
</Stack>
</Accordion>
<Accordion.Item>
<Accordion.Trigger>Columns to extract</Accordion.Trigger>
<Accordion.Panel>
<TableList<ExtractingCell>
initialItems={options.cellsToExtract}
onItemsChange={handleExtractingCellsChange}
addLabel="Add a value"
hasDefaultItem
>
{({ item, onItemChange }) => (
<CellWithVariableIdStack
item={item}
onItemChange={onItemChange}
columns={sheet?.columns ?? []}
/>
)}
</TableList>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
);
default:
return null;

View File

@ -1,13 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
HStack,
Stack,
Text,
} from "@chakra-ui/react";
import { HStack, Text } from "@chakra-ui/react";
import {
defaultHttpRequestAttributes,
defaultHttpRequestBlockOptions,
@ -22,6 +13,7 @@ import type {
ResponseVariableMapping,
VariableForTest,
} from "@typebot.io/blocks-integrations/httpRequest/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Button } from "@typebot.io/ui/components/Button";
import { Field } from "@typebot.io/ui/components/Field";
import { useMemo, useState } from "react";
@ -126,13 +118,10 @@ export const HttpRequestAdvancedConfigForm = ({
return (
<>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Advanced configuration
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4" as={Stack} spacing="3">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Advanced configuration</Accordion.Trigger>
<Accordion.Panel>
<SwitchWithLabel
label="Execute on client"
moreInfoContent="If enabled, the httpRequest will be executed on the client. It means it will be executed in the browser of your visitor. Make sure to enable CORS and do not expose sensitive data."
@ -151,13 +140,10 @@ export const HttpRequestAdvancedConfigForm = ({
items={Object.values(HttpMethod)}
/>
</HStack>
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Query params
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Query params</Accordion.Trigger>
<Accordion.Panel>
<TableList<KeyValue>
initialItems={httpRequest?.queryParams}
onItemsChange={updateQueryParams}
@ -165,14 +151,11 @@ export const HttpRequestAdvancedConfigForm = ({
>
{(props) => <QueryParamsInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Headers
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>Headers</Accordion.Trigger>
<Accordion.Panel>
<TableList<KeyValue>
initialItems={httpRequest?.headers}
onItemsChange={updateHeaders}
@ -180,14 +163,11 @@ export const HttpRequestAdvancedConfigForm = ({
>
{(props) => <HeadersInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Body
<AccordionIcon />
</AccordionButton>
<AccordionPanel py={4} as={Stack} spacing="6">
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>Body</Accordion.Trigger>
<Accordion.Panel>
<SwitchWithLabel
label="Custom body"
initialValue={isCustomBody}
@ -202,14 +182,11 @@ export const HttpRequestAdvancedConfigForm = ({
withLineNumbers={true}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Advanced parameters
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4" as={Stack}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>Advanced parameters</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<CredentialsDropdown
type="http proxy"
@ -234,14 +211,11 @@ export const HttpRequestAdvancedConfigForm = ({
withVariableButton={false}
/>
</Field.Root>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Variable values for test
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>Variable values for test</Accordion.Trigger>
<Accordion.Panel>
<TableList<VariableForTest>
initialItems={options?.variablesForTest}
onItemsChange={updateVariablesForTest}
@ -249,12 +223,12 @@ export const HttpRequestAdvancedConfigForm = ({
>
{(props) => <VariableForTestInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
{httpRequest?.url && (
<Button onClick={executeTestRequest} disabled={isTestResponseLoading}>
@ -267,13 +241,10 @@ export const HttpRequestAdvancedConfigForm = ({
{(testResponse ||
(options?.responseVariableMapping &&
options.responseVariableMapping.length > 0)) && (
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Save in variables
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Save in variables</Accordion.Trigger>
<Accordion.Panel>
<TableList<ResponseVariableMapping>
initialItems={options?.responseVariableMapping}
onItemsChange={updateResponseVariableMapping}
@ -281,9 +252,9 @@ export const HttpRequestAdvancedConfigForm = ({
>
{(props) => <ResponseMappingInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
)}
</>
);

View File

@ -1,13 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
Text,
useDisclosure,
} from "@chakra-ui/react";
import { Stack, useDisclosure } from "@chakra-ui/react";
import {
defaultOpenAIOptions,
openAITasks,
@ -18,6 +9,7 @@ import type {
CreateSpeechOpenAIOptions,
OpenAIBlock,
} from "@typebot.io/blocks-integrations/openai/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { TextInput } from "@/components/inputs/TextInput";
import { CredentialsDropdown } from "@/features/credentials/components/CredentialsDropdown";
@ -91,15 +83,10 @@ export const OpenAISettings = ({
)}
{options?.credentialsId && (
<>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton>
<Text w="full" textAlign="left">
Customize provider
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} spacing={4}>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Customize provider</Accordion.Trigger>
<Accordion.Panel>
<TextInput
label="Base URL"
defaultValue={baseUrl}
@ -112,9 +99,9 @@ export const OpenAISettings = ({
onChange={updateApiVersion}
/>
)}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
<BasicSelect
value={options.task}

View File

@ -1,13 +1,6 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
Text,
} from "@chakra-ui/react";
import { Stack, Text } from "@chakra-ui/react";
import type { ChatCompletionOpenAIOptions } from "@typebot.io/blocks-integrations/openai/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { BasicNumberInput } from "@/components/inputs/BasicNumberInput";
import { TableList } from "@/components/TableList";
@ -83,16 +76,15 @@ export const OpenAIChatCompletionSettings = ({
type="gpt"
onChange={updateModel}
/>
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
Messages
</Text>
<AccordionIcon />
</AccordionButton>
</Accordion.Trigger>
<AccordionPanel pt="4">
<Accordion.Panel>
<TableList
initialItems={options.messages}
onItemsChange={updateMessages}
@ -102,16 +94,15 @@ export const OpenAIChatCompletionSettings = ({
>
{(props) => <ChatCompletionMessageItem {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
Advanced settings
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</Accordion.Trigger>
<Accordion.Panel>
<Field.Root>
<Field.Label>Temperature</Field.Label>
<BasicNumberInput
@ -123,16 +114,15 @@ export const OpenAIChatCompletionSettings = ({
onValueChange={updateTemperature}
/>
</Field.Root>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>
<Text w="full" textAlign="left">
Save answer
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
</Accordion.Trigger>
<Accordion.Panel>
<TableList
initialItems={options.responseMapping}
onItemsChange={updateResponseMapping}
@ -141,9 +131,9 @@ export const OpenAIChatCompletionSettings = ({
>
{(props) => <ChatCompletionResponseItem {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</>
)}
</Stack>

View File

@ -1,9 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Flex,
HStack,
Stack,
@ -15,6 +10,7 @@ import { defaultSendEmailOptions } from "@typebot.io/blocks-integrations/sendEma
import type { SendEmailBlock } from "@typebot.io/blocks-integrations/sendEmail/schema";
import { env } from "@typebot.io/env";
import { isNotEmpty } from "@typebot.io/lib/utils";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { MoreInfoTooltip } from "@typebot.io/ui/components/MoreInfoTooltip";
import type { Variable } from "@typebot.io/variables/schemas";
@ -145,15 +141,10 @@ export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
defaultValue={options?.recipients?.join(", ")}
placeholder="email1@gmail.com, email2@gmail.com"
/>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton>
<HStack justifyContent="space-between" w="full">
<Text>Advanced</Text>
<AccordionIcon />
</HStack>
</AccordionButton>
<AccordionPanel as={Stack}>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Advanced</Accordion.Trigger>
<Accordion.Panel>
<TextInput
label="Reply to:"
onChange={handleReplyToChange}
@ -172,9 +163,9 @@ export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
defaultValue={options?.bcc?.join(", ") ?? ""}
placeholder="email1@gmail.com, email2@gmail.com"
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
<TextInput
label="Subject:"

View File

@ -1,13 +1,7 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
} from "@chakra-ui/react";
import { Stack } from "@chakra-ui/react";
import { defaultWaitOptions } from "@typebot.io/blocks-logic/wait/constants";
import type { WaitBlock } from "@typebot.io/blocks-logic/wait/schema";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { SwitchWithLabel } from "@/components/inputs/SwitchWithLabel";
import { TextInput } from "@/components/inputs/TextInput";
@ -32,13 +26,10 @@ export const WaitSettings = ({ options, onOptionsChange }: Props) => {
defaultValue={options?.secondsToWaitFor}
onChange={handleSecondsChange}
/>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Advanced
<AccordionIcon />
</AccordionButton>
<AccordionPanel py="4">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Advanced</Accordion.Trigger>
<Accordion.Panel>
<SwitchWithLabel
label="Pause the flow"
moreInfoContent="When enabled, the flow is paused until the client sends another message. This is automatic on the web bot."
@ -47,9 +38,9 @@ export const WaitSettings = ({ options, onOptionsChange }: Props) => {
}
onCheckChange={updateShouldPause}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,9 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
FormControl,
FormHelperText,
Input,
@ -23,6 +18,7 @@ import type { ResponseVariableMapping } from "@typebot.io/blocks-integrations/ht
import type { WebhookBlock } from "@typebot.io/blocks-logic/webhook/schema";
import { env } from "@typebot.io/env";
import { parseUnknownError } from "@typebot.io/lib/parseUnknownError";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Button } from "@typebot.io/ui/components/Button";
import usePartySocket from "partysocket/react";
import { useMemo, useState } from "react";
@ -156,13 +152,10 @@ export const WebhookSettings = ({
{(receivedData ||
(options?.responseVariableMapping &&
options.responseVariableMapping.length > 0)) && (
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Save in variables
<AccordionIcon />
</AccordionButton>
<AccordionPanel pt="4">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Save in variables</Accordion.Trigger>
<Accordion.Panel>
<TableList<ResponseVariableMapping>
initialItems={options?.responseVariableMapping}
onItemsChange={updateResponseVariableMapping}
@ -170,9 +163,9 @@ export const WebhookSettings = ({
>
{(props) => <ResponseMappingInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
)}
</Stack>
</TabPanel>

View File

@ -1,13 +1,7 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
} from "@chakra-ui/react";
import { Stack } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import type { InvalidReplyEvent } from "@typebot.io/events/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { MoreInfoTooltip } from "@typebot.io/ui/components/MoreInfoTooltip";
import type { Variable } from "@typebot.io/variables/schemas";
@ -42,13 +36,12 @@ export const InvalidReplyEventSettings = ({
return (
<Stack p="2" spacing={4}>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
{t("blocks.events.reply.settings.variableMappingAccordion.title")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} spacing={4}>
</Accordion.Trigger>
<Accordion.Panel>
<Field.Root>
<Field.Label>
{t("blocks.events.reply.settings.contentVariable.label")}
@ -82,9 +75,9 @@ export const InvalidReplyEventSettings = ({
onSelectVariable={updateInputNameVariableId}
/>
</Field.Root>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,13 +1,7 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
} from "@chakra-ui/react";
import { Stack } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import type { ReplyEvent } from "@typebot.io/events/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { MoreInfoTooltip } from "@typebot.io/ui/components/MoreInfoTooltip";
import type { Variable } from "@typebot.io/variables/schemas";
@ -42,13 +36,12 @@ export const ReplyEventSettings = ({
return (
<Stack p="2" spacing={4}>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
{t("blocks.events.reply.settings.variableMappingAccordion.title")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} spacing={4}>
</Accordion.Trigger>
<Accordion.Panel>
<Field.Root>
<Field.Label>
{t("blocks.events.reply.settings.contentVariable.label")}
@ -82,9 +75,9 @@ export const ReplyEventSettings = ({
onSelectVariable={updateInputNameVariableId}
/>
</Field.Root>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,15 +1,7 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Stack,
Text,
} from "@chakra-ui/react";
import { evaluateIsHidden } from "@typebot.io/forge/helpers/evaluateIsHidden";
import type { ForgedBlockDefinition } from "@typebot.io/forge-repository/definitions";
import type { ForgedBlock } from "@typebot.io/forge-repository/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import type { ZodLayoutMetadata } from "@typebot.io/zod";
import type { ReactNode } from "react";
import type { ZodTypeAny, z } from "zod";
@ -59,15 +51,10 @@ export const ZodObjectLayout = ({
return {
nodes: [
...nodes.nodes,
<Accordion allowToggle key={layout.accordion}>
<AccordionItem>
<AccordionButton>
<Text w="full" textAlign="left">
{layout.accordion}
</Text>
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} spacing={4}>
<Accordion.Root key={layout.accordion}>
<Accordion.Item>
<Accordion.Trigger>{layout.accordion}</Accordion.Trigger>
<Accordion.Panel>
{accordionKeys.map((accordionKey, idx) => (
<ZodFieldLayout
key={accordionKey + idx}
@ -81,9 +68,9 @@ export const ZodObjectLayout = ({
isInAccordion
/>
))}
</AccordionPanel>
</AccordionItem>
</Accordion>,
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>,
],
accordionsCreated: [
...nodes.accordionsCreated,

View File

@ -1,14 +1,8 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Flex,
HStack,
ListItem,
OrderedList,
Stack,
Text,
useDisclosure,
} from "@chakra-ui/react";
@ -17,6 +11,7 @@ import { LogicalOperator } from "@typebot.io/conditions/constants";
import type { Comparison } from "@typebot.io/conditions/schemas";
import { isDefined } from "@typebot.io/lib/utils";
import { defaultSessionExpiryTimeout } from "@typebot.io/settings/constants";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Dialog } from "@typebot.io/ui/components/Dialog";
import { Field } from "@typebot.io/ui/components/Field";
import { MoreInfoTooltip } from "@typebot.io/ui/components/MoreInfoTooltip";
@ -212,13 +207,10 @@ export const WhatsAppDeployDialog = ({
{typebot?.whatsAppCredentialsId && (
<>
<ListItem>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Configure integration
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} spacing="4" pt="4">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Configure integration</Accordion.Trigger>
<Accordion.Panel>
<Field.Root className="inline-flex flex-row items-center">
<Field.Label>
Session expire timeout
@ -270,9 +262,9 @@ export const WhatsAppDeployDialog = ({
{(props) => <WhatsAppComparisonItem {...props} />}
</TableList>
</SwitchWithRelatedSettings>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</ListItem>
<ListItem>

View File

@ -1,19 +1,11 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
HStack,
Stack,
Text,
} from "@chakra-ui/react";
import { HStack, Text } from "@chakra-ui/react";
import type {
BubbleProps,
BubbleTheme,
ButtonTheme,
PreviewMessageTheme,
} from "@typebot.io/js";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { ButtonThemeSettings } from "./ButtonThemeSettings";
import { PreviewMessageThemeSettings } from "./PreviewMessageThemeSettings";
@ -51,15 +43,10 @@ export const ThemeSettings = ({
};
return (
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton px="0">
<HStack flex="1">
<Text>Theme</Text>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack} pb={4} spacing={4} px="0">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Theme</Accordion.Trigger>
<Accordion.Panel>
<HStack justify="space-between">
<Text>Placement</Text>
<BasicSelect
@ -83,8 +70,8 @@ export const ThemeSettings = ({
onChange={updatePreviewMessageTheme}
/>
) : null}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
);
};

View File

@ -1,9 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
chakra,
HStack,
Spinner,
@ -14,6 +9,7 @@ import {
} from "@chakra-ui/react";
import { isDefined } from "@typebot.io/lib/utils";
import type { Log } from "@typebot.io/logs/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Dialog } from "@typebot.io/ui/components/Dialog";
import { useLogs } from "../hooks/useLogs";
@ -43,15 +39,9 @@ export const LogsDialog = ({ typebotId, resultId, onClose }: Props) => {
const LogCard = ({ log }: { log: Log }) => {
if (log.details)
return (
<Accordion allowToggle>
<AccordionItem style={{ borderBottomWidth: 0, borderWidth: 0 }}>
<AccordionButton
as={HStack}
p="4"
cursor="pointer"
justifyContent="space-between"
borderRadius="md"
>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
<HStack gap={3} alignItems="flex-start">
<StatusTag status={log.status} flexShrink={0} mt={0.5} />
<Stack>
@ -65,18 +55,10 @@ const LogCard = ({ log }: { log: Log }) => {
</Text>
</Stack>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel
as="pre"
overflow="auto"
borderWidth="1px"
borderRadius="md"
>
{log.details}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Trigger>
<Accordion.Panel>{log.details}</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
);
return (
<HStack p="4" gap={3} alignItems="flex-start">

View File

@ -1,9 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
FormControl,
FormLabel,
HStack,
@ -19,6 +14,7 @@ import {
rememberUserStorages,
} from "@typebot.io/settings/constants";
import type { Settings, SystemMessages } from "@typebot.io/settings/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { MoreInfoTooltip } from "@typebot.io/ui/components/MoreInfoTooltip";
import { BasicSelect } from "@/components/inputs/BasicSelect";
import { SwitchWithLabel } from "@/components/inputs/SwitchWithLabel";
@ -140,20 +136,19 @@ export const GeneralSettingsForm = ({
/>
</FormControl>
</SwitchWithRelatedSettings>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>
{t("settings.sideMenu.general.systemMessages")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</Accordion.Trigger>
<Accordion.Panel>
<SystemMessagesForm
systemMessages={generalSettings?.systemMessages}
onSystemMessagesChange={updateSystemMessages}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,21 +1,12 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Heading,
HStack,
Stack,
useColorModeValue,
} from "@chakra-ui/react";
import { Heading, Stack, useColorModeValue } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import type { Settings } from "@typebot.io/settings/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import {
ChatIcon,
CodeIcon,
LockedIcon,
MoreVerticalIcon,
MoreHorizontalIcon,
} from "@/components/icons";
import { useTypebot } from "@/features/editor/providers/TypebotProvider";
import { GeneralSettingsForm } from "./GeneralSettingsForm";
@ -62,67 +53,63 @@ export const SettingsSideMenu = () => {
rounded="xl"
bg={useColorModeValue("white", "gray.900")}
>
<Accordion allowMultiple borderBottomWidth={0} defaultIndex={[0]}>
<AccordionItem borderTopWidth={0}>
<AccordionButton py={4}>
<HStack flex="1" pl={2}>
<MoreVerticalIcon transform={"rotate(90deg)"} />
<Accordion.Root>
<Accordion.Item className="border-0">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<MoreHorizontalIcon />
<Heading fontSize="md">{t("settings.sideMenu.general")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<GeneralSettingsForm
generalSettings={typebot.settings.general}
onGeneralSettingsChange={handleGeneralSettingsChange}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton py={4}>
<HStack flex="1" pl={2}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item className="border-0 border-t-[1px]">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<ChatIcon />
<Heading fontSize="md">{t("settings.sideMenu.typing")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<TypingEmulationForm
typingEmulation={typebot.settings.typingEmulation}
onUpdate={updateTypingEmulation}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton py={4}>
<HStack flex="1" pl={2}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item className="border-0 border-t-[1px]">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<LockedIcon />
<Heading fontSize="md">{t("settings.sideMenu.security")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<SecurityForm
security={typebot.settings.security}
onUpdate={updateSecurity}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton py={4}>
<HStack flex="1" pl={2}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item className="border-0 border-t-[1px] last:rounded-b-none">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<CodeIcon />
<Heading fontSize="md">{t("settings.sideMenu.metadata")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<MetadataForm
workspaceId={typebot.workspaceId}
@ -132,9 +119,9 @@ export const SettingsSideMenu = () => {
onMetadataChange={handleMetadataChange}
/>
)}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,14 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Heading,
HStack,
Stack,
useColorModeValue,
} from "@chakra-ui/react";
import { Heading, Stack, useColorModeValue } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import { defaultSettings } from "@typebot.io/settings/constants";
import type {
@ -16,6 +6,7 @@ import type {
GeneralTheme,
ThemeTemplate,
} from "@typebot.io/theme/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { ChatIcon, CodeIcon, DropletIcon, TableIcon } from "@/components/icons";
import { useTypebot } from "@/features/editor/providers/TypebotProvider";
import { CustomCssSettings } from "./CustomCssSettings";
@ -76,17 +67,16 @@ export const ThemeSideMenu = () => {
rounded="xl"
bg={useColorModeValue("white", "gray.900")}
>
<Accordion allowToggle borderBottomWidth={0}>
<Accordion.Root>
{currentUserMode === "write" && (
<AccordionItem borderTopWidth={0}>
<AccordionButton py={4}>
<HStack flex="1" pl={2} spacing={3}>
<Accordion.Item className="border-0">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<TableIcon />
<Heading fontSize="md">{t("theme.sideMenu.template")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<ThemeTemplates
selectedTemplateId={templateId}
@ -96,18 +86,17 @@ export const ThemeSideMenu = () => {
onTemplateSelect={selectTemplate}
/>
)}
</AccordionPanel>
</AccordionItem>
</Accordion.Panel>
</Accordion.Item>
)}
<AccordionItem>
<AccordionButton py={4}>
<HStack flex="1" pl={2} spacing={3}>
<Accordion.Item className="border-0 border-t-[1px]">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<DropletIcon />
<Heading fontSize="md">{t("theme.sideMenu.global")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<GeneralSettings
key={templateId}
@ -120,17 +109,16 @@ export const ThemeSideMenu = () => {
onBrandingChange={updateBranding}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton py={4}>
<HStack flex="1" pl={2} spacing={3}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item className="border-0 border-t-[1px]">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<ChatIcon />
<Heading fontSize="md">{t("theme.sideMenu.chat")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<ChatThemeSettings
key={templateId}
@ -141,17 +129,16 @@ export const ThemeSideMenu = () => {
onChatThemeChange={updateChatTheme}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem _last={{ borderBottomWidth: 0 }}>
<AccordionButton py={4}>
<HStack flex="1" pl={2} spacing={3}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item className="border-0 border-t-[1px] last:rounded-b-none">
<Accordion.Trigger className="py-5">
<div className="flex items-center gap-3 pl-2">
<CodeIcon />
<Heading fontSize="md">{t("theme.sideMenu.customCSS")}</Heading>
</HStack>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
</div>
</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<CustomCssSettings
key={templateId}
@ -159,9 +146,9 @@ export const ThemeSideMenu = () => {
onCustomCssChange={updateCustomCss}
/>
)}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,14 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
FormLabel,
HStack,
Stack,
Switch,
} from "@chakra-ui/react";
import { FormLabel, HStack, Stack, Switch } from "@chakra-ui/react";
import { useTranslate } from "@tolgee/react";
import {
borderRoundness,
@ -20,6 +10,7 @@ import type {
ContainerTheme,
InputTheme,
} from "@typebot.io/theme/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { Field } from "@typebot.io/ui/components/Field";
import { BasicNumberInput } from "@/components/inputs/BasicNumberInput";
import { BasicSelect } from "@/components/inputs/BasicSelect";
@ -124,26 +115,20 @@ export const ContainerThemeForm = <
</HStack>
)}
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Border
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Border</Accordion.Trigger>
<Accordion.Panel>
<BorderThemeForm
border={theme?.border}
defaultBorder={defaultTheme.border}
onBorderChange={updateBorder}
/>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Advanced
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack}>
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>Advanced</Accordion.Trigger>
<Accordion.Panel>
{backgroundColor !== "transparent" && (
<>
<Field.Root className="flex-row">
@ -183,9 +168,9 @@ export const ContainerThemeForm = <
/>
</HStack>
</HStack>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -1,9 +1,4 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Flex,
FormLabel,
Stack,
@ -21,6 +16,7 @@ import type {
ProgressBar,
Theme,
} from "@typebot.io/theme/schemas";
import { Accordion } from "@typebot.io/ui/components/Accordion";
import { RadioButtons } from "@/components/inputs/RadioButtons";
import { ChangePlanDialog } from "@/features/billing/components/ChangePlanDialog";
import { LockTag } from "@/features/billing/components/LockTag";
@ -122,13 +118,10 @@ export const GeneralSettings = ({
onChange={updateBranding}
/>
</Flex>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton justifyContent="space-between">
Progress Bar
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
<Accordion.Root>
<Accordion.Item>
<Accordion.Trigger>Progress Bar</Accordion.Trigger>
<Accordion.Panel>
{typebot && (
<ProgressBarForm
progressBar={generalTheme?.progressBar}
@ -136,35 +129,33 @@ export const GeneralSettings = ({
typebotVersion={typebot.version}
/>
)}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>
{t("theme.sideMenu.global.font")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel as={Stack}>
</Accordion.Trigger>
<Accordion.Panel>
<RadioButtons
options={fontTypes}
defaultValue={fontType}
onSelect={updateFontType}
/>
<FontForm font={generalTheme?.font} onFontChange={updateFont} />
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<AccordionButton justifyContent="space-between">
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item>
<Accordion.Trigger>
{t("theme.sideMenu.global.background")}
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</Accordion.Trigger>
<Accordion.Panel>
<BackgroundSelector
background={generalTheme?.background}
onBackgroundChange={handleBackgroundChange}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
</Stack>
);
};

View File

@ -0,0 +1,77 @@
import { Accordion as AccordionPrimitive } from "@base-ui-components/react/accordion";
import { ArrowDown01Icon } from "../icons/ArrowDown01Icon";
import { cn } from "../lib/cn";
function Root({ className, ...props }: AccordionPrimitive.Root.Props) {
return (
<AccordionPrimitive.Root
data-slot="accordion"
className={cn("w-full -space-y-px", className)}
{...props}
/>
);
}
function Item({ className, ...props }: AccordionPrimitive.Item.Props) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn(
"border-b bg-white has-focus-visible:border-orange-9 has-focus-visible:ring-orange-9/50 relative border outline-none first:rounded-t-md last:rounded-b-md last:border-b has-focus-visible:ring-[3px]",
className,
)}
{...props}
/>
);
}
function Trigger({
className,
children,
...props
}: AccordionPrimitive.Trigger.Props) {
return (
<AccordionPrimitive.Header className="flex font-body font-normal">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"focus-visible:ring-orange-9/50 flex flex-1 items-center justify-between gap-4 rounded-md text-left text-sm font-semibold transition-all outline-none disabled:pointer-events-none disabled:opacity-50 [&[data-panel-open]>svg]:rotate-180 text-[15px] leading-6 hover:no-underline focus-visible:ring-0 px-4 py-3",
className,
)}
{...props}
>
{children}
<ArrowDown01Icon
className="pointer-events-none shrink-0 opacity-60 transition-transform"
aria-hidden="true"
/>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
}
function Panel({
className,
children,
style,
...props
}: AccordionPrimitive.Panel.Props) {
return (
<AccordionPrimitive.Panel
data-slot="accordion-content"
className="h-[var(--accordion-panel-height)] transition-[height] data-[ending-style]:h-0 data-[starting-style]:h-0 overflow-y-clip"
{...props}
>
<div className={cn("py-2 pb-4 px-4 gap-2 flex flex-col", className)}>
{children}
</div>
</AccordionPrimitive.Panel>
);
}
export const Accordion = {
Root,
Item,
Trigger,
Panel,
};

View File

@ -5,7 +5,7 @@ import { cva, type VariantProps } from "../lib/cva";
export const inputVariants = cva(
`
bg-transparent flex relative w-full overflow-visible rounded-md border transition-[box-shadow,border-color] border-gray-6 hover:border-gray-7
bg-transparent flex relative w-full overflow-visible rounded-md border transition-[box-shadow,border-color] border-gray-6 hover:border-gray-7 focus:z-10
focus:outline-none focus:ring-orange-8 focus:ring-2 focus:border-transparent
disabled:cursor-not-allowed disabled:opacity-50
placeholder:text-muted-foreground

View File

@ -1,17 +1,11 @@
import { Toast as ToastPrimitive } from "@base-ui-components/react/toast";
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
} from "@chakra-ui/react";
import { z } from "@typebot.io/zod";
import { Cancel01Icon } from "../icons/Cancel01Icon";
import { CheckmarkSquare02Icon } from "../icons/CheckmarkSquare02Icon";
import { InformationSquareIcon } from "../icons/InformationSquareIcon";
import { TriangleAlertIcon } from "../icons/TriangleAlertIcon";
import { cn } from "../lib/cn";
import { Accordion } from "./Accordion";
import { Button, buttonVariants } from "./Button";
const List = ({
@ -85,25 +79,20 @@ const List = ({
</div>
</div>
{toast.data.details && (
<Accordion allowToggle>
<AccordionItem onPointerDown={(e) => e.stopPropagation()}>
<AccordionButton
justifyContent="space-between"
fontSize="sm"
py="1"
>
<Accordion.Root>
<Accordion.Item onPointerDown={(e) => e.stopPropagation()}>
<Accordion.Trigger className="font-sm py-1">
Details
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
</Accordion.Trigger>
<Accordion.Panel>
<CodeEditor
isReadOnly
value={toast.data.details.content}
lang={toast.data.details.lang}
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Accordion.Panel>
</Accordion.Item>
</Accordion.Root>
)}
</div>