Openstatus www.openstatus.dev
at 20d0eeac16db94063a196dbfa8cb02fb172cac98 62 lines 1.7 kB view raw
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}