55 *
66 * Copyright Oxide Computer Company
77 */
8- import { useState } from 'react'
8+ import { useState , type ReactNode } from 'react'
99
1010import { Success12Icon } from '@oxide/design-system/icons/react'
1111
1212import { Button } from '~/ui/lib/Button'
1313import { Modal } from '~/ui/lib/Modal'
1414import { useTimeout } from '~/ui/lib/use-timeout'
1515
16- export function EquivalentCliCommand ( { command } : { command : string } ) {
16+ type CopyCodeProps = {
17+ code : string
18+ modalButtonText : string
19+ copyButtonText : string
20+ modalTitle : string
21+ /** rendered code */
22+ children ?: ReactNode
23+ }
24+
25+ export function CopyCode ( {
26+ code,
27+ modalButtonText,
28+ copyButtonText,
29+ modalTitle,
30+ children,
31+ } : CopyCodeProps ) {
1732 const [ isOpen , setIsOpen ] = useState ( false )
1833 const [ hasCopied , setHasCopied ] = useState ( false )
1934
@@ -24,30 +39,28 @@ export function EquivalentCliCommand({ command }: { command: string }) {
2439 useTimeout ( ( ) => setHasCopied ( false ) , hasCopied ? 2000 : null )
2540
2641 const handleCopy = ( ) => {
27- window . navigator . clipboard . writeText ( command ) . then ( ( ) => {
42+ window . navigator . clipboard . writeText ( code ) . then ( ( ) => {
2843 setHasCopied ( true )
2944 } )
3045 }
3146
3247 return (
3348 < >
3449 < Button variant = "ghost" size = "sm" className = "ml-2" onClick = { ( ) => setIsOpen ( true ) } >
35- Equivalent CLI Command
50+ { modalButtonText }
3651 </ Button >
37- < Modal isOpen = { isOpen } onDismiss = { handleDismiss } title = "CLI command ">
52+ < Modal isOpen = { isOpen } onDismiss = { handleDismiss } title = { modalTitle } width = "free ">
3853 < Modal . Section >
3954 < pre className = "flex w-full rounded border px-4 py-3 !normal-case !tracking-normal text-mono-md bg-default border-secondary" >
40- < div className = "mr-2 select-none text-tertiary" > $</ div >
41- { command }
55+ { children }
4256 </ pre >
4357 </ Modal . Section >
4458 < Modal . Footer
4559 onDismiss = { handleDismiss }
4660 onAction = { handleCopy }
4761 actionText = {
4862 < >
49- { /* use of invisible keeps button the same size in both states */ }
50- < span className = { hasCopied ? 'invisible' : '' } > Copy command</ span >
63+ < span className = { hasCopied ? 'invisible' : '' } > { copyButtonText } </ span >
5164 < span
5265 className = { `absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center ${
5366 hasCopied ? '' : 'invisible'
@@ -63,3 +76,25 @@ export function EquivalentCliCommand({ command }: { command: string }) {
6376 </ >
6477 )
6578}
79+
80+ type EquivProps = { project : string ; instance : string }
81+
82+ export function EquivalentCliCommand ( { project, instance } : EquivProps ) {
83+ const cmdParts = [
84+ 'oxide instance serial console' ,
85+ `--project ${ project } ` ,
86+ `--instance ${ instance } ` ,
87+ ]
88+
89+ return (
90+ < CopyCode
91+ code = { cmdParts . join ( ' ' ) }
92+ modalButtonText = "Equivalent CLI Command"
93+ copyButtonText = "Copy command"
94+ modalTitle = "CLI command"
95+ >
96+ < div className = "mr-2 select-none text-tertiary" > $</ div >
97+ { cmdParts . join ( ' \\\n' ) }
98+ </ CopyCode >
99+ )
100+ }
0 commit comments