Skip to content

Commit 1228b74

Browse files
authored
Merge pull request #475 from acelaya-forks/feature/card-modal-form
Wrap CardModal content in form
2 parents 89fedf2 + a950aa5 commit 1228b74

File tree

4 files changed

+52
-24
lines changed

4 files changed

+52
-24
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
66

7-
## [Unreleased]
7+
## [0.9.4] - 2025-05-29
88
### Added
99
* Add `sticky-cell` tailwind utility.
10+
* Wrap content of `CardModal` in `form`, so that it is possible to trigger confirm actions from inputs.
1011

1112
### Changed
1213
* *Nothing*

dev/tailwind/feedback/ModalDialogPage.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { clsx } from 'clsx';
22
import type { FC } from 'react';
33
import { useState } from 'react';
4-
import { Button, CardModal, ModalDialog } from '../../../src/tailwind';
4+
import { Button, CardModal, Input, ModalDialog } from '../../../src/tailwind';
55

66
export const ModalDialogPage: FC = () => {
77
const [plainDialogOpen, setPlainDialogOpen] = useState(false);
@@ -17,6 +17,8 @@ export const ModalDialogPage: FC = () => {
1717
const [confirmDisabledOpen, setConfirmDisabledOpen] = useState(false);
1818
const [dangerConfirmOpen, setDangerConfirmOpen] = useState(false);
1919

20+
const [formOpen, setFormOpen] = useState(false);
21+
2022
const [contentOpen, setContentOpen] = useState(false);
2123

2224
const [coverOpen, setCoverOpen] = useState(false);
@@ -124,6 +126,28 @@ export const ModalDialogPage: FC = () => {
124126
Danger dialog with confirm buttons
125127
</CardModal>
126128

129+
<div className="tw:flex tw:flex-col tw:gap-y-2">
130+
<h2>Card modal with form</h2>
131+
<div className="tw:flex tw:gap-x-2">
132+
<Button onClick={() => setFormOpen(true)}>With form</Button>
133+
</div>
134+
</div>
135+
136+
<CardModal
137+
size="md"
138+
title="Dialog with form"
139+
variant="danger"
140+
open={formOpen}
141+
onClose={() => setFormOpen(false)}
142+
onConfirm={() => setFormOpen(false)}
143+
onClosed={(exitAction) => console.log(`Closed form dialog: ${exitAction}`)}
144+
>
145+
<div className="tw:flex tw:flex-col tw:gap-3">
146+
<Input placeholder="Foo" name="foo" />
147+
<Input placeholder="Bar" name="bar" />
148+
</div>
149+
</CardModal>
150+
127151
<div className="tw:flex tw:flex-col tw:gap-y-2">
128152
<h2>Card modal with a lot of content</h2>
129153
<div className="tw:flex tw:gap-x-2">

src/tailwind/feedback/CardModal.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import clsx from 'clsx';
2-
import type { FC, ReactNode } from 'react';
2+
import type { FC, FormEvent, ReactNode } from 'react';
33
import { useCallback, useEffect, useRef, useState } from 'react';
44
import { Button, CloseButton } from '../form';
55
import { LinkButton } from '../navigation';
@@ -75,11 +75,13 @@ export const CardModal: FC<CardModalProps> = ({
7575
// Proxy the open/close modal state via an auxiliary variable, so that we can delay transitioning to `open=false`
7676
// after a CSS transition has ended.
7777
const [openProxy, setOpenProxy] = useState(open);
78-
const ref = useRef<HTMLDivElement>(null);
78+
const ref = useRef<HTMLFormElement>(null);
7979

8080
// Track what was the exit action, so that we can call onConfirmed with the right value, once close transition ended
8181
const exitAction = useRef<ExitAction>('cancel');
82-
const confirm = useCallback(() => {
82+
const confirm = useCallback((e: FormEvent) => {
83+
e.preventDefault();
84+
e.stopPropagation();
8385
exitAction.current = 'confirm';
8486
onConfirm?.();
8587
}, [onConfirm]);
@@ -142,7 +144,7 @@ export const CardModal: FC<CardModalProps> = ({
142144
)}
143145
{...restDialogProps}
144146
>
145-
<div
147+
<form
146148
data-testid="transition-container"
147149
ref={ref}
148150
className={clsx(
@@ -161,6 +163,7 @@ export const CardModal: FC<CardModalProps> = ({
161163
},
162164
{ 'tw:h-full': variant === 'cover' },
163165
)}
166+
onSubmit={confirm}
164167
>
165168
<Card className={clsx(
166169
'tw:w-full',
@@ -204,7 +207,7 @@ export const CardModal: FC<CardModalProps> = ({
204207
solid
205208
variant={variant === 'danger' ? 'danger' : 'primary'}
206209
disabled={confirmDisabled}
207-
onClick={confirm}
210+
type="submit"
208211
>
209212
{confirmText}
210213
</Button>
@@ -213,7 +216,7 @@ export const CardModal: FC<CardModalProps> = ({
213216
</>
214217
)}
215218
</Card>
216-
</div>
219+
</form>
217220
</ModalDialog>
218221
);
219222
};

test/tailwind/feedback/__snapshots__/CardModal.test.tsx.snap

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ exports[`<CardModal /> > renders expected size 1`] = `
55
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen"
66
open=""
77
>
8-
<div
8+
<form
99
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:sm:w-sm"
1010
data-open=""
1111
data-testid="transition-container"
@@ -53,7 +53,7 @@ exports[`<CardModal /> > renders expected size 1`] = `
5353
</div>
5454
</div>
5555
</div>
56-
</div>
56+
</form>
5757
</dialog>
5858
`;
5959

@@ -62,7 +62,7 @@ exports[`<CardModal /> > renders expected size 2`] = `
6262
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen"
6363
open=""
6464
>
65-
<div
65+
<form
6666
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:md:w-lg"
6767
data-open=""
6868
data-testid="transition-container"
@@ -110,7 +110,7 @@ exports[`<CardModal /> > renders expected size 2`] = `
110110
</div>
111111
</div>
112112
</div>
113-
</div>
113+
</form>
114114
</dialog>
115115
`;
116116

@@ -119,7 +119,7 @@ exports[`<CardModal /> > renders expected size 3`] = `
119119
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen"
120120
open=""
121121
>
122-
<div
122+
<form
123123
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:md:w-4xl"
124124
data-open=""
125125
data-testid="transition-container"
@@ -167,7 +167,7 @@ exports[`<CardModal /> > renders expected size 3`] = `
167167
</div>
168168
</div>
169169
</div>
170-
</div>
170+
</form>
171171
</dialog>
172172
`;
173173

@@ -176,7 +176,7 @@ exports[`<CardModal /> > renders expected size 4`] = `
176176
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen"
177177
open=""
178178
>
179-
<div
179+
<form
180180
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:md:w-6xl"
181181
data-open=""
182182
data-testid="transition-container"
@@ -224,7 +224,7 @@ exports[`<CardModal /> > renders expected size 4`] = `
224224
</div>
225225
</div>
226226
</div>
227-
</div>
227+
</form>
228228
</dialog>
229229
`;
230230

@@ -233,7 +233,7 @@ exports[`<CardModal /> > renders expected variant 1`] = `
233233
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen"
234234
open=""
235235
>
236-
<div
236+
<form
237237
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:md:w-lg"
238238
data-open=""
239239
data-testid="transition-container"
@@ -292,13 +292,13 @@ exports[`<CardModal /> > renders expected variant 1`] = `
292292
</button>
293293
<button
294294
class="tw:flex tw:gap-2 tw:items-center tw:justify-center tw:border tw:rounded-md tw:no-underline tw:transition-colors tw:focus-ring tw:px-3 tw:py-1.5 tw:border-lm-brand tw:dark:border-dm-brand tw:text-white tw:bg-lm-brand tw:dark:bg-dm-brand tw:highlight:bg-lm-brand-dark tw:dark:highlight:bg-dm-brand-dark tw:highlight:border-lm-brand-dark tw:dark:highlight:border-dm-brand-dark tw:highlight:bg-lm-brand tw:dark:highlight:bg-dm-brand"
295-
type="button"
295+
type="submit"
296296
>
297297
Confirm
298298
</button>
299299
</div>
300300
</div>
301-
</div>
301+
</form>
302302
</dialog>
303303
`;
304304

@@ -307,7 +307,7 @@ exports[`<CardModal /> > renders expected variant 2`] = `
307307
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen"
308308
open=""
309309
>
310-
<div
310+
<form
311311
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:md:w-lg"
312312
data-open=""
313313
data-testid="transition-container"
@@ -366,13 +366,13 @@ exports[`<CardModal /> > renders expected variant 2`] = `
366366
</button>
367367
<button
368368
class="tw:flex tw:gap-2 tw:items-center tw:justify-center tw:border tw:rounded-md tw:no-underline tw:transition-colors tw:focus-ring-danger tw:px-3 tw:py-1.5 tw:border-danger tw:text-white tw:bg-danger tw:highlight:bg-danger-dark tw:highlight:border-danger-dark tw:highlight:bg-danger"
369-
type="button"
369+
type="submit"
370370
>
371371
Confirm
372372
</button>
373373
</div>
374374
</div>
375-
</div>
375+
</form>
376376
</dialog>
377377
`;
378378

@@ -381,7 +381,7 @@ exports[`<CardModal /> > renders expected variant 3`] = `
381381
class="tw:bg-transparent tw:backdrop:bg-black/50 tw:flex tw:w-screen tw:h-screen tw:max-w-screen tw:max-h-screen tw:overflow-hidden"
382382
open=""
383383
>
384-
<div
384+
<form
385385
class="tw:w-full tw:m-auto tw:p-4 tw:sm:p-6 tw:-translate-y-4 tw:data-open:translate-y-0 tw:opacity-0 tw:data-open:opacity-100 tw:transition-[opacity_,_translate] tw:duration-300 tw:h-full"
386386
data-open=""
387387
data-testid="transition-container"
@@ -425,6 +425,6 @@ exports[`<CardModal /> > renders expected variant 3`] = `
425425
</div>
426426
</div>
427427
</div>
428-
</div>
428+
</form>
429429
</dialog>
430430
`;

0 commit comments

Comments
 (0)