Architect a headless Toggle with scoped slots

This tests decoupling logic from markup via scoped slots. A strong answer exposes on and toggle through a single default scoped slot, renders no DOM, and cites UI flexibility. A red flag is using config props or CSS classes to control layout.
What's really being asked
This question tests your ability to decouple component behavior from its visual representation. Interviewers want to see if you know how to use scoped slots to invert control, letting the parent own the markup while the child owns the state machine. It also surfaces whether you understand the trade-offs between configurable props and true composition.
The full answer
First, the component should render nothing but a single slot element with no wrapper divs or styling. Second, it should expose state and actions through a default scoped slot, for example passing an object containing on, toggle, and perhaps setOn or off. Third, mention that the parent receives this slot scope and decides what to render, whether that is a button, a switch, or a checkbox. Fourth, list the main advantages: the consumer gets full control over markup and CSS, the same logic can power wildly different UIs without forking code, and the component stays lightweight because it ships no presentational opinions. Fifth, note that this pattern works in Vue via scoped slots and in Svelte via slot props.
The mistakes people make
A red flag is suggesting the Toggle accept props like theme, color, or layout to customize its appearance. Another mistake is rendering wrapper elements or hard-coding a button inside the component and exposing only minor CSS variables. Some candidates forget that scoped slots are callbacks that receive data, and instead try to emit events or use provide and inject for this tightly coupled parent-child relationship. Others confuse renderless with higher-order components or mixins, missing that the slot mechanism keeps the API declarative and tree-shakeable.
What usually comes next
The interviewer might ask how you would handle accessibility, such as wiring aria-pressed or keyboard listeners, and where that logic lives. It is best to keep ARIA attributes and keyboard handlers inside the headless component so that every consumer inherits them. They might also ask how to support compound components, like a Toggle that exposes multiple named scoped slots for on and off states. Another follow-up is performance: because the renderless component adds no DOM, there is no extra reflow cost, but you should avoid creating new objects in the slot scope on every render to prevent unnecessary parent re-renders.
A concrete example
In Vue, the Toggle component would have a template containing only slot v-bind="slotProps" where slotProps is an object with on and toggle. The script section holds a data property on and a method toggle that flips it. The parent consumes it like Toggle v-slot="{ on, toggle }" and renders a button with its own classes, deciding whether to show a checkmark or a label based on on. In Svelte, you would use let: directives on the component to achieve the same inversion of control.
Interview question
When architecting a headless Toggle component, which approach correctly inverts control so the parent owns the markup?
- a.Rendering only a scoped slot that passes on and toggle to the parent, which decides what DOM to emitCorrect
- b.Accepting theme, color, and layout props to customize a pre-rendered button inside the component
- c.Wrapping the slot in a div and exposing CSS variables for the parent to style the wrapper
- d.Emitting toggle events upward and expecting the parent to implement its own state machine
Why? this is the answer
A headless component must render no DOM of its own and expose state and actions through a scoped slot so the parent controls all markup. Option B is a red flag because config props like theme tightly couple logic to a specific visual implementation rather than truly inverting control.
Just read this? Test yourself on what you have been reading.
Read the original → adamwathan.me
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on vue — each one lists the topics its interview covers.
See open roles