Files
zeekay dc00ea93d0 rag_evaluation ui: tailwind + radix + shadcn out, @hanzo/ui in
This example shipped a live tailwind pipeline (tailwind.config.ts, a postcss
config running the tailwind plugin, @tailwind directives in globals.css), ten
@radix-ui packages, and fourteen vendored shadcn components. Tailwind classes
and radix primitives are DOM-only, so the example taught readers a pattern that
cannot run on iOS or Android — and examples propagate.

Everything now renders through @hanzo/ui on the @hanzo/gui backend, which
compiles to React Native. Utility strings became style props on View/XStack/
YStack/Text; the vendored ui/ directory is gone because @hanzo/ui already
exports every primitive it re-implemented, with matching variant names.

Tailwind and @hanzo/ui cannot coexist: @hanzo/ui ships plain CSS cascade layers
and tailwind's postcss plugin rejects `@layer base` without `@tailwind base`.
The pipeline had to come out for the library to load at all, which is why this
is a whole-app change rather than a partial one.

Also removed EvaluationForm.tsx — 273 lines of tailwind nothing imported.

Platform moves the conversion required: React 18 -> 19 and Next 14 -> 15 for
@hanzo/ui's peer range, react-native aliased to react-native-web for the web
bundle, and <Hanzo> mounted in the root layout to install the theme.

Three defects found by rendering it rather than trusting the build:
  - Tabs defaults to flexDirection row, so tab panels laid out beside the tab
    list and spilled outside the metric cards
  - TabsContent computes flex 1 1 0, which collapses to height 0 inside a
    content-sized column; it needs flexBasis auto there
  - CollapsibleTrigger has no asChild — it wraps children itself, so the claim
    rows rendered as empty boxes

Measured: 1465 tailwind utility tokens across 22 files -> 0; 10 radix packages
-> 0; 14 vendored shadcn files -> 0. next build green, tsc --noEmit clean,
every tab and the claim expand/collapse verified in a real browser with no
console errors.
2026-08-13 12:29:55 -07:00

96 lines
2.9 KiB
TypeScript

'use client'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { Anchor, Text, YStack } from '@hanzo/ui'
import type { ComponentProps, ReactNode } from 'react'
type MarkdownContentProps = ComponentProps<typeof YStack> & {
content: string
}
const heading = (fontSize: number, fontWeight: '500' | '600', marginTop: string) =>
function Heading({ children }: { children?: ReactNode }) {
return (
<Text fontSize={fontSize} fontWeight={fontWeight} marginTop={marginTop} marginBottom="$2">
{children}
</Text>
)
}
const body = ({ children }: { children?: ReactNode }) => (
<Text fontSize={14} color="$color11" marginBottom="$2">
{children}
</Text>
)
const listItem = ({ children }: { children?: ReactNode }) => (
<Text fontSize={14} color="$color11">
{'• '}
{children}
</Text>
)
export function MarkdownContent({ content, ...frame }: MarkdownContentProps) {
if (!content) return null
return (
<YStack {...frame}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
h1: heading(18, '600', '$4'),
h2: heading(16, '600', '$4'),
h3: heading(14, '600', '$3'),
h4: heading(14, '500', '$2'),
p: body,
ul: ({ children }) => (
<YStack paddingLeft="$4" gap="$1" marginBottom="$2">
{children}
</YStack>
),
ol: ({ children }) => (
<YStack paddingLeft="$4" gap="$1" marginBottom="$2">
{children}
</YStack>
),
li: listItem,
strong: ({ children }) => <Text fontWeight="600">{children}</Text>,
em: ({ children }) => (
<Text fontStyle="italic" color="$color11">
{children}
</Text>
),
code: ({ children }) => (
<Text backgroundColor="$color3" paddingHorizontal={6} paddingVertical={2} borderRadius="$2" fontSize={12} fontFamily="$mono">
{children}
</Text>
),
pre: ({ children }) => (
<YStack backgroundColor="$color3" padding="$3" borderRadius="$4" marginBottom="$2">
<Text fontSize={12} fontFamily="$mono">
{children}
</Text>
</YStack>
),
blockquote: ({ children }) => (
<YStack borderLeftWidth={2} borderLeftColor="$primary" paddingLeft="$3" marginBottom="$2">
<Text fontStyle="italic" color="$color11">
{children}
</Text>
</YStack>
),
hr: () => <YStack borderTopWidth={1} borderTopColor="$borderColor" marginVertical="$4" />,
a: ({ href, children }) => (
<Anchor href={href} target="_blank" rel="noopener noreferrer" color="$primary">
{children}
</Anchor>
),
}}
>
{content}
</ReactMarkdown>
</YStack>
)
}