1- import { createFileRoute , retainSearchParams } from "@tanstack/react-router" ;
2- import { useEffect , useState } from "react" ;
3- import { codeToHtml } from "shiki" ;
4- import { Header } from "@/components/layout/header" ;
5- import { Button } from "@/components/ui/button" ;
61import {
2+ Button ,
73 Card ,
84 CardContent ,
95 CardDescription ,
106 CardHeader ,
117 CardTitle ,
12- } from "@/components/ui/card" ;
8+ } from "@databricks/app-kit-ui/react" ;
9+ import { createFileRoute , retainSearchParams } from "@tanstack/react-router" ;
10+ import { useEffect , useState } from "react" ;
11+ import { codeToHtml } from "shiki" ;
12+ import { Header } from "@/components/layout/header" ;
1313
1414export const Route = createFileRoute ( "/type-safety" ) ( {
1515 component : TypeSafetyRoute ,
@@ -34,17 +34,9 @@ function CodeBlock({
3434 } ) . then ( setHtml ) ;
3535 } , [ code , lang ] ) ;
3636
37- if ( ! html ) {
38- return (
39- < pre className = "bg-gray-800 text-gray-300 p-4 rounded-md text-sm font-mono overflow-x-auto" >
40- { code }
41- </ pre >
42- ) ;
43- }
44-
4537 return (
4638 < div
47- className = "rounded-md overflow-hidden [&>pre]:m-0 [&>pre]:p-4 [&>pre]:text-sm"
39+ className = "rounded-md overflow-hidden [&>pre]:m-0 [&>pre]:p-4 [&>pre]:text-sm font-mono "
4840 dangerouslySetInnerHTML = { { __html : html } }
4941 />
5042 ) ;
@@ -128,14 +120,14 @@ function FlowStep({
128120 < div className = "flex items-center" >
129121 < div className = "flex flex-col items-center" >
130122 < div
131- className = { `w-10 h-10 rounded-full flex items-center justify-center text-white font-semibold text-sm ${
132- active ? "bg-gray-900 " : "bg-gray-400 "
123+ className = { `w-10 h-10 rounded-full flex items-center justify-center text-primary-foreground font-semibold text-sm ${
124+ active ? "bg-primary " : "bg-muted-foreground/40 "
133125 } `}
134126 >
135127 { number }
136128 </ div >
137129 < span
138- className = { `mt-2 text-xs ${ active ? "text-gray-900 font-medium" : "text-gray-500 " } ` }
130+ className = { `mt-2 text-xs ${ active ? "text-foreground font-medium" : "text-muted-foreground " } ` }
139131 >
140132 { title }
141133 </ span >
@@ -167,7 +159,7 @@ function FlowDiagram() {
167159 />
168160 { index < steps . length - 1 && (
169161 < div
170- className = { `w-8 h-0.5 mx-3 ${ index < activeStep ? "bg-gray-900 " : "bg-gray-300 " } ` }
162+ className = { `w-8 h-0.5 mx-3 ${ index < activeStep ? "bg-primary " : "bg-border " } ` }
171163 />
172164 ) }
173165 </ div >
@@ -185,6 +177,7 @@ function IntelliSenseDemo() {
185177 const [ timeoutIds , setTimeoutIds ] = useState < ReturnType < typeof setTimeout > [ ] > (
186178 [ ] ,
187179 ) ;
180+ const [ html , setHtml ] = useState ( "" ) ;
188181
189182 const queryNames = [
190183 "apps_list" ,
@@ -298,63 +291,61 @@ function IntelliSenseDemo() {
298291 scheduleFromStep ( 0 ) ;
299292 } ;
300293
301- const codeLines = [
302- "const { data } = useAnalyticsQuery(" ,
303- step >= 2 ? ' "spend_data",' : ' "|"' ,
304- " {" ,
294+ // Use a unique placeholder that shiki won't transform
295+ const CURSOR_PLACEHOLDER = "___CURSOR___" ;
296+
297+ // Build code based on step - show cursor where user is "typing"
298+ const code =
305299 step >= 3
306- ? ' startDate: sql.date("2024-01-01"),'
300+ ? `const { data } = useAnalyticsQuery(
301+ "spend_data",
302+ {
303+ startDate: sql.date("2024-01-01"),
304+ endDate: sql.date("2024-12-31"),
305+ }
306+ );
307+
308+ data?.map(row => row.${ CURSOR_PLACEHOLDER } )`
307309 : step >= 2
308- ? " |"
309- : "" ,
310- step >= 3 ? ' endDate: sql.date("2024-12-31"),' : "" ,
311- " }" ,
312- ");" ,
313- "" ,
314- step >= 3 ? "data?.map(row => row.|)" : "" ,
315- ] . filter ( Boolean ) ;
310+ ? `const { data } = useAnalyticsQuery(
311+ "spend_data",
312+ {
313+ ${ CURSOR_PLACEHOLDER }
314+ }
315+ );`
316+ : `const { data } = useAnalyticsQuery(
317+ "${ CURSOR_PLACEHOLDER } "
318+ );` ;
319+
320+ useEffect ( ( ) => {
321+ codeToHtml ( code , {
322+ lang : "typescript" ,
323+ theme : "dark-plus" ,
324+ } ) . then ( ( highlighted ) => {
325+ // Replace placeholder with cursor HTML
326+ const cursorHtml = `<span class="animate-pulse bg-white/90 text-zinc-900 px-[1px]">|</span>` ;
327+ setHtml ( highlighted . replace ( CURSOR_PLACEHOLDER , cursorHtml ) ) ;
328+ } ) ;
329+ } , [ code ] ) ;
316330
317331 return (
318332 < div >
319- < div className = "relative bg-gray-800 rounded-md p-4 font-mono text-sm min-h-[240px]" >
320- < pre className = "text-gray-300" >
321- { codeLines . map ( ( line ) => (
322- < div key = { line } className = "leading-6" >
323- { line . includes ( "|" ) ? (
324- < >
325- { line . split ( "|" ) [ 0 ] }
326- < span className = "bg-white text-gray-900 animate-pulse" >
327- |
328- </ span >
329- { line . split ( "|" ) [ 1 ] }
330- </ >
331- ) : (
332- < span
333- className = {
334- line . includes ( '"spend_data"' )
335- ? "text-green-400"
336- : line . includes ( "sql." )
337- ? "text-green-400"
338- : ""
339- }
340- >
341- { line }
342- </ span >
343- ) }
344- </ div >
345- ) ) }
346- </ pre >
333+ < div className = "relative rounded-md min-h-[300px] [&_pre]:m-0 [&_pre]:p-4 [&_pre]:text-sm [&_pre]:min-h-[300px] [&_pre]:rounded-md font-mono" >
334+ < div
335+ className = "overflow-hidden rounded-md"
336+ dangerouslySetInnerHTML = { { __html : html } }
337+ />
347338
348339 { showAutocomplete && (
349- < div className = "absolute left-20 top-10 bg-[#252526] border border-gray-600 rounded shadow-lg z-10 w-56" >
350- < div className = "text-xs text-gray-400 px-2 py-1 border-b border-gray-600 " >
340+ < div className = "absolute left-[88px] top-[52px] bg-[#252526] border border-[#454545] rounded shadow-lg z-10 w-56" >
341+ < div className = "text-xs text-[#858585] px-2 py-1 border-b border-[#454545] " >
351342 QueryRegistry
352343 </ div >
353344 { queryNames . map ( ( name , i ) => (
354345 < div
355346 key = { name }
356347 className = { `px-3 py-1 text-sm font-mono ${
357- i === 2 ? "bg-gray-700 text-white" : "text-gray-300 "
348+ i === 2 ? "bg-[#04395e] text-white" : "text-[#cccccc] "
358349 } `}
359350 >
360351 { name }
@@ -364,11 +355,11 @@ function IntelliSenseDemo() {
364355 ) }
365356
366357 { showParamHint && (
367- < div className = "absolute left-24 top-16 bg-[#252526] border border-gray-600 rounded shadow-lg z-10 w-60" >
368- < div className = "text-xs text-gray-400 px-2 py-1 border-b border-gray-600 " >
358+ < div className = "absolute left-[100px] top-[84px] bg-[#252526] border border-[#454545] rounded shadow-lg z-10 w-60" >
359+ < div className = "text-xs text-[#858585] px-2 py-1 border-b border-[#454545] " >
369360 Parameters (spend_data)
370361 </ div >
371- < div className = "p-2 text-sm font-mono text-gray-300 " >
362+ < div className = "p-2 text-sm font-mono text-[#cccccc] " >
372363 < div > groupBy: SQLStringMarker</ div >
373364 < div > startDate: SQLDateMarker</ div >
374365 < div > endDate: SQLDateMarker</ div >
@@ -377,16 +368,16 @@ function IntelliSenseDemo() {
377368 ) }
378369
379370 { showResultHint && (
380- < div className = "absolute left-56 bottom-10 bg-[#252526] border border-gray-600 rounded shadow-lg z-10 w-48" >
381- < div className = "text-xs text-gray-400 px-2 py-1 border-b border-gray-600 " >
371+ < div className = "absolute left-[220px] bottom-[24px] bg-[#252526] border border-[#454545] rounded shadow-lg z-10 w-48 overflow-hidden " >
372+ < div className = "text-xs text-[#858585] px-2 py-1 border-b border-[#454545] " >
382373 Result Fields
383374 </ div >
384375 { [ "group_key: string" , "period: string" , "cost_usd: number" ] . map (
385376 ( field , i ) => (
386377 < div
387378 key = { field }
388379 className = { `px-3 py-1 text-sm font-mono ${
389- i === 2 ? "bg-gray-700 text-white" : "text-gray-300 "
380+ i === 2 ? "bg-[#04395e] text-white" : "text-[#cccccc] "
390381 } `}
391382 >
392383 { field }
@@ -406,7 +397,7 @@ function IntelliSenseDemo() {
406397 { isPaused ? "Resume" : "Pause" }
407398 </ Button >
408399 ) }
409- < span className = "text-sm text-gray-500 " >
400+ < span className = "text-sm text-muted-foreground " >
410401 { isPaused && "(Paused) " }
411402 { step === 0 && "Click to start" }
412403 { step === 1 && "Query name autocomplete" }
@@ -421,8 +412,8 @@ function IntelliSenseDemo() {
421412
422413function TypeSafetyRoute ( ) {
423414 return (
424- < div className = "min-h-[calc(100vh-73px)] bg-gray-50 " >
425- < div className = "max-w-[1200px] mx-auto px-6 py-12" >
415+ < div className = "min-h-screen bg-background " >
416+ < div className = "max-w-6xl mx-auto px-6 py-12" >
426417 < Header
427418 title = "Type-Safe SQL Queries"
428419 description = "Generate TypeScript types from SQL files at build time with full IntelliSense support."
@@ -573,14 +564,11 @@ npx appkit-generate-types --no-cache`}
573564 } ,
574565 { annotation : "@param data BINARY" , helper : "sql.binary()" } ,
575566 ] . map ( ( type ) => (
576- < div
577- key = { type . annotation }
578- className = "p-3 bg-gray-100 rounded"
579- >
580- < code className = "text-xs text-gray-600 block" >
567+ < div key = { type . annotation } className = "p-3 bg-muted rounded" >
568+ < code className = "text-xs text-muted-foreground block" >
581569 -- { type . annotation }
582570 </ code >
583- < code className = "text-sm text-gray-900 font-medium" >
571+ < code className = "text-sm text-foreground font-medium" >
584572 { type . helper }
585573 </ code >
586574 </ div >
0 commit comments