Skip to content

Commit

Permalink
POC: Add Dialog
Browse files Browse the repository at this point in the history
This is a proof of concept for utilizing the "new" native HTML `dialog` element with the `open` attribute. By default, it is accessible with focus and keyboard navigation.

In this version, it triggers a dialog/modal upon clicking on an event. The dialog includes a close button (the dialog also closes when pressing the escape key or clicking on the backdrop) and a button that currently displays an alert with the event's title. `handleEventEditing` will later be an update request to the API.
  • Loading branch information
kasperbirch1 committed Mar 20, 2024
1 parent 8bdf5b4 commit 144841a
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 25 deletions.
39 changes: 39 additions & 0 deletions src/apps/opening-hours-editor/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// The dialog element allready has keyboard support
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import React, { forwardRef } from "react";

type DialogType = {
children: React.ReactNode;
closeDialog: () => void;
};

const Dialog = forwardRef<HTMLDialogElement, DialogType>(
({ children, closeDialog }, ref) => {
return (
<dialog
ref={ref}
// close dialog when clicking outside of it (::backdrop pseudo-element)
onClick={({ currentTarget, target }) => {
if (currentTarget === target) {
closeDialog();
}
}}
>
<button
type="button"
onClick={closeDialog}
style={{
border: "1px solid black",
padding: "5px",
background: "grey"
}}
>
Close
</button>
{children}
</dialog>
);
}
);
export default Dialog;
35 changes: 35 additions & 0 deletions src/apps/opening-hours-editor/DialogFomular.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import { EventImpl } from "@fullcalendar/core/internal";

type DialogFomularProps = {
evnetInfo: EventImpl;
handleEventEditing: (title: string) => void;
};

const DialogFomular: React.FC<DialogFomularProps> = ({
evnetInfo,
handleEventEditing
}) => {
return (
<>
<p>DialogFomular:</p>
<pre>{JSON.stringify(evnetInfo, null, 2)}</pre>
<form>
{/* Should be type submit */}
<button
type="button"
onClick={() => handleEventEditing(evnetInfo.title)}
style={{
border: "1px solid black",
padding: "5px",
background: "grey"
}}
>
Show title btn
</button>
</form>
</>
);
};

export default DialogFomular;
67 changes: 43 additions & 24 deletions src/apps/opening-hours-editor/OpeningHoursEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,54 @@ import interactionPlugin from "@fullcalendar/interaction";
import da from "@fullcalendar/core/locales/da";
import OpeningHoursEditorEventContent from "./OpeningHoursEditorEventContent";
import useOpeningHours from "./useOpeningHours";
import DialogFomular from "./DialogFomular";
import Dialog from "./Dialog";
import useDialog from "./useDialog";

const OpeningHoursEditor: React.FC = () => {
const { events, handleEventSelect, handleEventClick, handleEventRemove } =
const { events, handleEventSelect, handleEventEditing, handleEventRemove } =
useOpeningHours();

const { dialogContent, openDialogWithContent, closeDialog, dialogRef } =
useDialog();

return (
<FullCalendar
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
headerToolbar={{
left: "title",
center: "prev,next today",
right: "dayGridMonth,timeGridWeek"
}}
initialView="timeGridWeek"
locale={da}
selectable
select={handleEventSelect}
eventClick={handleEventClick}
eventContent={(eventInput) =>
OpeningHoursEditorEventContent({
eventInput,
handleEventRemove
})
}
events={events}
stickyHeaderDates
height="auto"
selectMirror
/>
<>
<Dialog closeDialog={closeDialog} ref={dialogRef}>
{dialogContent}
</Dialog>

<FullCalendar
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
headerToolbar={{
left: "title",
center: "prev,next today",
right: "dayGridMonth,timeGridWeek"
}}
initialView="timeGridWeek"
locale={da}
selectable
select={handleEventSelect}
eventClick={(clickInfo) =>
openDialogWithContent(
<DialogFomular
evnetInfo={clickInfo.event}
handleEventEditing={handleEventEditing}
/>
)
}
eventContent={(eventInput) =>
OpeningHoursEditorEventContent({
eventInput,
handleEventRemove
})
}
events={events}
stickyHeaderDates
height="auto"
selectMirror
/>
</>
);
};

Expand Down
25 changes: 25 additions & 0 deletions src/apps/opening-hours-editor/useDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useRef, useState } from "react";

const useDialog = () => {
const [dialogContent, setDialogContent] = useState<React.ReactNode>(null);

const dialogRef = useRef<HTMLDialogElement>(null);

const closeDialog = () => {
dialogRef.current?.close();

Check failure on line 9 in src/apps/opening-hours-editor/useDialog.tsx

View workflow job for this annotation

GitHub Actions / Typescript compile check

Property 'close' does not exist on type 'HTMLDialogElement'.
};

const openDialogWithContent = (content: React.ReactNode) => {
setDialogContent(content);
dialogRef.current?.showModal();

Check failure on line 14 in src/apps/opening-hours-editor/useDialog.tsx

View workflow job for this annotation

GitHub Actions / Typescript compile check

Property 'showModal' does not exist on type 'HTMLDialogElement'.
};

return {
dialogContent,
dialogRef,
openDialogWithContent,
closeDialog
};
};

export default useDialog;
9 changes: 8 additions & 1 deletion src/apps/opening-hours-editor/useOpeningHours.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const useOpeningHours = () => {
calendarApi.unselect();
};

// This will probably be replaced with handleEventEditing
const handleEventClick = (clickInfo: EventClickArg) => {
// eslint-disable-next-line no-alert
const newTitle = prompt(
Expand All @@ -65,6 +66,11 @@ const useOpeningHours = () => {
}
};

const handleEventEditing = (string: string) => {
// eslint-disable-next-line no-alert
alert(string);
};

const handleEventRemove = (eventToRemove: EventInput) => {
setEvents(events.filter((event) => event.id !== eventToRemove.id));
};
Expand All @@ -73,7 +79,8 @@ const useOpeningHours = () => {
events,
handleEventSelect,
handleEventClick,
handleEventRemove
handleEventRemove,
handleEventEditing
};
};

Expand Down

0 comments on commit 144841a

Please sign in to comment.