$props and $bindable — Component Props
In React, a component declares its props via its function parameters (or TypeScript interface). Props are always one-way, read-only — the child calls a callback to ask the parent to update. Svelte 5 introduces $props() for the same one-way model, plus $bindable() for an opt-in two-way binding that eliminates the callback boilerplate.
$props() — declaring props with defaults
Section titled “$props() — declaring props with defaults”// Childfunction Greeting({ name = 'World', color = 'black' }) { return <p style={{ color }}>Hello, {name}!</p>;}
// Parentfunction App() { return <Greeting name="Alice" color="steelblue" />;}<script> let { name = 'World', color = 'black' } = $props();</script>
<p style="color: {color}">Hello, {name}!</p>$props() returns an object you destructure normally. Default values work with standard JS destructuring defaults. There is no propTypes, no separate TypeScript interface required (though you can add interface Props and annotate $props<Props>()).
Rest props / forwarding
Section titled “Rest props / forwarding”function Button({ children, variant = 'primary', ...rest }) { return ( <button className={'btn btn-' + variant} {...rest}> {children} </button> );}<script> let { children, variant = 'primary', ...rest } = $props();</script>
<button class="btn btn-{variant}" {...rest}> {@render children?.()}</button>The ...rest spread forwards any extra attributes to the underlying element — exactly like React.
$bindable() — two-way props (no callback needed)
Section titled “$bindable() — two-way props (no callback needed)”React requires “lifting state”: the parent owns the value, the child receives it as a prop and a setter callback. Svelte’s $bindable() lets the parent use bind:propName on the child, giving the child the ability to write back to the parent’s variable without any explicit callback.
// React: parent must own state + pass setter downfunction TextInput({ value, onChange }) { return <input value={value} onChange={e => onChange(e.target.value)} />;}
function App() { const [text, setText] = React.useState(''); return ( <div> <TextInput value={text} onChange={setText} /> <p>You typed: {text}</p> </div> );}<script> // Child: TextInput.svelte let { value = $bindable('') } = $props();</script>
<input bind:value />
<!-- Parent usage: <TextInput bind:value={text} /> -->