Skip to content

Commit a9506ff

Browse files
kitfunsoclaude
andcommitted
a11y: migrate remaining calculators to accessible Toggle
Updated 13 calculator components to use the accessible Toggle: - BabyCost, BirthdayPartyBudget, CateringCalculator - ConferenceRoomCalculator, EventSeatingCalculator - FenceCalculator, GraduationPartyPlanner - HolidayDinnerCalculator, MarketplaceFees - SolarCalculator, StartupCost, TileCalculator - VacationBudget All toggle buttons now have proper ARIA attributes and keyboard navigation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f4c1b5e commit a9506ff

13 files changed

Lines changed: 140 additions & 356 deletions

File tree

src/components/calculators/BabyCost/BabyCost.tsx

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
MetricCard,
3434
Alert,
3535
ButtonGroup,
36+
Toggle,
3637
} from '../../ui';
3738
import ShareResults from '../../ui/ShareResults';
3839

@@ -175,21 +176,12 @@ export default function BabyCost() {
175176
</div>
176177

177178
{/* Health Insurance */}
178-
<div className="flex items-center gap-3">
179-
<button
180-
onClick={() => updateInput('hasHealthInsurance', !inputs.hasHealthInsurance)}
181-
className={`w-12 h-6 rounded-full transition-all ${
182-
inputs.hasHealthInsurance ? 'bg-rose-500' : 'bg-white/20'
183-
}`}
184-
>
185-
<div
186-
className={`w-5 h-5 rounded-full bg-white transition-transform ${
187-
inputs.hasHealthInsurance ? 'translate-x-6' : 'translate-x-0.5'
188-
}`}
189-
/>
190-
</button>
191-
<span className="text-[var(--color-cream)]">Has Health Insurance</span>
192-
</div>
179+
<Toggle
180+
checked={inputs.hasHealthInsurance}
181+
onChange={(checked) => updateInput('hasHealthInsurance', checked)}
182+
label="Has Health Insurance"
183+
size="md"
184+
/>
193185

194186
{inputs.hasHealthInsurance && inputs.currency === 'USD' && (
195187
<Grid responsive={{ sm: 2 }} gap="md">

src/components/calculators/BirthdayPartyBudget/BirthdayPartyBudget.tsx

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
MetricCard,
3636
Alert,
3737
ButtonGroup,
38+
Toggle,
3839
} from '../../ui';
3940
import ShareResults from '../../ui/ShareResults';
4041

@@ -271,28 +272,13 @@ export default function BirthdayPartyBudget() {
271272
{ key: 'includeCharacter', label: 'Character Appearance' },
272273
{ key: 'includePhotographer', label: 'Photographer' },
273274
].map(({ key, label }) => (
274-
<div key={key} className="flex items-center gap-3">
275-
<button
276-
onClick={() =>
277-
updateInput(
278-
key as keyof BirthdayPartyInputs,
279-
!inputs[key as keyof BirthdayPartyInputs]
280-
)
281-
}
282-
className={`w-10 h-5 rounded-full transition-all ${
283-
inputs[key as keyof BirthdayPartyInputs] ? 'bg-amber-500' : 'bg-white/20'
284-
}`}
285-
>
286-
<div
287-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
288-
inputs[key as keyof BirthdayPartyInputs]
289-
? 'translate-x-5'
290-
: 'translate-x-0.5'
291-
}`}
292-
/>
293-
</button>
294-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
295-
</div>
275+
<Toggle
276+
key={key}
277+
checked={inputs[key as keyof BirthdayPartyInputs] as boolean}
278+
onChange={(checked) => updateInput(key as keyof BirthdayPartyInputs, checked)}
279+
label={label}
280+
size="sm"
281+
/>
296282
))}
297283
</div>
298284

src/components/calculators/CateringCalculator/CateringCalculator.tsx

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
MetricCard,
2828
Alert,
2929
ButtonGroup,
30+
Toggle,
3031
} from '../../ui';
3132
import ShareResults from '../../ui/ShareResults';
3233

@@ -204,23 +205,13 @@ export default function CateringCalculator() {
204205
{ key: 'includeDessert', label: 'Include Dessert' },
205206
{ key: 'includeBreads', label: 'Include Bread/Rolls' },
206207
].map(({ key, label }) => (
207-
<div key={key} className="flex items-center gap-3">
208-
<button
209-
onClick={() =>
210-
updateInput(key as keyof CateringInputs, !inputs[key as keyof CateringInputs])
211-
}
212-
className={`w-10 h-5 rounded-full transition-all ${
213-
inputs[key as keyof CateringInputs] ? 'bg-red-500' : 'bg-white/20'
214-
}`}
215-
>
216-
<div
217-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
218-
inputs[key as keyof CateringInputs] ? 'translate-x-5' : 'translate-x-0.5'
219-
}`}
220-
/>
221-
</button>
222-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
223-
</div>
208+
<Toggle
209+
key={key}
210+
checked={inputs[key as keyof CateringInputs] as boolean}
211+
onChange={(checked) => updateInput(key as keyof CateringInputs, checked)}
212+
label={label}
213+
size="sm"
214+
/>
224215
))}
225216
</div>
226217

