Openstatus
www.openstatus.dev
1import React from "react";
2
3import { Button } from "@openstatus/ui/src/components/button";
4
5import { Kbd } from "../../kbd";
6import { LoadingAnimation } from "../../loading-animation";
7
8interface Props {
9 onSubmit?: () => void;
10 isPending?: boolean;
11 isDirty?: boolean;
12 form?: string;
13}
14
15export function SaveButton({ isPending, isDirty, onSubmit, form }: Props) {
16 React.useEffect(() => {
17 const callback = (event: KeyboardEvent) => {
18 // event.metaKey - pressed Command key on Macs
19 // event.ctrlKey - pressed Control key on Linux or Windows
20 if ((event.metaKey || event.ctrlKey) && event.key === "s") {
21 event.preventDefault();
22 onSubmit?.();
23 }
24 };
25 document.addEventListener("keydown", callback);
26 return () => {
27 document.removeEventListener("keydown", callback);
28 };
29 // no need to listen to `onSubmit` changes
30 }, [onSubmit]);
31
32 return (
33 <div className="grid gap-3 sm:justify-end">
34 <div className="flex flex-col gap-6 sm:col-span-full sm:flex-row sm:justify-end">
35 <Button
36 className="w-full sm:w-auto"
37 size="lg"
38 type="submit"
39 disabled={isPending}
40 form={form}
41 >
42 {!isPending ? (
43 <span className="flex items-center gap-2">
44 Confirm
45 <Kbd>
46 <span className="mr-0.5">⌘</span>
47 <span>S</span>
48 </Kbd>
49 </span>
50 ) : (
51 <LoadingAnimation />
52 )}
53 </Button>
54 </div>
55 {isDirty ? (
56 <p className="text-muted-foreground text-xs">
57 You have unsaved changes
58 </p>
59 ) : null}
60 </div>
61 );
62}