@@ -526,14 +526,33 @@ export async function renderTui(options: TuiOptions): Promise<void> {
526526
527527 return new Promise ( ( resolve ) => {
528528 const handleExit = ( ) => {
529+ // Clean up the renderer before exiting (following opencode pattern)
530+ try {
531+ renderer . destroy ( ) ;
532+ } catch {
533+ // Ignore errors during cleanup
534+ }
529535 options . onCancel ( ) ;
536+ resolve ( ) ;
530537 process . exit ( 0 ) ;
531538 } ;
532539
540+ // Handle SIGINT (Ctrl+C) for clean exit
541+ process . on ( "SIGINT" , handleExit ) ;
542+
533543 createRoot ( renderer ) . render (
534544 < App
535545 initialConfig = { options . initialConfig }
536- onComplete = { options . onComplete }
546+ onComplete = { async ( config ) => {
547+ await options . onComplete ( config ) ;
548+ // Clean up after successful completion
549+ try {
550+ renderer . destroy ( ) ;
551+ } catch {
552+ // Ignore errors during cleanup
553+ }
554+ resolve ( ) ;
555+ } }
537556 onExit = { handleExit }
538557 /> ,
539558 ) ;
@@ -717,13 +736,13 @@ function App(props: {
717736 < box style = { { width, height, backgroundColor : theme . bg , flexDirection : "column" } } >
718737 < box
719738 style = { {
720- height : 5 ,
739+ height : 6 ,
721740 justifyContent : "center" ,
722741 alignItems : "center" ,
723742 backgroundColor : theme . surface ,
724743 } }
725744 >
726- < ascii-font text = "Better T Stack" font = "tiny " />
745+ < ascii-font text = "Better T Stack" font = "block " />
727746 </ box >
728747
729748 < box
@@ -735,11 +754,12 @@ function App(props: {
735754 overflow : "scroll" ,
736755 } }
737756 >
738- { /* Prompts Phase */ }
757+ { /* Prompts Phase - Sequential like clack */ }
739758 { phase === "prompts" && (
740- < >
759+ < box style = { { flexDirection : "column" } } >
760+ { /* Completed steps - compact list */ }
741761 { visibleSteps . slice ( 0 , currentVisibleIndex ) . map ( ( { step } ) => (
742- < box key = { step . id } style = { { flexDirection : "row" } } >
762+ < box key = { step . id } style = { { flexDirection : "row" , marginBottom : 0 } } >
743763 < text >
744764 < span fg = { theme . success } > ◆</ span >
745765 < span fg = { theme . muted } > { step . title } : </ span >
@@ -748,8 +768,9 @@ function App(props: {
748768 </ box >
749769 ) ) }
750770
771+ { /* Current step - prominent with spacing */ }
751772 { ! completed && currentStep && (
752- < box style = { { marginTop : 1 } } >
773+ < box style = { { marginTop : currentVisibleIndex > 0 ? 1 : 0 , flexDirection : "column" } } >
753774 < box style = { { flexDirection : "row" , marginBottom : 1 } } >
754775 < text >
755776 < span fg = { theme . primary } > ◇</ span >
@@ -805,23 +826,15 @@ function App(props: {
805826 </ box >
806827 ) }
807828
829+ { /* Confirmation step */ }
808830 { completed && (
809831 < ConfirmStep
810832 config = { config }
811833 onComplete = { handleComplete }
812834 onBack = { ( ) => setCompleted ( false ) }
813835 />
814836 ) }
815-
816- { ! completed &&
817- visibleSteps . slice ( currentVisibleIndex + 1 ) . map ( ( { step } ) => (
818- < box key = { step . id } style = { { flexDirection : "row" } } >
819- < text >
820- < span fg = { theme . muted } > ○ { step . title } </ span >
821- </ text >
822- </ box >
823- ) ) }
824- </ >
837+ </ box >
825838 ) }
826839
827840 { /* Creating Phase - Show spinner and logs */ }
@@ -905,34 +918,76 @@ function App(props: {
905918 </ span >
906919 </ text >
907920 </ box >
908-
909- < box style = { { marginTop : 3 } } >
910- < text >
911- < span fg = { theme . muted } > Press any key to exit...</ span >
912- </ text >
913- </ box >
914921 </ box >
915922 ) }
916923 </ box >
917924
918- < box
919- style = { {
920- height : 1 ,
921- backgroundColor : theme . surface ,
922- paddingLeft : 2 ,
923- paddingRight : 2 ,
924- flexDirection : "row" ,
925- justifyContent : "space-between" ,
926- } }
927- >
928- < text >
929- < span fg = { theme . muted } > ctrl+c</ span >
930- < span fg = { theme . subtext } > exit</ span >
931- </ text >
932- < text >
933- < span fg = { theme . primary } > better-t-stack.dev</ span >
934- </ text >
935- </ box >
925+ { /* Status Bar */ }
926+ < StatusBar phase = { phase } canGoBack = { stepIndex > 0 } />
927+ </ box >
928+ ) ;
929+ }
930+
931+ // Version from package.json
932+ const VERSION = "3.11.0" ;
933+
934+ // Status bar component showing keybinds and version
935+ function StatusBar ( props : { phase : Phase ; canGoBack : boolean } ) {
936+ const keybinds = ( ) => {
937+ switch ( props . phase ) {
938+ case "prompts" :
939+ return (
940+ < >
941+ < span fg = { theme . muted } > ↑↓</ span >
942+ < span fg = { theme . subtext } > navigate </ span >
943+ < span fg = { theme . muted } > ⏎</ span >
944+ < span fg = { theme . subtext } > select </ span >
945+ { props . canGoBack && (
946+ < >
947+ < span fg = { theme . muted } > esc</ span >
948+ < span fg = { theme . subtext } > back </ span >
949+ </ >
950+ ) }
951+ < span fg = { theme . muted } > ctrl+c</ span >
952+ < span fg = { theme . subtext } > exit</ span >
953+ </ >
954+ ) ;
955+ case "creating" :
956+ return (
957+ < >
958+ < span fg = { theme . muted } > ctrl+c</ span >
959+ < span fg = { theme . subtext } > cancel</ span >
960+ </ >
961+ ) ;
962+ case "done" :
963+ return (
964+ < >
965+ < span fg = { theme . muted } > any key</ span >
966+ < span fg = { theme . subtext } > exit</ span >
967+ </ >
968+ ) ;
969+ }
970+ } ;
971+
972+ return (
973+ < box
974+ style = { {
975+ height : 1 ,
976+ backgroundColor : theme . surface ,
977+ paddingLeft : 2 ,
978+ paddingRight : 2 ,
979+ flexDirection : "row" ,
980+ justifyContent : "space-between" ,
981+ alignItems : "center" ,
982+ } }
983+ >
984+ < text >
985+ < span fg = { theme . muted } > v{ VERSION } </ span >
986+ </ text >
987+ < text > { keybinds ( ) } </ text >
988+ < text >
989+ < span fg = { theme . primary } > better-t-stack.dev</ span >
990+ </ text >
936991 </ box >
937992 ) ;
938993}
0 commit comments