Customize the recording studio

On this page
  1. Match your brand
  2. Choose recording modes
  3. Show or hide controls
  4. Countdown and quality
  5. Screen sharing options
  6. Light or shadow mounting
  7. Replace individual screens
  8. Change settings after creation
  9. Use the <dadan-recorder> web component

The built-in studio works without any configuration, but most apps want it to match their brand and offer only the recording types that make sense. This guide covers every option you can pass when you create the studio, plus the <dadan-recorder> web component.

All options go in the object you pass to createInstance (or to the sdk prop of the React and Vue components, or to init() in Angular). Interface options live under config.

typescript
import { createInstance } from "@dadan-io/record-sdk-ui";

const studio = await createInstance({
  mode: "custom",
  publicAppId: import.meta.env.VITE_DADAN_PUBLIC_APP_ID,
  videoTitle: "Product feedback",
  recordingQuality: "1080p",
  mount: "shadow",
  config: {
    theme: {
      primary: "#0F766E",
      appearance: "light",
      borderRadius: "14px",
    },
    features: { modes: ["both", "camera", "audio"], backdrop: false },
    countdownSeconds: 3,
  },
});

config.theme sets the studio’s colors, font and corner radius. Every field is optional.

The studio review screen in dark appearance with a teal Upload button
The review screen with appearance set to dark and a teal primary color.
OptionWhat it changes
primaryAccent color for the main buttons and highlights
appearance"light" or "dark"
fontFamilyFont used in the studio, as a CSS font-family value
borderRadiusCorner radius of panels and buttons, for example "12px"
surfaceBackground of the control bar, menus and chips
surfaceMutedSubtle fills such as the mode selector
inkMain text color
inkSoftSecondary and label text
inkMutedIcon and control color
borderHairline borders
borderStrongStronger borders and switch tracks
dangerDestructive actions and errors
successSuccess states
shadowShadow of the control bar, as a CSS box-shadow value

Check contrast when you change primary and ink: text on the primary color should stay readable for everyone.

config.features.modes controls which recording types appear in the mode picker:

typescript
const studio = await createInstance({
  mode: "custom",
  publicAppId: import.meta.env.VITE_DADAN_PUBLIC_APP_ID,
  config: {
    features: { modes: ["camera", "audio"] },
    defaultMode: "camera",
  },
});
  • The default list is both, camera and screen. Audio-only recording appears only when you add audio.
  • defaultMode opens the studio straight in that mode and skips the picker.
  • With a single mode, the picker is hidden automatically.
  • On phones and tablets, only camera and audio are available because mobile browsers cannot capture the screen. Check with isModeSupported(mode) if you want to hide a choice in your own UI.

You can also choose the mode when you open the studio: studio.open({ mode: "screen" }).

Every flag under config.features defaults to true. Set one to false to hide that control:

FlagControls
modePickerThe recording mode selector
cameraPickerThe camera selector
micPickerThe microphone toggle and selector
systemAudioThe system or tab audio toggle in screen modes
backdropThe background color picker
deckGripThe handle used to drag the control bar
closeButtonThe close button on the control bar
restorePendingTakeThe offer to restore an unsent recording after a reload
  • config.countdownSeconds sets the countdown before recording starts. The default is 3. Use 0 to start immediately.
  • recordingQuality (a top-level option) sets capture quality: "720p", "1080p" (default) or "2k". Lower quality means smaller files and faster uploads on slow connections.

config.screenCapture passes hints to the browser’s screen picker:

OptionEffect
surfacesWhich surfaces to offer: "monitor" (entire screen), "window" and "browser" (a tab)
preferredSurfaceThe surface selected first
surfacePickerShow an Entire screen, Window or Tab choice in the studio. Off by default
preferCurrentTabSuggest the current tab first (Chrome and Edge)
selfBrowserSurface"include" or "exclude" the current tab from the list (Chrome and Edge)
surfaceSwitchingAllow switching the shared surface while recording (Chrome and Edge)
monitorTypeSurfaces"include" or "exclude" entire screens (Chrome and Edge)

Browsers treat these as hints, so people may still be able to pick another surface.

mount decides how the studio’s markup relates to your page’s CSS:

  • "light" (default): the studio is part of your page, so your stylesheets can reach it. Useful when you want to fine-tune its look with your own CSS.
  • "shadow": the studio renders inside a shadow root and your CSS cannot affect it. Choose this when global styles (such as a CSS reset or a utility framework) change how the studio looks. Style it through config.theme.

