{"id":26341019,"url":"https://github.com/frontify/typeform-block-tutorial","last_synced_at":"2025-03-16T04:28:32.181Z","repository":{"id":187985399,"uuid":"611133625","full_name":"Frontify/typeform-block-tutorial","owner":"Frontify","description":"This is the repository for the Typeform block tutorial.","archived":false,"fork":false,"pushed_at":"2023-04-06T11:54:09.000Z","size":159,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2023-08-13T05:36:28.878Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Frontify.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-03-08T07:23:09.000Z","updated_at":"2023-08-13T05:36:35.853Z","dependencies_parsed_at":"2023-08-13T05:49:14.989Z","dependency_job_id":null,"html_url":"https://github.com/Frontify/typeform-block-tutorial","commit_stats":null,"previous_names":["frontify/typeform-block-tutorial"],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frontify%2Ftypeform-block-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frontify%2Ftypeform-block-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frontify%2Ftypeform-block-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Frontify%2Ftypeform-block-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Frontify","download_url":"https://codeload.github.com/Frontify/typeform-block-tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243826824,"owners_count":20354220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-16T04:28:31.602Z","updated_at":"2025-03-16T04:28:32.163Z","avatar_url":"https://github.com/Frontify.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Building a Typeform Content Block\n\nWith Frontify's Brand SDK for Content Blocks, you can create your own Content Blocks for your Guidelines.\n\nIn this quick guide, you'll learn how to create a simple Typeform block that uses some of the Brand SDK's features.\n\n## Prerequisites\n\nBefore starting, you should check out the general [Content Block documentation](https://developer.frontify.com/d/XFPCrGNrXQQM/content-blocks) to get a rough overview of how Content Blocks work. If you're at it, check out the [Typeform React Embed Library](https://developer.typeform.com/embed/react/) as well 🙂\n\nYou need to have Node \u003e=16 installed, and a basic understanding of TypeScript would be good, too.\n\n## Frontify-CLI\n\nOne of the main features of the Brand SDK is the `frontify-cli`. You can install it globally if you want:\n\n```sh\n$ npm install -g @frontify/frontify-cli\n```\n\nAnother (and preferred) way to use the tool is, to use `npx @frontify/frontify-cli@latest` instead. Just replace the `frontify-cli` calls with `npx @frontify/frontify-cli`. Going forward, in this tutorial we'll be using the `npx` approach.\n\n## Scaffold a new Content Block\n\nOnce the `frontify-cli` tool is installed, we can use it to scaffold our Typeform block:\n\n```sh\n$ npx @frontify/frontify-cli@latest block create typeform-block\n```\n\nIf everything worked out, you should have a new folder looking something like this:\n\n```\n.\n├── README.md\n├── manifest.json\n├── package-lock.json\n├── package.json\n├── src\n│   ├── Block.tsx\n│   ├── cssModule.d.ts\n│   ├── index.ts\n│   ├── settings.ts\n│   └── style.module.css\n└── tsconfig.json\n```\n\nTo finish the installation, we need to install all the npm packages:\n\n```sh\n$ cd typeform-block\n$ npm ci\n```\n\n## Test our new block\n\nLet's test-run our new Content Block to see if everything is working as expected.\n\n### Local Block Development block\n\nFor our block to be displayed in our Guidelines, we need to add a \"Local Block Development\" block:\n\nNote: If you can't find the \"Local Block Development\" block, you probably don't have access to the Brand SDK and Marketplace yet. Please reach out to use on [Slack](https://join.slack.com/t/frontify-friends/shared_invite/zt-1lhu6lump-s18oTGI4EhHt8BKWfBAN_A) so we can activate it for you.\n\n![Local Block Develoment block](https://cdn-assets-eu.frontify.com/s3/frontify-enterprise-files-eu/eyJwYXRoIjoid2VhcmVcL2FjY291bnRzXC82ZVwvNDAwMDM4OFwvcHJvamVjdHNcLzk4NFwvYXNzZXRzXC80NVwvMTQ5MDg0XC9kYTY1OWQzZWM1NTc0ZjVmMTMzMzczMmQ3MzhiMmNmMS0xNjQ5MDcwMTgyLnBuZyJ9:weare:Ou6SqL6rCEMH9YDjfVDpSjtOk8YL35-yyIBMLvDDhH4?width=1700\u0026height=1023)\n\nYou should now see something like this:\n\n![Websocket Port](https://cdn-assets-eu.frontify.com/s3/frontify-enterprise-files-eu/eyJwYXRoIjoid2VhcmVcL2FjY291bnRzXC82ZVwvNDAwMDM4OFwvcHJvamVjdHNcLzk4NFwvYXNzZXRzXC85NFwvMTQ5MDg1XC9lZDkwNWFiNzc5MDE3ZmJjYThiNzMyY2FjZDQyMzViMS0xNjQ5MDcwMTgyLnBuZyJ9:weare:3nq4mkUFw4RJ2M4cfTVwLGVHGEpmRNtSYesgHu20pDs?width=1700\u0026height=846)\n\nThe block itself doesn't need much configuration besides the WebSocket port, which you can leave at 5600.\n\n### Running the watch task\n\nIn our project, we can now run the serve task to connect the development environment with our Guidelines:\n\n```sh\n$ npm run serve\n```\n\nAssuming that this worked, you’ll get a notification that the task is listening on port 5600:\n\n```sh\n\u003e typeform-block@1.0.0 serve\n\u003e frontify-cli serve --entryPath src/index.ts\n\n[08:33:54] Starting the development server...\n  ➜  Local:   http://localhost:5600/\n. . .\n```\n\nAnd the Guidelines should now show the contents of our block:\n\n![The running block](https://cdn-assets-eu.frontify.com/s3/frontify-enterprise-files-eu/eyJwYXRoIjoid2VhcmVcL2FjY291bnRzXC82ZVwvNDAwMDM4OFwvcHJvamVjdHNcLzk4NFwvYXNzZXRzXC9kYVwvMTQ5MDkwXC9lMGUwZTBjZWFmMzQ1OTViNDAzMTYxNTI4ZGJiNTQwOC0xNjQ5MDcxNTEyLnBuZyJ9:weare:dT_LngpJXHfyMGrTrK0EOyaLAQE8-rDqfJU1AvjdBA0?width=1700\u0026height=677)\n\nIf you don't see the violet message, try refreshing the page.\n\n🎉 Cool, we're now ready to start working on our Typeform block.\n\n## Adding the Typeform Library\n\nTypeform offers multiple ways to embed their forms in our projects. But since the Content Blocks use React, we're going to use the Typeform React Embed Library:\n\n```sh\n$ npm install @typeform/embed-react --save\n```\n\n## Preparing the `Block.tsx` file\n\nNow that we have everything ready for our Typeform block, we need to set up the part of our block that gets rendered in the Guidelines. For this, we modify the `Block.tsx` file in the `src/` directory:\n\n```tsx\nimport { FC } from 'react';\nimport { PopupButton, SliderButton, Widget } from '@typeform/embed-react';\nimport { useBlockSettings, useEditorState } from '@frontify/app-bridge';\nimport type { BlockProps } from '@frontify/guideline-blocks-settings';\nimport styles from './style.module.css';\nimport type { Settings } from './types';\n\nconst Placeholder: FC = () =\u003e (\n    \u003cdiv\u003e\n        \u003cp className={styles.placeholder}\u003ePlease enter a Typeform form id in the block settings.\u003c/p\u003e\n    \u003c/div\u003e\n);\n\nexport const TypeformBlock: FC\u003cBlockProps\u003e = ({ appBridge }) =\u003e {\n    const isEditing = useEditorState(appBridge);\n    const [blockSettings] = useBlockSettings\u003cSettings\u003e(appBridge);\n\n    if (!blockSettings.formId) {\n        return \u003cPlaceholder /\u003e;\n    }\n\n    const renderEmbed = () =\u003e {\n        switch (blockSettings.embedStyle) {\n            case 'embed':\n                return (\n                    \u003cWidget\n                        style={{\n                            height: blockSettings.isHeightCustom\n                                ? blockSettings.heightCustom\n                                : blockSettings.heightSimple,\n                        }}\n                        id={blockSettings.formId}\n                        enableSandbox={isEditing}\n                        hideHeaders={!blockSettings.header}\n                        hideFooter={!blockSettings.footer}\n                        opacity={blockSettings.transparent ? 0 : 100}\n                    /\u003e\n                );\n\n            case 'popup':\n                return (\n                    \u003cPopupButton\n                        size={100}\n                        opacity={100}\n                        className=\"a-button-primary\"\n                        id={blockSettings.formId}\n                        enableSandbox={isEditing}\n                        hideHeaders={!blockSettings.header}\n                        hideFooter={!blockSettings.footer}\n                    \u003e\n                        {blockSettings.buttonText}\n                    \u003c/PopupButton\u003e\n                );\n\n            case 'sidePanel':\n                return (\n                    \u003cSliderButton\n                        className=\"a-button-primary\"\n                        id={blockSettings.formId}\n                        enableSandbox={isEditing}\n                        hideHeaders={!blockSettings.header}\n                        hideFooter={!blockSettings.footer}\n                    \u003e\n                        {blockSettings.buttonText}\n                    \u003c/SliderButton\u003e\n                );\n\n            default:\n                return \u003cPlaceholder /\u003e;\n        }\n    };\n\n    return \u003cdiv className={styles.container}\u003e{renderEmbed()}\u003c/div\u003e;\n};\n\n```\n\nLet’s talk about the contents of this file. First, we import all the necessary bindings we need for the presentational part of the block:\n\n```ts\nimport { FC } from 'react';\nimport { PopupButton, SliderButton, Widget } from '@typeform/embed-react';\nimport { useBlockSettings, useEditorState } from '@frontify/app-bridge';\nimport type { BlockProps } from '@frontify/guideline-blocks-settings';\nimport type { Settings } from './types';\nimport styles from './style.module.css';\n```\n\nFirst, we import the `FC` function from React to export a function component. We'll be using the `PopupButton`, `SliderButton`, and`Widget` components from the Typekit library. Besides that, we need to include the `useBlockSettings` hook to access the settings sidebar and the `useEditorState` hook to know if we're in edit state. Further, we need the `BlockProps` and `Settings` types for our function, and lastly, we import some CSS. Let's create that file right now, in the `src/` directory:\n\n```css\n.placeholder {\n    color: #ddd;\n}\n\n.container {\n    overflow: hidden;\n}\n```\n\nNext, we define some types we’re going to need for the block:\n\n```ts\nexport enum BlockHeight {\n    Small = '200px',\n    Medium = '400px',\n    Large = '800px',\n}\n\nexport type Settings = {\n    embedStyle: string;\n    formId: string;\n    isHeightCustom: boolean;\n    heightCustom: string;\n    heightSimple: string;\n    buttonText: string;\n    header: boolean;\n    footer: boolean;\n    transparent: boolean;\n};\n```\n\nThis is not strictly necessary, but since we're using TypeScript, it makes sense to have everything properly typed.\n\nBecause we have an initial state, we need to prepare a React element to render in those cases:\n\n```ts\nconst Placeholder: FC = () =\u003e (\n    \u003cdiv\u003e\n        \u003cp className={styles.placeholder}\u003ePlease enter a Typeform form id in the block settings.\u003c/p\u003e\n    \u003c/div\u003e\n);\n```\n\nNow we’re getting to the exciting part, the main component:\n\n```ts\nexport const TypeformBlock: FC\u003cBlockProps\u003e = ({ appBridge }) =\u003e {\n    const isEditing = useEditorState(appBridge);\n    const [blockSettings] = useBlockSettings\u003cSettings\u003e(appBridge);\n    . . .\n```\n\nHere, we're defining the block itself that we're going to export. We're using the `useEditorState()` and `useBlockSettings` hooks, which we'll be using to handle the edit-state of the block and to pull in the settings for the block itself.\n\n```ts\nif (!blockSettings.formId) {\n    return \u003cPlaceholder /\u003e;\n}\n```\n\nIn case we haven't set a `formId` in the settings, we want to render the `\u003cPlaceholder /\u003e` component defined before in the file. Keep in mind that we haven't set up any settings yet. So the `formId` will always be undefined.\n\nFinally, we render the actual Typeform components, depending on what has been set up through the settings:\n\n```ts\nconst renderEmbed = () =\u003e {\n    switch (blockSettings.embedStyle) {\n        case 'embed':\n            return (\n                \u003cWidget\n                    style={{\n                        height: blockSettings.isHeightCustom\n                            ? blockSettings.heightCustom\n                            : blockSettings.heightSimple,\n                    }}\n                    id={blockSettings.formId}\n                    enableSandbox={isEditing}\n                    hideHeaders={!blockSettings.header}\n                    hideFooter={!blockSettings.footer}\n                    opacity={blockSettings.transparent ? 0 : 100}\n                /\u003e\n            );\n\n        case 'popup':\n            return (\n                \u003cPopupButton\n                    size={100}\n                    opacity={100}\n                    className=\"a-button-primary\"\n                    id={blockSettings.formId}\n                    enableSandbox={isEditing}\n                    hideHeaders={!blockSettings.header}\n                    hideFooter={!blockSettings.footer}\n                \u003e\n                    {blockSettings.buttonText}\n                \u003c/PopupButton\u003e\n            );\n\n        case 'sidePanel':\n            return (\n                \u003cSliderButton\n                    className=\"a-button-primary\"\n                    id={blockSettings.formId}\n                    enableSandbox={isEditing}\n                    hideHeaders={!blockSettings.header}\n                    hideFooter={!blockSettings.footer}\n                \u003e\n                    {blockSettings.buttonText}\n                \u003c/SliderButton\u003e\n            );\n\n        default:\n            return \u003cPlaceholder /\u003e;\n    }\n};\n\nreturn \u003cdiv className={styles.container}\u003e{renderEmbed()}\u003c/div\u003e;\n```\n\nThe different components are pretty self-explanatory. We populate the different properties through the `blockSettings` object that we instantiated at the beginning of our component. Here's where we use the `isEditing` variable again to set the `enableSandbox` property on the Typeform components (to disable tracking while we're editing the block).\n\nIf the user has not set up the block yet, we default to the `\u003cPlaceholder /\u003e` element.\n\nNow that we set up the presentational part of the block we can run the `npm run serve` command again and should see the before mentioned placeholder.\n\n🎉 Nice, we're done with the presentational part of the block. Now on to the settings!\n\n## The `settings.ts` file\n\nLet's do the same thing we did with the `index.ts` file for the `settings.ts` file:\n\n```ts\nimport { BlockHeight } from './types';\nimport {\n    DropdownSize,\n    IconEnum,\n    appendUnit,\n    defineSettings,\n    numericalOrPixelRule,\n} from '@frontify/guideline-blocks-settings';\n\nexport const HEIGHT_DEFAULT_VALUE = BlockHeight.Small;\n\nexport const settings = defineSettings({\n    main: [\n        {\n            id: 'embedStyle',\n            type: 'dropdown',\n            label: 'Embed Type',\n            defaultValue: 'embed',\n            size: DropdownSize.Large,\n            choices: [\n                {\n                    value: 'embed',\n                    icon: IconEnum.MarkArea,\n                    label: 'Embed',\n                },\n                {\n                    value: 'popup',\n                    icon: IconEnum.TextBoxStack,\n                    label: 'Popup',\n                },\n                {\n                    value: 'sidePanel',\n                    icon: IconEnum.SidebarRight,\n                    label: 'Side Panel',\n                },\n            ],\n        },\n    ],\n    content: [\n        {\n            id: 'formId',\n            type: 'input',\n            label: 'Typeform Form ID',\n            info: 'You can find \u003cform-id\u003e from the public URL of your form: https://form.typeform.com/to/\u003cform-id\u003e',\n        },\n        {\n            id: 'buttonText',\n            label: 'Button Label',\n            type: 'input',\n            placeholder: 'Open Form',\n            defaultValue: 'Open Form',\n            show: (bundle) =\u003e\n                bundle.getBlock('embedStyle')?.value === 'popup' ||\n                bundle.getBlock('embedStyle')?.value === 'sidePanel',\n        },\n    ],\n    layout: [\n        {\n            id: 'header',\n            type: 'switch',\n            label: 'Header',\n            info: 'Controls the header that appears when you have a question group, or a long question',\n            defaultValue: false,\n        },\n        {\n            id: 'footer',\n            type: 'switch',\n            label: 'Footer',\n            info: 'Controls the visiblity of the form progress bar and navigation buttons',\n            defaultValue: true,\n        },\n        {\n            id: 'position',\n            type: 'slider',\n            label: 'Slider position',\n            defaultValue: 'right',\n            choices: [\n                {\n                    value: 'left',\n                    label: 'Left',\n                },\n                {\n                    value: 'right',\n                    label: 'Right',\n                },\n            ],\n            show: (bundle) =\u003e bundle.getBlock('embedStyle')?.value === 'sidePanel',\n        },\n        {\n            id: 'isHeightCustom',\n            type: 'switch',\n            label: 'Block Height',\n            switchLabel: 'Custom',\n            defaultValue: false,\n            show: (bundle) =\u003e bundle.getBlock('embedStyle')?.value === 'embed',\n            info: 'Determines the block height.',\n            on: [\n                {\n                    id: 'heightCustom',\n                    type: 'input',\n                    placeholder: '100px',\n                    rules: [numericalOrPixelRule],\n                    onChange: (bundle) =\u003e appendUnit(bundle, 'heightCustom'),\n                },\n            ],\n            off: [\n                {\n                    id: 'heightSimple',\n                    type: 'slider',\n                    defaultValue: HEIGHT_DEFAULT_VALUE,\n                    choices: [\n                        {\n                            value: BlockHeight.Small,\n                            label: 'S',\n                        },\n                        {\n                            value: BlockHeight.Medium,\n                            label: 'M',\n                        },\n                        {\n                            value: BlockHeight.Large,\n                            label: 'L',\n                        },\n                    ],\n                },\n            ],\n        },\n    ],\n    style: [\n        {\n            id: 'transparent',\n            label: 'Transparent Background',\n            info: 'Enable or disable the background of the form',\n            type: 'switch',\n            show: (bundle) =\u003e bundle.getBlock('embedStyle')?.value === 'embed',\n            defaultValue: false,\n        },\n    ],\n});\n```\n\nLike with the `Block.tsx` file, we’re importing all the necessary bindings:\n\n```ts\nimport { BlockHeight } from './types';\nimport {\n    DropdownSize,\n    IconEnum,\n    appendUnit,\n    defineSettings,\n    numericalOrPixelRule,\n} from '@frontify/guideline-blocks-settings';\n```\n\nWe need the types for the `BlockHeight` and a couple of helpers and enums from the `@frontify/guideline-blocks-settings` package.\n\nThe settings are split up in several different sections, which mirror the sections we have available in the Guidelines:\n\n```ts\nexport const settings = defineSettings({\n    main: [. . .],\n    content: [. . .],\n    layout: [. . .],\n    style: [. . .]\n});\n```\n\nFor more instructions on how to use the different sections and for what use-cases they might fit, check out the in-depth [documentation](https://developer.frontify.com/d/XFPCrGNrXQQM/content-blocks#/details-concepts-1/block-settings-1).\n\nIn our case, we use the `main` section for the way we’re going to display the Typeform component:\n\n```ts\nmain: [\n    {\n        id: 'embedStyle',\n        type: 'dropdown',\n        label: 'Embed Type',\n        defaultValue: 'embed',\n        size: DropdownSize.Large,\n        choices: [\n            {\n                value: 'embed',\n                icon: IconEnum.MarkArea,\n                label: 'Embed',\n            },\n            {\n                value: 'popup',\n                icon: IconEnum.TextBoxStack,\n                label: 'Popup',\n            },\n            {\n                value: 'sidePanel',\n                icon: IconEnum.SidebarRight,\n                label: 'Side Panel',\n            },\n        ],\n    },\n],\n```\n\nFor `size` and `icon`, we're using the imported enums, so we don't have to worry if they change in the future.\n\nThe `content` section is pretty basic, except for the `show` property on the second item:\n\n```ts\ncontent: [\n    {\n        id: 'formId',\n        type: 'input',\n        label: 'Typeform Form ID',\n        info: 'You can find \u003cform-id\u003e from the public URL of your form: https://form.typeform.com/to/\u003cform-id\u003e',\n    },\n    {\n        id: 'buttonText',\n        label: 'Button Label',\n        type: 'input',\n        placeholder: 'Open Form',\n        defaultValue: 'Open Form',\n        show: (bundle) =\u003e\n            bundle.getBlock('embedStyle')?.value === 'popup' ||\n            bundle.getBlock('embedStyle')?.value === 'sidePanel',\n    },\n],\n```\n\nThe `show` property determines if a setting item will be displayed. In this case, we'll only display the Button Label setting if the user chose the `popup` or the `sidePanel` version of the Typeform integration in the `main` section.\n\nThe `layout` section is a little bit more complex because it contains a switch setting:\n\n```ts\nlayout: [\n    {\n        id: 'header',\n        type: 'switch',\n        label: 'Header',\n        info: 'Controls the header that appears when you have a question group, or a long question',\n        defaultValue: false,\n    },\n    {\n        id: 'footer',\n        type: 'switch',\n        label: 'Footer',\n        info: 'Controls the visiblity of the form progress bar and navigation buttons',\n        defaultValue: true,\n    },\n    {\n        id: 'position',\n        type: 'slider',\n        label: 'Slider position',\n        defaultValue: 'right',\n        choices: [\n            {\n                value: 'left',\n                label: 'Left',\n            },\n            {\n                value: 'right',\n                label: 'Right',\n            },\n        ],\n        show: (bundle) =\u003e bundle.getBlock('embedStyle')?.value === 'sidePanel',\n    },\n    {\n        id: 'isHeightCustom',\n        type: 'switch',\n        label: 'Block Height',\n        switchLabel: 'Custom',\n        defaultValue: false,\n        show: (bundle) =\u003e bundle.getBlock('embedStyle')?.value === 'embed',\n        info: 'Determines the block height.',\n        on: [\n            {\n                id: 'heightCustom',\n                type: 'input',\n                placeholder: '100px',\n                rules: [numericalOrPixelRule],\n                onChange: (bundle) =\u003e appendUnit(bundle, 'heightCustom'),\n            },\n        ],\n        off: [\n            {\n                id: 'heightSimple',\n                type: 'slider',\n                defaultValue: HEIGHT_DEFAULT_VALUE,\n                choices: [\n                    {\n                        value: BlockHeight.Small,\n                        label: 'S',\n                    },\n                    {\n                        value: BlockHeight.Medium,\n                        label: 'M',\n                    },\n                    {\n                        value: BlockHeight.Large,\n                        label: 'L',\n                    },\n                ],\n            },\n        ],\n    },\n],\n```\n\nIf you have a look at `isHeightCustom`, you'll see that we use the `on` and `off` properties. You can think of them as nested settings that will be displayed depending on the state of the `switch` setting. The [documentation](https://developer.frontify.com/d/XFPCrGNrXQQM/content-blocks#/details-concepts-1/block-settings-1) explains that behavior pretty well.\n\nThe last setting is the `style` part:\n\n```ts\nstyle: [\n    {\n        id: 'transparent',\n        label: 'Transparent Background',\n        info: 'Enable or disable the background of the form',\n        type: 'switch',\n        show: (bundle) =\u003e bundle.getBlock('embedStyle')?.value === 'embed',\n        defaultValue: false,\n    },\n],\n```\n\nIt again contains a `show` property to determine if we want to show the setting (in this case only if the `embed` style was chosen).\n\n## The `index.ts` file\nThere is one important file left that we haven't talked about: the `index.ts` file. You can think of the `index.ts` file as the cooridnatior that brings everything together and let's the `frontify-cli` know how to actually build our Content Block:\n\n```ts\nimport { defineBlock } from '@frontify/guideline-blocks-settings';\n\nimport { TypeformBlock } from './Block';\nimport { settings } from './settings';\n\nexport default defineBlock({\n    block: TypeformBlock,\n    settings,\n});\n```\n\nBesides importing the `defineBlock` function from the `@frontify/guideline-blocks-settings`, we as well need the actual block and settings. We're importing those and pass them to the `defineBlock` function. Now the `frontify-cli` know where to find the relevant files.\n\nAnd that's basically it. Let's run `npm run serve` again and open the settings for our block. If you use `GKcYunMz` as the Form ID, you should see the Typeform form getting loaded in the Guide Lines:\n\n![The final Typeform block](https://cdn-assets-eu.frontify.com/s3/frontify-enterprise-files-eu/eyJwYXRoIjoid2VhcmVcL2FjY291bnRzXC82ZVwvNDAwMDM4OFwvcHJvamVjdHNcLzk4NFwvYXNzZXRzXC8wMVwvMTQ5MDg3XC9iNzQ4ZmFhNmNhOTg0ZmQ0YjEzMmJhNTE3OGQ1ZWRlNy0xNjQ5MDcwMTgyLnBuZyJ9:weare:SvuUvaDBCW0yJnHpPo74swa39ti5KPYQSJJG_2kFNwg?width=1700\u0026height=1187)\n\nAnd that's it. Congrats for making it this far 🙂\n\nWhile we know that this tutorial is not very in-depth, it should give you an idea of how a basic block is built. We're constantly working on extending and improving our documentation. So if you have feedback, please [get back to us](mailto:hello@frontify.com)!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrontify%2Ftypeform-block-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrontify%2Ftypeform-block-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrontify%2Ftypeform-block-tutorial/lists"}