Skip to content

Commit 2324d37

Browse files
committed
fix(radio-button): allow standalone usage with checked prop
Fixes #1879
1 parent 750cd75 commit 2324d37

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

src/RadioButton/RadioButton.svelte

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@
5353
add({ id, checked, disabled, value });
5454
}
5555
56-
$: checked = $selectedValue === value;
56+
// Only sync checked when inside RadioButtonGroup.
57+
// This allows standalone `RadioButton` usage.
58+
$: if (add) {
59+
checked = $selectedValue === value;
60+
}
5761
</script>
5862
5963
<div
@@ -74,9 +78,12 @@
7478
on:focus
7579
on:blur
7680
on:change
77-
on:change={() => {
81+
on:change={(e) => {
7882
if (update) {
7983
update(value);
84+
} else {
85+
// Update `checked` for standalone `RadioButton` usage.
86+
checked = e.currentTarget.checked;
8087
}
8188
}}
8289
/>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<svelte:options accessors />
2+
3+
<script lang="ts">
4+
import { RadioButton } from "carbon-components-svelte";
5+
6+
export let checked = false;
7+
</script>
8+
9+
<RadioButton
10+
bind:checked
11+
value="standalone"
12+
labelText="Standalone Option"
13+
name="standalone-radio"
14+
/>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { render, screen } from "@testing-library/svelte";
2+
import { user } from "../setup-tests";
3+
import RadioButtonStandalone from "./RadioButtonStandalone.test.svelte";
4+
5+
describe("RadioButton (Standalone)", () => {
6+
it("should allow checked prop to be updated programmatically when standalone", async () => {
7+
const { component } = render(RadioButtonStandalone, {
8+
props: { checked: false },
9+
});
10+
11+
const input = screen.getByRole("radio") as HTMLInputElement;
12+
expect(input).not.toBeChecked();
13+
14+
component.checked = true;
15+
await new Promise((resolve) => setTimeout(resolve, 0));
16+
17+
expect(input).toBeChecked();
18+
19+
component.checked = false;
20+
await new Promise((resolve) => setTimeout(resolve, 0));
21+
22+
expect(input).not.toBeChecked();
23+
});
24+
25+
it("should bind checked state when user clicks standalone radio button", async () => {
26+
const { component } = render(RadioButtonStandalone, {
27+
props: { checked: false },
28+
});
29+
30+
const input = screen.getByRole("radio");
31+
expect(component.checked).toBe(false);
32+
33+
await user.click(input);
34+
35+
expect(component.checked).toBe(true);
36+
expect(input).toBeChecked();
37+
});
38+
39+
it("should support initial checked state for standalone radio button", () => {
40+
const { component } = render(RadioButtonStandalone, {
41+
props: { checked: true },
42+
});
43+
44+
const input = screen.getByRole("radio");
45+
expect(input).toBeChecked();
46+
expect(component.checked).toBe(true);
47+
});
48+
});

0 commit comments

Comments
 (0)