mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
Radix was leaking out of the primitive layer into application code. Thirty dialog components under apps/remix imported `@radix-ui/react-dialog` purely to spell `Omit<DialogPrimitive.DialogProps, 'children'>`, and two more imported `TooltipArrow` directly. Each of those is a place the UI substrate has to be swapped when it changes, for no gain — the app never touched Radix behaviour, only a type and one arrow element. `packages/ui/primitives/dialog.tsx` now exports `DialogProps` and `tooltip.tsx` exports `TooltipArrow`, so callers name the primitive, not the library behind it. Radix imports outside packages/ui: 32 -> 0. Eleven vendored shadcn primitives had no importers at all — aspect-ratio, auto-sized-text, calendar, collapsible, context-menu, menubar, navigation-menu, slider, toggle, a stray document-flow dialog and a signature-pad Canvas class shadowed by skia-canvas. Dead component code reads as supported API in review, so it is deleted rather than carried. That retires eight Radix packages plus react-day-picker from packages/ui and @radix-ui/react-tabs from apps/docs, which was declared and never imported: 28 declared Radix packages -> 19. The embedding doc taught Tailwind classes in a snippet third parties copy into their own apps; it now uses the same inline styles as the plain-HTML example directly above it. `.cursorrules` told every AI touching this repo to write "Shadcn UI, Radix, and Tailwind Aria" — it now points at @hanzo/gui and says the inherited layer is to be replaced, not extended. Verified: apps/remix typecheck 0 errors, client+server build green, prisma 38/38.
83 lines
3.6 KiB
Plaintext
83 lines
3.6 KiB
Plaintext
You are an expert in TypeScript, Node.js, Remix, React and @hanzo/gui.
|
|
|
|
Code Style and Structure:
|
|
|
|
- Write concise, technical TypeScript code with accurate examples
|
|
- Use functional and declarative programming patterns; avoid classes
|
|
- Prefer iteration and modularization over code duplication
|
|
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
|
|
- Structure files: exported component, subcomponents, helpers, static content, types
|
|
|
|
Naming Conventions:
|
|
|
|
- Use lowercase with dashes for directories (e.g., components/auth-wizard)
|
|
- Favor named exports for components
|
|
|
|
TypeScript Usage:
|
|
|
|
- Use TypeScript for all code; prefer types over interfaces
|
|
- Use functional components with TypeScript interfaces
|
|
|
|
Syntax and Formatting:
|
|
|
|
- Create functions using `const fn = () => {}`
|
|
- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements
|
|
- Use declarative JSX
|
|
- Never use 'use client'
|
|
- Never use 1 line if statements
|
|
|
|
Error Handling and Validation:
|
|
|
|
- Prioritize error handling: handle errors and edge cases early
|
|
- Use early returns and guard clauses
|
|
- Implement proper error logging and user-friendly messages
|
|
- Use Zod for form validation
|
|
- Model expected errors as return values in Server Actions
|
|
- Use error boundaries for unexpected errors
|
|
|
|
UI and Styling:
|
|
|
|
- @hanzo/gui is the only UI framework. It compiles to React Native, so the same
|
|
components run on web, iOS and Android. Do not add Tailwind classes, Radix
|
|
primitives, shadcn copies or any other UI library — each of those is DOM-only
|
|
and caps the app at the browser.
|
|
- Express layout and appearance as style props on @hanzo/ui / @hanzo/gui
|
|
components, never as class strings.
|
|
- packages/ui still carries a shadcn/Radix/Tailwind layer inherited from
|
|
upstream. It is being replaced, not extended: reuse what is there, add nothing
|
|
new to it.
|
|
- When using Lucide icons, prefer the longhand names, for example HomeIcon instead of Home
|
|
|
|
React forms
|
|
|
|
- Use zod for form validation react-hook-form for forms
|
|
- Look at TeamCreateDialog.tsx as an example of form usage
|
|
- Use <Form> <FormItem> elements, and also wrap the contents of form in a fieldset which should have the :disabled attribute when the form is loading
|
|
|
|
TRPC Specifics
|
|
|
|
- Every route should be in it's own file, example routers/teams/create-team.ts
|
|
- Every route should have a types file associated with it, example routers/teams/create-team.types.ts. These files should have the OpenAPI meta, and request/response zod schemas
|
|
- The request/response schemas should be named like Z[RouteName]RequestSchema and Z[RouteName]ResponseSchema
|
|
- Use create-team.ts and create-team.types.ts as an example when creating new routes.
|
|
- When creating the OpenAPI meta, only use GET and POST requests, do not use any other REST methods
|
|
- Deconstruct the input argument on it's one line of code.
|
|
|
|
Toast usage
|
|
|
|
- Use the t`string` macro from @lingui/react/macro to display toast messages
|
|
|
|
Remix/ReactRouter Usage
|
|
|
|
- Use (params: Route.Params) to get the params from the route
|
|
- Use (loaderData: Route.LoaderData) to get the loader data from the route
|
|
- When using loaderdata, deconstruct the data you need from the loader data inside the function body
|
|
- Do not use json() to return data, directly return the data
|
|
|
|
Translations
|
|
|
|
- Use <Trans>string</Trans> to display translations in jsx code, this should be imported from @lingui/react/macro
|
|
- Use the t`string` macro from @lingui/react/macro to display translations in typescript code
|
|
- t should be imported as const { t } = useLingui() where useLingui is imported from @lingui/react/macro
|
|
- String in constants should be using the t`string` macro
|