You can keep the SDK’s capture and upload logic and replace single screens with your own components. The slots are React render functions, so they fit best in React apps:

SlotReplacesProps you receive
renderSetupThe control bar before recordingMode, devices, toggles and onRecord
renderRecordingThe controls while recordingElapsed time, pause, mute and onStop
renderReviewThe preview after recordingobjectUrl, durationSeconds, onConfirmUpload, onRedo, onDiscard
renderUploadingThe upload progress screenpercentage
renderUploadFailedThe upload error screenmessage, onRetry, onDiscard
renderErrorThe error messagemessage, recoverable, onDismiss
countdownComponentThe 3, 2, 1 countdownvalue, durationSeconds, onCancel

For example, a review screen with your own design system:

tsx
import {
  DadanRecordButton,
  type CreateInstanceArgs,
} from "@dadan-io/record-sdk-react";
import type { SdkReviewUiProps } from "@dadan-io/record-sdk-ui";

function ReviewScreen({
  objectUrl,
  durationSeconds,
  onConfirmUpload,
  onRedo,
  onDiscard,
}: SdkReviewUiProps) {
  return (
    <div
      className="review-panel"
      role="dialog"
      aria-label="Review your recording"
    >
      <video src={objectUrl} controls playsInline />
      <p>{Math.round(durationSeconds)} seconds</p>
      <button type="button" onClick={onConfirmUpload}>
        Send video
      </button>
      <button type="button" onClick={onRedo}>
        Record again
      </button>
      <button type="button" onClick={onDiscard}>
        Discard
      </button>
    </div>
  );
}

const sdk: CreateInstanceArgs = {
  mode: "custom",
  publicAppId: import.meta.env.VITE_DADAN_PUBLIC_APP_ID,
  config: { renderReview: (props) => <ReviewScreen {...props} /> },
};

export function FeedbackRecorder() {
  return <DadanRecordButton sdk={sdk} />;
}

SdkReviewUiProps and the other slot types come from @dadan-io/record-sdk-ui, which the React package installs. With pnpm, add @dadan-io/record-sdk-ui to your own dependencies before importing from it.

If you need to replace most screens, a fully custom recorder is simpler. See Build a custom recorder with DadanRecorder.

updateConfig changes interface options or the video title without recreating the studio:

typescript
studio.updateConfig({
  config: { theme: { appearance: "dark" } },
  videoTitle: "Feedback from the pricing page",
});

Use the <dadan-recorder> web component

Link to section: Use the <dadan-recorder> web component

The web component puts the studio in your HTML and configures it with attributes. Add the element where it makes sense in your page:

html
<dadan-recorder
  public-app-id="app_your_public_id"
  video-title="Interview answer"
  folder-id="123456"
  mount="shadow"
  theme='{"primary":"#0F766E"}'
></dadan-recorder>
<button type="button" id="open-recorder">Record your answer</button>

Then register the element once in your JavaScript bundle and open it from your button:

javascript
import { defineDadanRecorder } from "@dadan-io/record-sdk-ui/wc";

defineDadanRecorder();

const recorder = document.querySelector("dadan-recorder");
document
  .querySelector("#open-recorder")
  .addEventListener("click", () => recorder.open());
recorder.addEventListener("dadan-insert", (event) => {
  console.log("Uploaded", event.detail.sharedUrl);
});

recorder.open({ mode: "camera" }) opens a specific mode and recorder.close() closes the studio.

AttributeMeaning
public-app-idYour public app ID
video-titleTitle saved with the recording
folder-id, team-idWhere the recording is saved
recording-quality720p, 1080p or 2k
mountlight or shadow
themeTheme options as JSON
configInterface options (the same as config above) as JSON
auto-openOpen the studio as soon as the element is ready
nonceYour Content Security Policy nonce

The element dispatches these events, which bubble and cross shadow boundaries: dadan-insert (upload finished, event.detail is the DadanVideo), dadan-upload-complete, dadan-cancel, dadan-error (event.detail.code), dadan-backdrop-change and dadan-lifecycle. Removing the element from the page tears the studio down.

Ask AI about this article

What should the AI help you with?

Are you still facing issues?

Reach out to our support team for further assistance.

dadan