framer-code-link 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,715 @@
1
+ # Framer Property Controls
2
+
3
+ Control types for property controls in Framer components. Each control type specifies a different user interface for receiving input. All control types accept `title`, `description`, and `hidden` properties.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Boolean](#boolean)
8
+ - [Number](#number)
9
+ - [String](#string)
10
+ - [Enum](#enum)
11
+ - [Color](#color)
12
+ - [ResponsiveImage](#responsiveimage)
13
+ - [File](#file)
14
+ - [Array](#array)
15
+ - [Slot](#slot)
16
+ - [EventHandler](#eventhandler)
17
+ - [Font](#font)
18
+ - [Transition](#transition)
19
+ - [BoxShadow](#boxshadow)
20
+ - [Link](#link)
21
+ - [Date](#date)
22
+ - [Object](#object)
23
+ - [Border](#border)
24
+ - [Cursor](#cursor)
25
+ - [Padding](#padding)
26
+ - [BorderRadius](#borderradius)
27
+ - [Gap](#gap)
28
+ - [TrackingId](#trackingid)
29
+ - [Deprecated Controls](#deprecated-controls)
30
+ - [TypeScript Interfaces](#typescript-interfaces)
31
+
32
+ ## Boolean
33
+
34
+ A control that displays an on/off checkbox. The associated property will be `true` or `false`, depending on the state of the checkbox.
35
+
36
+ **Properties:**
37
+
38
+ - `defaultValue`: Set to `true` by default
39
+ - `optional`: Whether the control value is optional
40
+ - `enabledTitle`: Customize the label when enabled _(deprecated)_
41
+ - `disabledTitle`: Customize the label when disabled _(deprecated)_
42
+
43
+ **Example:**
44
+
45
+ ```javascript
46
+ export function MyComponent(props) {
47
+ return <Frame size={"100%"}>{props.showText ? "Hello World" : null}</Frame>;
48
+ }
49
+
50
+ addPropertyControls(MyComponent, {
51
+ showText: {
52
+ type: ControlType.Boolean,
53
+ title: "Show Text",
54
+ defaultValue: true,
55
+ },
56
+ });
57
+ ```
58
+
59
+ ## Number
60
+
61
+ A control that accepts any numeric value. This will be provided directly as a property. Displays an input field with a range slider by default.
62
+
63
+ **Properties:**
64
+
65
+ - `defaultValue`: The default numeric value
66
+ - `min`: Minimum allowed value
67
+ - `max`: Maximum allowed value
68
+ - `unit`: Unit label (e.g., "deg", "px")
69
+ - `step`: Increment value for the slider
70
+ - `displayStepper`: Enable to show a stepper control instead
71
+ - `optional`: Whether the control value is optional
72
+
73
+ **Example:**
74
+
75
+ ```javascript
76
+ export function MyComponent(props) {
77
+ return (
78
+ <Frame rotateZ={props.rotation} size={"100%"}>
79
+ {props.rotation}
80
+ </Frame>
81
+ );
82
+ }
83
+
84
+ addPropertyControls(MyComponent, {
85
+ rotation: {
86
+ type: ControlType.Number,
87
+ defaultValue: 0,
88
+ min: 0,
89
+ max: 360,
90
+ unit: "deg",
91
+ step: 0.1,
92
+ displayStepper: true,
93
+ },
94
+ });
95
+ ```
96
+
97
+ ## String
98
+
99
+ A control that accepts plain text values. Displays an input field with an optional placeholder value.
100
+
101
+ **Properties:**
102
+
103
+ - `defaultValue`: The default text value
104
+ - `placeholder`: Placeholder text
105
+ - `obscured`: Set to true to use a password input field
106
+ - `displayTextArea`: Enable for a multi-line input area
107
+ - `preventLocalization`: Prevents automatic translation of the text
108
+ - `optional`: Whether the control value is optional
109
+
110
+ **Example:**
111
+
112
+ ```javascript
113
+ export function MyComponent(props) {
114
+ return (
115
+ <Frame>
116
+ {props.title} — {props.body}
117
+ </Frame>
118
+ );
119
+ }
120
+
121
+ addPropertyControls(MyComponent, {
122
+ title: {
123
+ type: ControlType.String,
124
+ defaultValue: "Framer",
125
+ placeholder: "Type something…",
126
+ },
127
+ body: {
128
+ type: ControlType.String,
129
+ defaultValue: "Lorem ipsum dolor sit amet.",
130
+ placeholder: "Type something…",
131
+ displayTextArea: true,
132
+ },
133
+ });
134
+ ```
135
+
136
+ ## Enum
137
+
138
+ A property control that represents a list of options. The selected option will be provided as a property. Displayed as a dropdown menu.
139
+
140
+ **Properties:**
141
+
142
+ - `defaultValue`: The default selected option (string, boolean, number, or null)
143
+ - `options`: Array of unique values (string, boolean, number, or null)
144
+ - `optionTitles`: Display names for the options
145
+ - `displaySegmentedControl`: Enable to display a segmented control instead
146
+ - `segmentedControlDirection`: Direction of the segmented control ('horizontal' or 'vertical')
147
+
148
+ **Example:**
149
+
150
+ ```javascript
151
+ export function MyComponent(props) {
152
+ const value = props.value || "a";
153
+ const colors = { a: "red", b: "green", c: "blue" };
154
+ return (
155
+ <Frame background={colors[value]} size={"100%"}>
156
+ {value}
157
+ </Frame>
158
+ );
159
+ }
160
+
161
+ addPropertyControls(MyComponent, {
162
+ value: {
163
+ type: ControlType.Enum,
164
+ defaultValue: "a",
165
+ options: ["a", "b", "c"],
166
+ optionTitles: ["Option A", "Option B", "Option C"],
167
+ },
168
+ });
169
+ ```
170
+
171
+ **Example with Segmented Control:**
172
+
173
+ ```javascript
174
+ addPropertyControls(MyComponent, {
175
+ alignment: {
176
+ type: ControlType.Enum,
177
+ defaultValue: "left",
178
+ options: ["left", "center", "right"],
179
+ optionTitles: ["Left", "Center", "Right"],
180
+ displaySegmentedControl: true,
181
+ segmentedControlDirection: "horizontal",
182
+ },
183
+ });
184
+ ```
185
+
186
+ ## Color
187
+
188
+ A control that represents a color value. The selected color is provided as a string in either HEX (`"#fff"`) or HSL (`hsla(203, 87%, 50%, 0.5)`) notation, depending on whether there is an alpha channel.
189
+
190
+ **Properties:**
191
+
192
+ - `defaultValue`: The default color value
193
+ - `optional`: Whether the color is optional
194
+
195
+ **Example:**
196
+
197
+ ```javascript
198
+ function MyComponent(props) {
199
+ return <Frame background={props.background} size={"100%"} />;
200
+ }
201
+
202
+ addPropertyControls(MyComponent, {
203
+ background: {
204
+ type: ControlType.Color,
205
+ defaultValue: "#fff",
206
+ },
207
+ });
208
+ ```
209
+
210
+ ## ResponsiveImage
211
+
212
+ A control that allows the user to pick an image resource. Displayed as an image picker with associated file picker.
213
+
214
+ **Returns an object with:**
215
+
216
+ - `src`: URL string of the full resolution image
217
+ - `srcSet`: Optional string with scaled image variants (for `<img srcSet>`)
218
+ - `alt`: Optional description of the image
219
+
220
+ **Example:**
221
+
222
+ ```javascript
223
+ function MyComponent(props) {
224
+ return (
225
+ <img
226
+ src={props.image?.src}
227
+ srcSet={props.image?.srcSet}
228
+ alt={props.image?.alt}
229
+ />
230
+ );
231
+ }
232
+
233
+ addPropertyControls(MyComponent, {
234
+ image: {
235
+ type: ControlType.ResponsiveImage,
236
+ },
237
+ });
238
+ ```
239
+
240
+ ## File
241
+
242
+ A control that allows the user to pick a file resource. The selected file will be provided as a fully qualified URL.
243
+
244
+ **Properties:**
245
+
246
+ - `allowedFileTypes`: Array specifying acceptable file types. Supported formats:
247
+ - Media types (`"image/png"`, `"audio/*"`, `"*/*"`)
248
+ - File extensions with dot (`".png"`, `".mov"`)
249
+ - File extensions without dot (`"png"`) for backward compatibility
250
+ - Wildcard (`"*"`) to allow everything
251
+
252
+ **Example:**
253
+
254
+ ```javascript
255
+ export function MyComponent(props) {
256
+ return (
257
+ <Frame size={"100%"}>
258
+ <video
259
+ style={{
260
+ objectFit: "contain",
261
+ width: props.width,
262
+ height: props.height,
263
+ }}
264
+ src={props.filepath}
265
+ controls
266
+ />
267
+ </Frame>
268
+ );
269
+ }
270
+
271
+ addPropertyControls(MyComponent, {
272
+ filepath: {
273
+ type: ControlType.File,
274
+ allowedFileTypes: ["mov", "mp4"],
275
+ },
276
+ });
277
+ ```
278
+
279
+ ## Array
280
+
281
+ A control that allows multiple values per `ControlType`, provided as an array via properties. Displays as an additional section in the properties panel.
282
+
283
+ **Properties:**
284
+
285
+ - `control`: The control type to repeat
286
+ - `minCount`: Minimum number of items
287
+ - `maxCount`: Maximum number of items
288
+ - `defaultValue`: Default array values
289
+
290
+ **Example with Objects:**
291
+
292
+ ```javascript
293
+ export function MyComponent(props) {
294
+ return (
295
+ <Stack size={"100%"}>
296
+ {props.items.map((item, index) => (
297
+ <div key={index}>{item.title}</div>
298
+ ))}
299
+ </Stack>
300
+ );
301
+ }
302
+
303
+ addPropertyControls(MyComponent, {
304
+ items: {
305
+ type: ControlType.Array,
306
+ control: {
307
+ type: ControlType.Object,
308
+ controls: {
309
+ title: { type: ControlType.String, defaultValue: "Item" },
310
+ image: { type: ControlType.ResponsiveImage },
311
+ },
312
+ },
313
+ defaultValue: [{ title: "First" }, { title: "Second" }],
314
+ maxCount: 10,
315
+ },
316
+ });
317
+ ```
318
+
319
+ ## Slot
320
+
321
+ A control that references one or more other components on the canvas, included in the component props as a React node. By default allows any number of components to be linked.
322
+
323
+ **Properties:**
324
+
325
+ - `maxCount`: Maximum number of components to be linked
326
+
327
+ **Example:**
328
+
329
+ ```javascript
330
+ export function MyComponent(props) {
331
+ return <Stack size={"100%"}>{props.children}</Stack>;
332
+ }
333
+
334
+ addPropertyControls(MyComponent, {
335
+ children: {
336
+ type: ControlType.Slot,
337
+ maxCount: 5,
338
+ },
339
+ });
340
+ ```
341
+
342
+ ## EventHandler
343
+
344
+ A control that exposes events in the prototyping panel within the Framer UI. When choosing an event, you can select from a list of actions to trigger.
345
+
346
+ **Example:**
347
+
348
+ ```javascript
349
+ export function MyComponent(props) {
350
+ return <Frame onTap={props.onTap} size={"100%"} />;
351
+ }
352
+
353
+ addPropertyControls(MyComponent, {
354
+ onTap: {
355
+ type: ControlType.EventHandler,
356
+ },
357
+ });
358
+ ```
359
+
360
+ ## Font
361
+
362
+ A control that allows for selecting a font to be used in the component.
363
+
364
+ **Properties:**
365
+
366
+ - `defaultValue`: Default font settings
367
+ - `controls`: Specifies control options ("basic" or "extended")
368
+ - `defaultFontType`: Default font type ("sans-serif", "serif", or "monospace")
369
+ - `displayTextAlignment`: Whether to display text alignment options
370
+ - `displayFontSize`: Whether to display font size options
371
+
372
+ **Default Value Options:**
373
+
374
+ - `textAlign`: "left", "right", "center", or "justify"
375
+ - `fontSize`: string or number (e.g., "16px", 16)
376
+ - `letterSpacing`: string or number (e.g., "-0.01em", 0.1)
377
+ - `lineHeight`: string or number (e.g., "1.5em", 1.5, "150%")
378
+ - `variant`: Font variant (only for "sans-serif" font type)
379
+
380
+ **Example:**
381
+
382
+ ```javascript
383
+ export function MyComponent(props) {
384
+ return <div style={props.customFont}>Hello World</div>;
385
+ }
386
+
387
+ addPropertyControls(MyComponent, {
388
+ customFont: {
389
+ type: ControlType.Font,
390
+ defaultValue: {
391
+ fontSize: "16px",
392
+ variant: "Medium",
393
+ letterSpacing: "-0.01em",
394
+ lineHeight: "1.2em",
395
+ textAlign: "left",
396
+ },
397
+ controls: "extended",
398
+ defaultFontType: "sans-serif",
399
+ },
400
+ });
401
+ ```
402
+
403
+ ## Transition
404
+
405
+ A control that allows for editing Framer Motion transition options within the Framer UI.
406
+
407
+ **Properties:**
408
+
409
+ - `defaultValue`: Default transition (null or Transition object)
410
+
411
+ **Example:**
412
+
413
+ ```javascript
414
+ export function MyComponent(props) {
415
+ return <Frame animate={{ scale: 2 }} transition={props.transition} />;
416
+ }
417
+
418
+ addPropertyControls(MyComponent, {
419
+ transition: {
420
+ type: ControlType.Transition,
421
+ },
422
+ });
423
+ ```
424
+
425
+ ## BoxShadow
426
+
427
+ A control that allows for exposing shadows. The value will be provided as a string with valid CSS box-shadow values.
428
+
429
+ **Properties:**
430
+
431
+ - `defaultValue`: Default shadow (string or BoxShadow array)
432
+
433
+ **Example:**
434
+
435
+ ```javascript
436
+ export function MyComponent(props) {
437
+ return <motion.div style={{ boxShadow: props.shadow }} />;
438
+ }
439
+
440
+ addPropertyControls(MyComponent, {
441
+ shadow: {
442
+ type: ControlType.BoxShadow,
443
+ },
444
+ });
445
+ ```
446
+
447
+ ## Link
448
+
449
+ A control that allows for exposing web links.
450
+
451
+ **Properties:**
452
+
453
+ - `defaultValue`: Default URL as string
454
+
455
+ **Example:**
456
+
457
+ ```javascript
458
+ export function MyComponent(props) {
459
+ return <a href={props.link}>My Link</a>;
460
+ }
461
+
462
+ addPropertyControls(MyComponent, {
463
+ link: {
464
+ type: ControlType.Link,
465
+ },
466
+ });
467
+ ```
468
+
469
+ ## Date
470
+
471
+ A control that allows for exposing dates. The value will be provided in toJSON() string format.
472
+
473
+ **Properties:**
474
+
475
+ - `displayTime`: Whether to include time selection
476
+ - `defaultValue`: Default date as ISO string
477
+ - `optional`: Whether the date is optional
478
+
479
+ **Example:**
480
+
481
+ ```javascript
482
+ export function MyComponent(props) {
483
+ const formattedDate = React.useMemo(() => {
484
+ return props.date ? new Date(props.date).toLocaleDateString() : "No date";
485
+ }, [props.date]);
486
+ return <div>{formattedDate}</div>;
487
+ }
488
+
489
+ addPropertyControls(MyComponent, {
490
+ date: {
491
+ type: ControlType.Date,
492
+ displayTime: true,
493
+ optional: true,
494
+ },
495
+ });
496
+ ```
497
+
498
+ ## Object
499
+
500
+ A control that allows for grouping multiple properties as an object.
501
+
502
+ **Properties:**
503
+
504
+ - `controls`: Object containing nested controls
505
+ - `defaultValue`: Default object values
506
+ - `buttonTitle`: Custom button title
507
+ - `optional`: Whether the object is optional
508
+ - `icon`: Icon to display ('object', 'effect', 'color', 'interaction', or 'boolean')
509
+
510
+ **Example:**
511
+
512
+ ```javascript
513
+ export function MyComponent(props) {
514
+ return (
515
+ <Frame opacity={props.style?.opacity} background={props.style?.tint} />
516
+ );
517
+ }
518
+
519
+ addPropertyControls(MyComponent, {
520
+ style: {
521
+ type: ControlType.Object,
522
+ optional: true,
523
+ icon: "effect",
524
+ controls: {
525
+ opacity: { type: ControlType.Number, defaultValue: 1, min: 0, max: 1 },
526
+ tint: { type: ControlType.Color, defaultValue: "#000" },
527
+ },
528
+ },
529
+ });
530
+ ```
531
+
532
+ ## Border
533
+
534
+ A control that represents a border.
535
+
536
+ **Properties:**
537
+
538
+ - `defaultValue`: Default border settings
539
+ - `optional`: Whether the border is optional
540
+
541
+ **Border Value Object:**
542
+
543
+ - `borderColor`: CSS color string
544
+ - `borderStyle`: "solid", "dashed", "dotted", or "double"
545
+ - `borderWidth`: Uniform width (number)
546
+ - `borderTopWidth`, `borderLeftWidth`, `borderRightWidth`, `borderBottomWidth`: Per-side widths
547
+
548
+ **Example:**
549
+
550
+ ```javascript
551
+ function MyComponent(props) {
552
+ return <div style={props.border} />;
553
+ }
554
+
555
+ addPropertyControls(MyComponent, {
556
+ border: {
557
+ type: ControlType.Border,
558
+ defaultValue: {
559
+ borderWidth: 1,
560
+ borderStyle: "solid",
561
+ borderColor: "rgba(0, 0, 0, 0.5)",
562
+ },
563
+ },
564
+ });
565
+ ```
566
+
567
+ ## Cursor
568
+
569
+ A control that allows specifying a web cursor that should be shown when mousing over the element assigned.
570
+
571
+ **Properties:**
572
+
573
+ - `defaultValue`: Default cursor value (CSS cursor string)
574
+
575
+ **Example:**
576
+
577
+ ```javascript
578
+ function MyComponent(props) {
579
+ return <div style={{ cursor: props.cursor }}>Hover me</div>;
580
+ }
581
+
582
+ addPropertyControls(MyComponent, {
583
+ cursor: {
584
+ type: ControlType.Cursor,
585
+ defaultValue: "pointer",
586
+ },
587
+ });
588
+ ```
589
+
590
+ ## Padding
591
+
592
+ A control that represents CSS padding.
593
+
594
+ **Properties:**
595
+
596
+ - `defaultValue`: Default padding value (e.g., "8px", "10px 20px", "10px 20px 30px 40px")
597
+
598
+ **Example:**
599
+
600
+ ```javascript
601
+ function MyComponent({ padding }) {
602
+ return <div style={{ padding }}>Content</div>;
603
+ }
604
+
605
+ addPropertyControls(MyComponent, {
606
+ padding: {
607
+ type: ControlType.Padding,
608
+ defaultValue: "8px",
609
+ },
610
+ });
611
+ ```
612
+
613
+ ## BorderRadius
614
+
615
+ A control that represents CSS border radius.
616
+
617
+ **Properties:**
618
+
619
+ - `defaultValue`: Default border radius value (e.g., "16px", "8px 16px")
620
+
621
+ **Example:**
622
+
623
+ ```javascript
624
+ function MyComponent({ borderRadius }) {
625
+ return <div style={{ borderRadius, background: "red" }} />;
626
+ }
627
+
628
+ addPropertyControls(MyComponent, {
629
+ borderRadius: {
630
+ type: ControlType.BorderRadius,
631
+ defaultValue: "16px",
632
+ title: "Radius",
633
+ },
634
+ });
635
+ ```
636
+
637
+ ## Gap
638
+
639
+ A control that represents CSS gap for grid/flex layouts.
640
+
641
+ **Properties:**
642
+
643
+ - `defaultValue`: Default gap value (e.g., "8px", "8px 16px")
644
+
645
+ **Example:**
646
+
647
+ ```javascript
648
+ function MyComponent({ gap, children }) {
649
+ return <div style={{ display: "flex", gap }}>{children}</div>;
650
+ }
651
+
652
+ addPropertyControls(MyComponent, {
653
+ gap: {
654
+ type: ControlType.Gap,
655
+ defaultValue: "8px",
656
+ },
657
+ children: {
658
+ type: ControlType.Slot,
659
+ },
660
+ });
661
+ ```
662
+
663
+ ## TrackingId
664
+
665
+ A control that represents an ID for tracking events.
666
+
667
+ **Format Requirements:**
668
+
669
+ - Lowercase letters (a-z) and numbers (0-9) only
670
+ - Hyphens (-) as separators (no leading/trailing or consecutive hyphens)
671
+ - Valid: "button-click", "form-submit", "video-play", "nav-item-1"
672
+ - Invalid: "Button-Click", "form--submit", "-button-click", "button_utils"
673
+
674
+ **Properties:**
675
+
676
+ - `defaultValue`: Default tracking ID string
677
+
678
+ **Example:**
679
+
680
+ ```javascript
681
+ function MyComponent(props) {
682
+ const handleClick = () => {
683
+ // Track the event using props.trackingId
684
+ analytics.track(props.trackingId);
685
+ };
686
+ return <button onClick={handleClick}>Click me</button>;
687
+ }
688
+
689
+ addPropertyControls(MyComponent, {
690
+ trackingId: {
691
+ type: ControlType.TrackingId,
692
+ defaultValue: "button-click",
693
+ },
694
+ });
695
+ ```
696
+
697
+ ## Deprecated Controls
698
+
699
+ ### ControlType.Image
700
+
701
+ **Deprecated.** Use `ControlType.ResponsiveImage` instead. The `src` field provides the image URL.
702
+
703
+ ### ControlType.ComponentInstance
704
+
705
+ **Deprecated.** Use `ControlType.Slot` instead. The new Slot type doesn't need to be nested within an array control for multiple items. By default, Slot allows infinite items; use `maxCount` to limit.
706
+
707
+ ### ControlType.SegmentedEnum
708
+
709
+ **Deprecated.** Use `ControlType.Enum` with `displaySegmentedControl: true` instead.
710
+
711
+ ### ControlType.FusedNumber
712
+
713
+ **Deprecated.** Use `ControlType.Padding` and `ControlType.BorderRadius` instead. These new controls provide a single value (e.g., "10px" or "10px 20px 30px 40px").
714
+
715
+ For TypeScript interfaces and type definitions, see [Property Control Types](PROPERTY_CONTROL_TYPES.md).