Skip to content

Commit d4ea947

Browse files
committed
Enable the modal to be opened by default
1 parent 16588c0 commit d4ea947

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

src/Modal.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,47 @@ addModalTranslations({
181181

182182
export { addModalTranslations };
183183

184-
function createOpenModalButtonProps(id: string) {
184+
function createOpenModalButtonProps(params: { modalId: string; isOpenedByDefault: boolean }) {
185+
const { modalId, isOpenedByDefault } = params;
186+
185187
return {
188+
//For RSC we don't want to pass an empty function.
186189
"onClick": undefined as any as () => void,
187190
"nativeButtonProps": {
188-
"aria-controls": id,
189-
"data-fr-opened": false
191+
"aria-controls": modalId,
192+
"data-fr-opened": isOpenedByDefault
190193
}
191194
};
192195
}
193196

194197
let counter = 0;
195198

196199
/** @see <https://react-dsfr-components.etalab.studio/?path=/docs/components-modal> */
197-
export function createModal<Name extends string>(
198-
name: Name
199-
): Record<`${Uncapitalize<Name>}ModalButtonProps`, ReturnType<typeof createOpenModalButtonProps>> &
200+
export function createModal<Name extends string>(params: {
201+
name: Name;
202+
isOpenedByDefault: boolean;
203+
}): Record<`${Uncapitalize<Name>}ModalButtonProps`, ReturnType<typeof createOpenModalButtonProps>> &
200204
Record<`${Capitalize<Name>}Modal`, (props: ModalProps) => JSX.Element> {
205+
const { name, isOpenedByDefault } = params;
206+
201207
const modalId = `${uncapitalize(name)}-modal-${counter++}`;
202208

209+
const openModalButtonProps = createOpenModalButtonProps({
210+
modalId,
211+
isOpenedByDefault
212+
});
213+
203214
function InternalModal(props: ModalProps) {
204-
return <Modal {...props} id={modalId} />;
215+
return (
216+
<>
217+
{isOpenedByDefault && (
218+
<Button {...openModalButtonProps} className={fr.cx("fr-hidden")}>
219+
{" "}
220+
</Button>
221+
)}
222+
<Modal {...props} id={modalId} />
223+
</>
224+
);
205225
}
206226

207227
InternalModal.displayName = `${capitalize(name)}Modal`;
@@ -210,6 +230,6 @@ export function createModal<Name extends string>(
210230

211231
return {
212232
[InternalModal.displayName]: InternalModal,
213-
[`${uncapitalize(name)}ModalButtonProps`]: createOpenModalButtonProps(modalId)
233+
[`${uncapitalize(name)}ModalButtonProps`]: openModalButtonProps
214234
} as any;
215235
}

stories/Modal.stories.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ const { meta, getStory } = getStoryFactory({
1414
1515
- [See DSFR documentation](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/modale)
1616
- [See source code](https://github.com/codegouvfr/react-dsfr/blob/main/src/Modal.tsx)
17+
18+
This is a uncontrolled implementation of the modal, compatible with Server Components.
19+
An controlled variant is coming soon.
20+
1721
`,
1822
"argTypes": {
1923
"title": {
@@ -68,7 +72,10 @@ const { meta, getStory } = getStoryFactory({
6872

6973
export default meta;
7074

71-
const { SimpleModal, simpleModalButtonProps } = createModal("simple");
75+
const { SimpleModal, simpleModalButtonProps } = createModal({
76+
"name": "simple",
77+
"isOpenedByDefault": false
78+
});
7279

7380
function Template(args: ModalProps) {
7481
return (
@@ -109,7 +116,10 @@ Default.parameters = {
109116
import { createModal } from "@codegouvfr/react-dsfr/Modal";
110117
import { Button } from "@codegouvfr/react-dsfr/Button";
111118
112-
const { AcceptTermsModal, acceptTermsModalButtonProps } = createModal("acceptTerms");
119+
const { AcceptTermsModal, acceptTermsModalButtonProps } = createModal(
120+
name: "simple",
121+
isOpenedByDefault: false
122+
);
113123
114124
function MyComponent(){
115125

0 commit comments

Comments
 (0)