src/components/calculators/ConferenceRoomCalculator/ConferenceRoomCalculator.tsx

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
MetricCard,
2525
Alert,
2626
ButtonGroup,
27+
Toggle,
2728
} from '../../ui';
2829
import ShareResults from '../../ui/ShareResults';
2930

@@ -156,21 +157,12 @@ export default function ConferenceRoomCalculator() {
156157
</Grid>
157158

158159
{/* Stage/Presenter Area */}
159-
<div className="flex items-center gap-3">
160-
<button
161-
onClick={() => updateInput('stageOrPresenterArea', !inputs.stageOrPresenterArea)}
162-
className={`w-10 h-5 rounded-full transition-all ${
163-
inputs.stageOrPresenterArea ? 'bg-cyan-500' : 'bg-white/20'
164-
}`}
165-
>
166-
<div
167-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
168-
inputs.stageOrPresenterArea ? 'translate-x-5' : 'translate-x-0.5'
169-
}`}
170-
/>
171-
</button>
172-
<span className="text-[var(--color-cream)] text-sm">Stage/Presenter Area</span>
173-
</div>
160+
<Toggle
161+
checked={inputs.stageOrPresenterArea}
162+
onChange={(checked) => updateInput('stageOrPresenterArea', checked)}
163+
label="Stage/Presenter Area"
164+
size="sm"
165+
/>
174166

175167
{inputs.stageOrPresenterArea && (
176168
<Slider
@@ -200,28 +192,13 @@ export default function ConferenceRoomCalculator() {
200192
{ key: 'includePodium', label: 'Podium/Lectern' },
201193
{ key: 'adaAccessible', label: 'ADA Accessible' },
202194
].map(({ key, label }) => (
203-
<div key={key} className="flex items-center gap-3">
204-
<button
205-
onClick={() =>
206-
updateInput(
207-
key as keyof ConferenceRoomInputs,
208-
!inputs[key as keyof ConferenceRoomInputs]
209-
)
210-
}
211-
className={`w-10 h-5 rounded-full transition-all ${
212-
inputs[key as keyof ConferenceRoomInputs] ? 'bg-cyan-500' : 'bg-white/20'
213-
}`}
214-
>
215-
<div
216-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
217-
inputs[key as keyof ConferenceRoomInputs]
218-
? 'translate-x-5'
219-
: 'translate-x-0.5'
220-
}`}
221-
/>
222-
</button>
223-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
224-
</div>
195+
<Toggle
196+
key={key}
197+
checked={!!inputs[key as keyof ConferenceRoomInputs]}
198+
onChange={(checked) => updateInput(key as keyof ConferenceRoomInputs, checked)}
199+
label={label}
200+
size="sm"
201+
/>
225202
))}
226203
</div>
227204

