github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/public/src/components/DynamicButton.tsx (about) 1 import React, { useState } from "react" 2 import { Color } from "../Helpers" 3 import { ButtonType } from "./admin/Button" 4 5 6 export type DynamicButtonProps = { 7 text: string, 8 onClick: () => Promise<unknown>, 9 color: Color, 10 type: ButtonType, 11 className?: string, 12 } 13 14 /** DynamicButton will display a spinner while the onClick function is running. 15 * This is useful for buttons that perform an action that takes a while to complete. 16 * The button will be disabled while the onClick function is running. 17 */ 18 const DynamicButton = ({ text, onClick, color, type, className }: DynamicButtonProps) => { 19 const [isPending, setIsPending] = useState<boolean>(false) 20 21 const handleClick = async () => { 22 if (isPending) { 23 // Disable double clicks 24 return 25 } 26 setIsPending(true) 27 await onClick() 28 setIsPending(false) 29 } 30 31 const buttonClass = `${type}-${isPending ? Color.GRAY : color} ${className ?? ""}` 32 const content = isPending 33 ? <span className="spinner-border spinner-border-sm" role="status" aria-hidden="true" /> 34 : text 35 36 return ( 37 <button type="button" disabled={isPending} className={buttonClass} onClick={handleClick}> 38 {content} 39 </button> 40 ) 41 } 42 43 export default DynamicButton