Skip to content

Commit 0f6272f

Browse files
frolicmax-drake
andauthored
feat(tldraw): add allowVideoAutoplay option to TldrawOptions (tldraw#8943)
In order to let SDK consumers disable video autoplay across the board without subclassing `VideoShapeUtil`, this PR adds a top-level `allowVideoAutoplay` option to `TldrawOptions`. The host opt-out acts as a ceiling, not a floor: when `false`, no video autoplays regardless of its per-shape `autoplay` prop; when `true` (the default, preserving existing behavior), each shape's per-shape `autoplay` prop is respected. The `prefers-reduced-motion` check at the render site continues to apply independently. ```tsx <Tldraw options={{ allowVideoAutoplay: false }} /> ``` ### Behavior matrix | `TldrawOptions.allowVideoAutoplay` | `shape.props.autoplay` | Result | | ---------------------------------- | ---------------------- | --------------- | | `true` (default) | `true` | Autoplays | | `true` (default) | `false` | Does not play | | `false` | `true` | Does not play | | `false` | `false` | Does not play | So `allowVideoAutoplay: false` is a global opt-out for the host app — it never forces every video to play. The per-shape prop remains the way users opt individual shapes in or out when autoplay is allowed at the host level. Closes [tldraw#8915](tldraw#8915). ### Change type - [x] \`feature\` ### Test plan 1. Create a tldraw editor with \`<Tldraw options={{ allowVideoAutoplay: false }} />\`. 2. Drop a video file onto the canvas — confirm it does not start playing automatically. 3. Click into the video to edit, press play — confirm the user can still play it manually. 4. With the default option (or \`allowVideoAutoplay: true\`), drop a video and confirm it still autoplays as before. 5. With the default option, set \`shape.props.autoplay = false\` on an individual video — confirm only that shape stops autoplaying while others still autoplay. ### Release notes - Add an \`allowVideoAutoplay\` option to \`TldrawOptions\`. When set to \`false\`, no video shape autoplays regardless of its per-shape \`autoplay\` prop — including pasted and restored shapes. Defaults to \`true\`. ### API changes - Added \`TldrawOptions.allowVideoAutoplay: boolean\` (default \`true\`). ### Code changes | Section | LOC change | | --------------- | ---------- | | Core code | +18 / -1 | | Automated files | +2 / -0 | | Documentation | +7 / -0 | --------- Co-authored-by: Max Drake <maxdrake46@gmail.com>
1 parent a8199ec commit 0f6272f

5 files changed

Lines changed: 26 additions & 1 deletion

File tree

apps/docs/content/sdk-features/default-shapes.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ const ConfiguredVideoUtil = VideoShapeUtil.configure({
324324
})
325325
```
326326

327+
To disable autoplay across the board — including for pasted or restored shapes — set the editor-level `allowVideoAutoplay` option to `false` instead:
328+
329+
```tsx
330+
<Tldraw options={{ allowVideoAutoplay: false }} />
331+
```
332+
327333
### Bookmark
328334

329335
The bookmark shape displays a URL as a card with metadata including title, description, and preview image. Bookmarks are created when you paste URLs onto the canvas. The editor fetches metadata from the URL and stores it in an associated asset record. Bookmark shapes have fixed dimensions and can't be resized.

apps/docs/content/sdk-features/options.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ When `debouncedZoom` is enabled and the page has more shapes than `debouncedZoom
201201
| `laserDelayMs` | 1200 | Duration laser pointer remains visible |
202202
| `laserFadeoutMs` | 500 | Duration for laser pointer fadeout animation |
203203
| `quickZoomPreservesScreenBounds` | true | Whether quick zoom brush keeps viewport scale |
204+
| `allowVideoAutoplay` | true | Whether video shapes are allowed to autoplay |
204205
| `branding` | undefined | App name for accessibility labels |
205206
| `nonce` | undefined | CSP nonce for inline styles |
206207

packages/editor/api-report.api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ export const DefaultSvgDefs: () => null;
718718
export const defaultTldrawOptions: {
719719
readonly actionShortcutsLocation: "swap";
720720
readonly adjacentShapeMargin: 10;
721+
readonly allowVideoAutoplay: true;
721722
readonly animationMediumMs: 320;
722723
readonly camera: TLCameraOptions;
723724
readonly cameraMovingTimeoutMs: 64;
@@ -3754,6 +3755,7 @@ export interface TldrawOptions {
37543755
readonly actionShortcutsLocation: 'menu' | 'swap' | 'toolbar';
37553756
// (undocumented)
37563757
readonly adjacentShapeMargin: number;
3758+
readonly allowVideoAutoplay: boolean;
37573759
// (undocumented)
37583760
readonly animationMediumMs: number;
37593761
readonly branding?: string;

packages/editor/src/lib/options.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ export interface TldrawOptions {
209209
* viewport's page dimensions regardless of overview zoom changes.
210210
*/
211211
readonly quickZoomPreservesScreenBounds: boolean
212+
/**
213+
* Whether video shapes are allowed to autoplay. When `true` (the default), each
214+
* video respects its own `shape.props.autoplay` value. When `false`, no video
215+
* autoplays regardless of its shape prop — useful for host apps that want to
216+
* disable autoplay across the board, including for pasted or restored shapes.
217+
*
218+
* This does not change the per-shape `autoplay` prop on new video shapes — that
219+
* default is controlled by `VideoShapeOptions.autoplay` on `VideoShapeUtil`. The
220+
* `prefers-reduced-motion` media query continues to suppress autoplay independently.
221+
*/
222+
readonly allowVideoAutoplay: boolean
212223
/**
213224
* Called before content is written to the clipboard during a copy or cut operation.
214225
* Receives the serialized content (shapes, bindings, assets) and can filter or transform
@@ -347,6 +358,7 @@ export const defaultTldrawOptions = {
347358
text: {},
348359
deepLinks: undefined,
349360
quickZoomPreservesScreenBounds: true,
361+
allowVideoAutoplay: true,
350362
onBeforeCopyToClipboard: undefined,
351363
onBeforePasteFromClipboard: undefined,
352364
onClipboardPasteRaw: undefined,

packages/tldraw/src/lib/shapes/video/VideoShapeUtil.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,11 @@ const VideoShape = memo(function VideoShape({ shape }: { shape: TLVideoShape })
210210
height="100%"
211211
draggable={false}
212212
playsInline
213-
autoPlay={shape.props.autoplay && !prefersReducedMotion}
213+
autoPlay={
214+
shape.props.autoplay &&
215+
editor.options.allowVideoAutoplay &&
216+
!prefersReducedMotion
217+
}
214218
muted
215219
loop
216220
disableRemotePlayback

0 commit comments

Comments
 (0)