src/components/calculators/EventSeatingCalculator/EventSeatingCalculator.tsx

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
MetricCard,
2525
Alert,
2626
ButtonGroup,
27+
Toggle,
2728
} from '../../ui';
2829
import ShareResults from '../../ui/ShareResults';
2930

@@ -175,28 +176,13 @@ export default function EventSeatingCalculator() {
175176
{ key: 'includeBuffetArea', label: 'Buffet Area' },
176177
{ key: 'includeHeadTable', label: 'Head Table' },
177178
].map(({ key, label }) => (
178-
<div key={key} className="flex items-center gap-3">
179-
<button
180-
onClick={() =>
181-
updateInput(
182-
key as keyof EventSeatingInputs,
183-
!inputs[key as keyof EventSeatingInputs]
184-
)
185-
}
186-
className={`w-10 h-5 rounded-full transition-all ${
187-
inputs[key as keyof EventSeatingInputs] ? 'bg-purple-500' : 'bg-white/20'
188-
}`}
189-
>
190-
<div
191-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
192-
inputs[key as keyof EventSeatingInputs]
193-
? 'translate-x-5'
194-
: 'translate-x-0.5'
195-
}`}
196-
/>
197-
</button>
198-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
199-
</div>
179+
<Toggle
180+
key={key}
181+
checked={!!inputs[key as keyof EventSeatingInputs]}
182+
onChange={(checked) => updateInput(key as keyof EventSeatingInputs, checked)}
183+
label={label}
184+
size="sm"
185+
/>
200186
))}
201187

202188
{inputs.includeHeadTable && (

src/components/calculators/FenceCalculator/FenceCalculator.tsx

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
MetricCard,
3434
Alert,
3535
Slider,
36+
Toggle,
3637
} from '../../ui';
3738
import ShareResults from '../../ui/ShareResults';
3839

@@ -211,23 +212,12 @@ export default function FenceCalculator() {
211212
</div>
212213
</Grid>
213214

214-
<div className="space-y-3">
215-
<div className="flex items-center gap-3">
216-
<button
217-
onClick={() => updateInput('doublePostCorners', !inputs.doublePostCorners)}
218-
className={`w-10 h-5 rounded-full transition-all ${
219-
inputs.doublePostCorners ? 'bg-emerald-500' : 'bg-white/20'
220-
}`}
221-
>
222-
<div
223-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
224-
inputs.doublePostCorners ? 'translate-x-5' : 'translate-x-0.5'
225-
}`}
226-
/>
227-
</button>
228-
<span className="text-[var(--color-cream)] text-sm">Double Posts at Corners</span>
229-
</div>
230-
</div>
215+
<Toggle
216+
checked={inputs.doublePostCorners}
217+
onChange={(checked) => updateInput('doublePostCorners', checked)}
218+
label="Double Posts at Corners"
219+
size="sm"
220+
/>
231221

232222
<Divider />
233223

src/components/calculators/GraduationPartyPlanner/GraduationPartyPlanner.tsx

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
MetricCard,
2828
Alert,
2929
ButtonGroup,
30+
Toggle,
3031
} from '../../ui';
3132
import ShareResults from '../../ui/ShareResults';
3233

