mirror of
https://github.com/supabase/supabase.git
synced 2026-06-05 20:32:43 +08:00
This PR finishes the Tailwind migration by doing some minor fixes: - Remove `@radix-ui/colors` and inline the color values into the color definitions. The default Tailwind colors are unset and replaced by our own color set (both in light and dark variants). - Remove the `colorA` colors because they were used with alpha values. They were unused and Tailwind v4 supports alpha values natively. - Replace the `hit-area` JS config with the original CSS config from https://bazza.dev/craft/2026/hit-area. The original config was migrated to JS config to work with Tailwind v3. Now that we're on v4, we can just use the source format. - Remove the `motion-safe-transition` plugin since it's now [supported natively by Tailwind](https://tailwindcss.com/docs/transition-duration#supporting-reduced-motion) - Replace `tailwindcss-animate` with `tw-animate-css`. The old plugin was unmaintained and using JS config. The new one should be a drop-in replacement. - Remove all scripts for generating colors, they're not needed anymore, all values are hardcoded. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added hit-area debugging and sizing utilities for enhanced layout control. * **Refactor** * Restructured color system to use hand-edited CSS variables with inlined values for improved performance and maintainability. * Migrated animation utilities to a new framework. * **Style** * Enhanced motion-reduced animations with improved transition behavior. * Adjusted sidebar layout styling for better visual presentation. * **Chores** * Updated animation dependencies. * Removed legacy color generation scripts. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45925) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
122 lines
3.5 KiB
TypeScript
122 lines
3.5 KiB
TypeScript
'use client'
|
|
|
|
import { File } from 'lucide-react'
|
|
import { useState } from 'react'
|
|
import { flattenTree, TreeView, TreeViewItem } from 'ui'
|
|
import { CodeBlock } from 'ui-patterns/CodeBlock'
|
|
|
|
import { RegistryNode } from '@/lib/process-registry'
|
|
|
|
interface BlockItemCodeProps {
|
|
files: RegistryNode[]
|
|
}
|
|
|
|
interface TreeNode {
|
|
name: string
|
|
children: TreeNode[]
|
|
metadata: { path: string }
|
|
}
|
|
|
|
const flattenChildren = (files: RegistryNode[]): TreeNode[] => {
|
|
return files.map(
|
|
(node): TreeNode => ({
|
|
name: node.name,
|
|
children: node.children ? flattenChildren(node.children) : [],
|
|
metadata: { path: node.path },
|
|
})
|
|
)
|
|
}
|
|
|
|
const findFirstFile = (nodes: RegistryNode[]): RegistryNode | null => {
|
|
for (const node of nodes) {
|
|
if (node.type === 'file') {
|
|
return node
|
|
}
|
|
if (node.children) {
|
|
const foundFile = findFirstFile(node.children)
|
|
if (foundFile) {
|
|
return foundFile
|
|
}
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function BlockItemCode({ files }: BlockItemCodeProps) {
|
|
// Find the first file to select by default
|
|
const [selectedFile, setSelectedFile] = useState<RegistryNode | null>(findFirstFile(files))
|
|
const flattenedData = flattenTree({ name: '', children: flattenChildren(files) })
|
|
|
|
// Handle file selection from the TreeView
|
|
const handleNodeSelect = (element: any) => {
|
|
const findFileByPath = (nodes: RegistryNode[], path: string): RegistryNode | null => {
|
|
for (const node of nodes) {
|
|
if (node.path === path) {
|
|
return node
|
|
}
|
|
if (node.children) {
|
|
const found = findFileByPath(node.children, path)
|
|
if (found) {
|
|
return found
|
|
}
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
const filePath = element.metadata.path
|
|
const foundFile = findFileByPath(files, filePath)
|
|
|
|
if (foundFile?.type === 'directory') return
|
|
|
|
setSelectedFile(foundFile || null)
|
|
}
|
|
|
|
return (
|
|
<div className="flex mt-4 border rounded-lg overflow-hidden h-[652px] not-prose">
|
|
{/* File browser sidebar */}
|
|
<div className="w-64 py-2 border-r bg-muted/30 overflow-y-auto">
|
|
<TreeView
|
|
data={flattenedData}
|
|
aria-label="file browser"
|
|
className="w-full"
|
|
defaultExpandedIds={flattenedData.filter((n) => n.children?.length).map((n) => n.id)}
|
|
defaultSelectedIds={flattenedData
|
|
.filter((n) => n.metadata?.path === selectedFile?.path)
|
|
.map((n) => n.id)}
|
|
onNodeSelect={({ element }) => handleNodeSelect(element)}
|
|
nodeRenderer={({ element, isBranch, isExpanded, getNodeProps, level, isSelected }) => (
|
|
<TreeViewItem
|
|
{...getNodeProps()}
|
|
isExpanded={isExpanded}
|
|
isBranch={isBranch}
|
|
isSelected={isSelected}
|
|
level={level}
|
|
icon={<File strokeWidth={1.5} size={16} className="shrink-0" />}
|
|
name={element.name}
|
|
className="gap-1.5"
|
|
/>
|
|
)}
|
|
/>
|
|
</div>
|
|
|
|
{/* Code display area */}
|
|
{selectedFile?.content ? (
|
|
<CodeBlock
|
|
wrapperClassName="w-full"
|
|
className="h-full max-w-none w-full! flex-1 font-mono text-xs rounded-none border-none"
|
|
language="ts"
|
|
>
|
|
{selectedFile?.content}
|
|
</CodeBlock>
|
|
) : (
|
|
<div className="flex items-center justify-center h-full text-muted-foreground">
|
|
<div className="flex flex-col items-center gap-2">
|
|
<p>No file selected or file content unavailable</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|