1
- import { useRef , useState , type ComponentProps } from 'react' ;
1
+ import { useRef , useState , type ComponentProps , type ReactNode } from 'react' ;
2
2
import { Root , Portal , Content , Item , Trigger } from '@radix-ui/react-context-menu' ;
3
+ import * as RadixDialog from '@radix-ui/react-dialog' ;
3
4
import picomatch from 'picomatch/posix' ;
4
5
import type { FileDescriptor , I18n } from '@tutorialkit/types' ;
5
6
@@ -44,7 +45,8 @@ export function ContextMenu({
44
45
triggerProps,
45
46
...props
46
47
} : Props ) {
47
- const [ state , setState ] = useState < 'idle' | 'add_file' | 'add_folder' > ( 'idle' ) ;
48
+ const [ state , setState ] = useState < 'idle' | 'add_file' | 'add_folder' | { error : string } > ( 'idle' ) ;
49
+ const error = typeof state === 'string' ? false : state . error ;
48
50
const inputRef = useRef < HTMLInputElement > ( null ) ;
49
51
50
52
if ( ! onFileChange ) {
@@ -65,8 +67,7 @@ export function ContextMenu({
65
67
method : 'add' ,
66
68
} ) ;
67
69
} else {
68
- // TODO: Use `@radix-ui/react-dialog` instead
69
- alert ( `File "${ value } " is not allowed. Allowed patterns: [${ allowEditPatterns . join ( ', ' ) } ].` ) ;
70
+ return setState ( { error : `Failed to create "${ name } "` } ) ;
70
71
}
71
72
}
72
73
@@ -126,6 +127,19 @@ export function ContextMenu({
126
127
</ MenuItem >
127
128
</ Content >
128
129
</ Portal >
130
+
131
+ { error && (
132
+ < Dialog onClose = { ( ) => setState ( 'idle' ) } >
133
+ { error } . Allowed patterns are:
134
+ < ul className = "list-disc ml-4" >
135
+ { allowEditPatterns . map ( ( pattern ) => (
136
+ < li key = { pattern } >
137
+ < code > { pattern } </ code >
138
+ </ li >
139
+ ) ) }
140
+ </ ul >
141
+ </ Dialog >
142
+ ) }
129
143
</ Root >
130
144
) ;
131
145
}
@@ -141,3 +155,25 @@ function MenuItem({ icon, children, ...props }: { icon: string } & ComponentProp
141
155
</ Item >
142
156
) ;
143
157
}
158
+
159
+ function Dialog ( { onClose, children } : { onClose : ( ) => void ; children : ReactNode } ) {
160
+ return (
161
+ < RadixDialog . Root open = { true } onOpenChange = { ( open ) => ! open && onClose ( ) } >
162
+ < RadixDialog . Portal >
163
+ < RadixDialog . Overlay className = "fixed inset-0 opacity-50 bg-black" />
164
+
165
+ < RadixDialog . Content className = "fixed top-50% left-50% transform-translate--50% w-90vw max-w-450px max-h-85vh rounded-xl text-tk-text-primary bg-tk-background-negative" >
166
+ < div className = "relative py-4 px-10" >
167
+ < RadixDialog . Title className = "text-6 mb-2" > Failed to create file</ RadixDialog . Title >
168
+
169
+ { children }
170
+
171
+ < RadixDialog . Close title = "Close" className = "absolute top-4 right-4 w-6 h-6" >
172
+ < span aria-hidden className = "i-ph-x block w-full h-full" > </ span >
173
+ </ RadixDialog . Close >
174
+ </ div >
175
+ </ RadixDialog . Content >
176
+ </ RadixDialog . Portal >
177
+ </ RadixDialog . Root >
178
+ ) ;
179
+ }
0 commit comments