Props and slots

Create and expose custom properties in Webflow Designer for use in React.

DevLink converts Webflow’s component properties into fully typed React props, giving you programmatic control over your components.

These props come with full TypeScript support and preserve all the defaults and rules set up in Webflow. You can use them to update content, handle user interactions, and control how your components behave in your React app.

Basic props

Webflow’s native component properties for content and visibility. The visual editor defines these properties, and DevLink automatically types them in React. DevLink Export supports the following properties:

A prop’s Type setting determines the values it can accept and how it appears in the Designer.

  • Text
  • Video
  • Link
  • Rich text
  • Number
  • Visibility

Example: Notification button

This Button component has text and visibility props to show the number of new notifications for a user. The text prop sets the number of notifications, while the showThis visibility prop shows/hides the button based on the number of notifications.

Dashboard.tsx
1import { Button } from "webflow/Button";
2
3
4export default function Dashboard({numNotifications}: {numNotifications: number}) {
5 return (
6 <div>
7 <Button
8 text={`${numNotifications} new notifications`}
9 showIcon={numNotifications > 0}
10 />
11 </div>
12 );
13}

Attributes

Attributes props let exported components forward arbitrary HTML attributes — data-*, aria-*, id, role, event handlers, refs — onto an element’s underlying DOM node. DevLink emits the prop typed as Record<string, unknown> and spreads it on the bound element.

Use Attributes props to:

  • Forward analytics or test-id attributes (data-testid, data-analytics-id)
  • Inject ARIA attributes from React (aria-label, aria-describedby)
  • Hook into element events (onClick, onSubmit)
  • Apply inline styles or attach a React ref

Creating Attributes props in Webflow

You have two ways to expose Attributes on an element:

  1. From the Custom attributes panel. Select the element in the Designer, open the Settings tab in the right panel, and find Custom attributes. Add attributes by Name and Value, then bind the entire list to a new prop. DevLink generates a prop named after your binding, typed Record<string, unknown>. Any static attributes you set become the prop’s default value.
  2. From the Props management panel. Open Props management, click Add property, choose Attributes, then bind it to an element via that element’s Custom attributes section.

Example: Tagged button

This Button component has a buttonAttributes Attributes prop bound to the button element.

Dashboard.tsx
1import { Button } from "webflow/Button";
2
3export default function Dashboard() {
4 return (
5 <Button
6 text="Save"
7 buttonAttributes={{
8 "data-analytics-id": "save-button",
9 "aria-describedby": "save-help",
10 onClick: () => console.log("clicked"),
11 }}
12 />
13 );
14}

In the exported component, the prop type is Record<string, unknown>, and the static attributes you set in the Designer become the default value:

Button.tsx (generated)
1export type ButtonProps = {
2 buttonAttributes?: Record<string, unknown>;
3 text?: React.ReactNode;
4};
5
6export function Button({
7 buttonAttributes = { "data-default": "yes" },
8 text = "Click me",
9}: ButtonProps) {
10 return <button {...buttonAttributes}>{text}</button>;
11}

Slots

Webflow’s native Slot element lets a component accept other components as content, so you can nest components in instances of a parent component — from the Designer or from React.

To create a slot:

  1. Open the parent component in the Designer.
  2. Add a Slot element where the nested content should appear.
  3. In instances of the component, drop other components into the slot — or in your React code, pass them via the matching prop.

Example: Card component with a slot

For example, this Card component has a cardContent slot that accepts a React component as its value:

Card.tsx
1/**
2 * @generated
3 * @file Card (generated by DevLink)
4 *
5 * This file is generated by DevLink from a Webflow component. Manual edits are discouraged.
6 *
7 * @see {@link https://my-example-site.design.webflow.com | Source site in Webflow}
8 */
9"use client";
10
11import { DEVLINK_SCOPE_CLASS } from "./devlinkScope";
12import Block from "./webflow_modules/Basic/components/Block";
13import Heading from "./webflow_modules/Basic/components/Heading";
14import InlineCode from "./webflow_modules/Basic/components/InlineCode";
15import Section from "./webflow_modules/Basic/components/Section";
16
17/**
18 * Props for {@link Card}
19 */
20export type CardProps = {
21 as?: React.ElementType;
22 cardContent?: React.ReactNode;
23 text?: React.ReactNode;
24};
25
26/**
27 * Card
28 *
29 * @see {@link https://my-example-site.design.webflow.com | Source site in Webflow}
30 */
31export function Card({
32 as: _Component = Section,
33 cardContent,
34 text = "Hello.",
35}: CardProps) {
36 return (
37 <div
38 className={DEVLINK_SCOPE_CLASS}
39 style={{
40 display: "contents",
41 }}
42 >
43 <_Component
44 grid={{
45 type: "section",
46 }}
47 tag="section"
48 >
49 <Heading tag="h1">
50 <InlineCode>{"My component"}</InlineCode>
51 </Heading>
52 <Block tag="div">{text}</Block>
53 {cardContent}
54 </_Component>
55 </div>
56 );
57}

You can put other React components in the slot by passing them as the prop value, as in this example:

UserProfileCard.tsx
1import { Card } from "webflow/Card";
2import { UserProfile } from "../../../../../components/UserProfile";
3
4export function UserProfileCard() {
5 return (
6 <Card
7 cardContent={
8 <UserProfile id="42" />
9 }
10 />
11 );
12}

When to use slots

  • Embed custom React components (e.g., charts, modals, media players).
  • Integrate third-party libraries inside a Webflow-made layout.
  • Pass dynamic content into a reusable Webflow component without hard-coding it in the Designer.

For more information about using slots, see Slots.