docs: ban $bindable(default_value) on optional props in CLAUDE.md (#8267)

Add a "Banned Patterns" section documenting that $bindable(default_value)
on props that can be undefined is banned. The correct alternatives are
using $derived(my_prop ?? default_value) or creating a useMyPropState()
helper higher in the component tree.

Closes #8266

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
claude[bot]
2026-03-07 18:55:40 +00:00
committed by GitHub
co-authored by claude[bot] windmill-internal-app[bot]
parent cfd42f2385
commit 2f0b224437
+21
View File
@@ -26,6 +26,27 @@ Open-source platform for internal tools, workflows, API integrations, background
- **Login**: `admin@windmill.dev` / `changeme`
- **Instance settings**: navigate to `/#superadmin-settings`
## Banned Patterns
### `$bindable(default_value)` on optional props
Using `$bindable(default_value)` on props that can be `undefined` is **banned**. This pattern causes subtle bugs because the default value masks the `undefined` state.
**Bad:**
```svelte
let { my_prop = $bindable(default_value) }: { my_prop?: string } = $props()
```
**Correct alternatives:**
1. **Use `$derived` with nullish coalescing** — handle the potential `undefined` at the usage site:
```svelte
let { my_prop = $bindable() }: { my_prop?: string } = $props()
let effective_value = $derived(my_prop ?? default_value)
```
2. **Create a `useMyPropState()` helper** — encapsulate the undefined-handling logic in a reusable function and call it higher in the component tree, so the child component always receives a defined value.
## Core Principles
- Search for existing code to reuse before writing new code