react-vite-demo

react and vite demo

git clone https://9o.is/git/react-vite-demo.git

Progress.tsx

(1661B)


      1 import { createContext, ReactNode, useContext, useId } from "react"
      2 
      3 type ProgressContext = { 
      4     labelId: string
      5     progressBarId: string
      6     loading: boolean 
      7 }
      8 
      9 type ProgressProps = {
     10     loading: boolean
     11     children: ReactNode
     12 }
     13 
     14 const ProgressContext = createContext<ProgressContext | undefined>(undefined)
     15 
     16 export function useProgressContext() {
     17     const context = useContext(ProgressContext)
     18     if (!context) throw new Error('useProgressContext must be used within a Progress component')
     19     return context
     20 }
     21 
     22 export function Progress ({ loading, children }: ProgressProps) {
     23     const labelId = useId()
     24     const progressBarId = useId()
     25 
     26     return (
     27         <ProgressContext.Provider value={{ labelId, progressBarId, loading }}>
     28             {children}
     29         </ProgressContext.Provider>
     30     )
     31 }
     32 
     33 function ProgressBar({ children }: { children: ReactNode }) {
     34     const { progressBarId, labelId, loading } = useProgressContext()
     35 
     36     if (!loading) return <>&nbsp;</>
     37 
     38     return (
     39         <div id={progressBarId} role="progressbar" aria-labelledby={labelId}>
     40             {children}
     41         </div>
     42     )
     43 }
     44 
     45 function ProgressLabel({ children }: { children: ReactNode }) {
     46     const { labelId } = useProgressContext()
     47     return (
     48         <span id={labelId}>{children}</span>
     49     )
     50 }
     51 
     52 function ProgressContent({ children }: { children: ReactNode }) {
     53     const { loading, progressBarId } = useProgressContext()
     54     return (
     55         <div aria-live="polite" aria-describedby={loading ? progressBarId : undefined}>
     56             {children}
     57         </div>
     58     )
     59 }
     60 
     61 Progress.Bar = ProgressBar
     62 Progress.Label = ProgressLabel
     63 Progress.Content = ProgressContent