@@ -157,28 +158,13 @@ export default function GraduationPartyPlanner() {
157158
{ key: 'includeDessert', label: 'Desserts' },
158159
{ key: 'includeCake', label: 'Graduation Cake' },
159160
].map(({ key, label }) => (
160-
<div key={key} className="flex items-center gap-3">
161-
<button
162-
onClick={() =>
163-
updateInput(
164-
key as keyof GraduationPartyInputs,
165-
!inputs[key as keyof GraduationPartyInputs]
166-
)
167-
}
168-
className={`w-10 h-5 rounded-full transition-all ${
169-
inputs[key as keyof GraduationPartyInputs] ? 'bg-cyan-500' : 'bg-white/20'
170-
}`}
171-
>
172-
<div
173-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
174-
inputs[key as keyof GraduationPartyInputs]
175-
? 'translate-x-5'
176-
: 'translate-x-0.5'
177-
}`}
178-
/>
179-
</button>
180-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
181-
</div>
161+
<Toggle
162+
key={key}
163+
checked={inputs[key as keyof GraduationPartyInputs] as boolean}
164+
onChange={(checked) => updateInput(key as keyof GraduationPartyInputs, checked)}
165+
label={label}
166+
size="sm"
167+
/>
182168
))}
183169

184170
<Divider />
@@ -193,28 +179,13 @@ export default function GraduationPartyPlanner() {
193179
{ key: 'includePunch', label: 'Punch' },
194180
{ key: 'includeCoffee', label: 'Coffee' },
195181
].map(({ key, label }) => (
196-
<div key={key} className="flex items-center gap-3">
197-
<button
198-
onClick={() =>
199-
updateInput(
200-
key as keyof GraduationPartyInputs,
201-
!inputs[key as keyof GraduationPartyInputs]
202-
)
203-
}
204-
className={`w-10 h-5 rounded-full transition-all ${
205-
inputs[key as keyof GraduationPartyInputs] ? 'bg-cyan-500' : 'bg-white/20'
206-
}`}
207-
>
208-
<div
209-
className={`w-4 h-4 rounded-full bg-white transition-transform ${
210-
inputs[key as keyof GraduationPartyInputs]
211-
? 'translate-x-5'
212-
: 'translate-x-0.5'
213-
}`}
214-
/>
215-
</button>
216-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
217-
</div>
182+
<Toggle
183+
key={key}
184+
checked={inputs[key as keyof GraduationPartyInputs] as boolean}
185+
onChange={(checked) => updateInput(key as keyof GraduationPartyInputs, checked)}
186+
label={label}
187+
size="sm"
188+
/>
218189
))}
219190
</div>
220191

src/components/calculators/HolidayDinnerCalculator/HolidayDinnerCalculator.tsx

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
MetricCard,
2626
Alert,
2727
ButtonGroup,
28+
Toggle,
2829
} from '../../ui';
2930
import ShareResults from '../../ui/ShareResults';
3031

@@ -210,28 +211,13 @@ export default function HolidayDinnerCalculator() {
210211
{ key: 'includeRolls', label: 'Dinner Rolls' },
211212
{ key: 'includePie', label: 'Pies' },
212213
].map(({ key, label }) => (
213-
<div key={key} className="flex items-center gap-2">
214-
<button
215-
onClick={() =>
216-
updateInput(
217-
key as keyof HolidayDinnerInputs,
218-
!inputs[key as keyof HolidayDinnerInputs]
219-
)
220-
}
221-
className={`w-8 h-4 rounded-full transition-all ${
222-
inputs[key as keyof HolidayDinnerInputs] ? 'bg-red-500' : 'bg-white/20'
223-
}`}
224-
>
225-
<div
226-
className={`w-3 h-3 rounded-full bg-white transition-transform ${
227-
inputs[key as keyof HolidayDinnerInputs]
228-
? 'translate-x-4'
229-
: 'translate-x-0.5'
230-
}`}
231-
/>
232-
</button>
233-
<span className="text-[var(--color-cream)] text-sm">{label}</span>
234-
</div>
214+
<Toggle
215+
key={key}
216+
checked={inputs[key as keyof HolidayDinnerInputs] as boolean}
217+
onChange={(checked) => updateInput(key as keyof HolidayDinnerInputs, checked)}
218+
label={label}
219+
size="sm"
220+
/>
235221
))}
236222
</div>
237223
</div>

0 commit comments

Comments
 (0)