Build TercihAI MVP: landing page, YÖK Atlas data pipeline, rank-based results
- Add product vision/market research doc (VISION.md) - Set up shadcn/ui (radix + nova preset) with blue/orange theme, Outfit + Work Sans fonts - Landing page: hero with rank input, problem/steps sections, comparison table, FAQ - Data pipeline: CSV archive ingest (2021-2024) + live YÖK Atlas API refresh (2025) into SQLite (npm run ingest / refresh); zeros normalized to NULL - /sonuc page: hayal/dengeli/garanti buckets by COALESCE(sira2025, sira2024), score-type switcher, 2024→2025 trend indicators - Add ui-ux-pro-max and shadcn agent skills, shadcn MCP config, launch.json Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
110
.agents/skills/migrate-radix-to-base/wrapper-shapes.md
Normal file
110
.agents/skills/migrate-radix-to-base/wrapper-shapes.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Target wrapper shapes (golden-derived specifics)
|
||||
|
||||
Facts learned by diffing hand migrations against the shadcn base registry
|
||||
wrappers. These close gaps the mapping tables cannot express: exact classes,
|
||||
defaults, and composition shapes. When migrating shadcn-style wrappers,
|
||||
prefer these shapes.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Positioner parts get NO `data-slot` attribute; keep data-slot on the parts
|
||||
the radix wrapper already had.
|
||||
- Menu-family Positioner: `className="isolate z-50 outline-none"`; the Popup
|
||||
KEEPS `z-50` and `outline-none` too. Tooltip: Popup keeps `z-50`,
|
||||
Positioner gets `isolate z-50`. Select: `isolate z-50` lives on the Popup,
|
||||
Positioner gets no class.
|
||||
- The base registry adds `cn-<comp>-content-logical` (and for tooltip also
|
||||
`cn-tooltip-arrow-logical`) companion classes next to the existing
|
||||
`cn-<comp>-content` hooks on popover, tooltip, hover-card, dropdown,
|
||||
context-menu, select, menubar popups. Add them when the source uses cn-*
|
||||
hooks; skip for plain-Tailwind projects.
|
||||
|
||||
## Button
|
||||
|
||||
Base UI HAS a Button primitive: `import { Button as ButtonPrimitive } from
|
||||
"@base-ui/react/button"`. A shadcn button.tsx with the Slot/asChild idiom
|
||||
migrates to `<ButtonPrimitive>` directly (which supports `render`), NOT to a
|
||||
hand-rolled useRender wrapper. Reserve useRender + mergeProps for
|
||||
non-button polymorphic components (breadcrumb link, marker).
|
||||
|
||||
## Tooltip Arrow (literal classes)
|
||||
|
||||
```tsx
|
||||
<TooltipPrimitive.Arrow
|
||||
className={cn(
|
||||
"cn-tooltip-arrow cn-tooltip-arrow-logical",
|
||||
"data-[side=bottom]:top-1 data-[side=left]:right-[-13px] data-[side=left]:top-1/2! data-[side=left]:-translate-y-1/2 data-[side=right]:left-[-13px] data-[side=right]:top-1/2! data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5",
|
||||
className
|
||||
)}
|
||||
/>
|
||||
```
|
||||
|
||||
Verify against the current base registry tooltip before relying on the exact
|
||||
pixel values; the shape (per-side offsets + translate, no rotation) is the
|
||||
stable part. Golden default: `alignOffset = 0`, `sideOffset = 4`.
|
||||
|
||||
## DropdownMenu / ContextMenu SubContent
|
||||
|
||||
Compose the PUBLIC Content wrapper, do not rebuild from primitives:
|
||||
|
||||
```tsx
|
||||
function DropdownMenuSubContent(props) {
|
||||
return (
|
||||
<DropdownMenuContent
|
||||
align="start"
|
||||
alignOffset={-3}
|
||||
side="right"
|
||||
sideOffset={0}
|
||||
className={cn("w-auto", props.className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
The `-3` / `0` defaults are load-bearing (visual alignment with the parent
|
||||
menu). NOTE: the live registry shapes SubContent differently per menu:
|
||||
context-menu is a true minimal compose (as above), while dropdown-menu's
|
||||
SubContent duplicates the full content class list (including translucent menu
|
||||
styling) rather than composing. When a golden pair exists, copy the golden
|
||||
shape; this example is the fallback.
|
||||
|
||||
DANGER — do not confuse SubContent defaults with main-Content defaults. The
|
||||
values above are ONLY for the *submenu* wrappers (DropdownMenuSubContent /
|
||||
ContextMenuSubContent). The MAIN ContextMenuContent (the pointer-anchored
|
||||
right-click menu) keeps its own positioning — do NOT apply
|
||||
`side="right"`/`alignOffset` to it, or every right-click menu mispositions.
|
||||
- ContextMenu SUBContent defaults: `align="start" alignOffset={4} side="right" sideOffset={0}`.
|
||||
- DropdownMenu SUBContent defaults: `align="start" alignOffset={-3} side="right" sideOffset={0}`.
|
||||
- Main Content (either): keep the wrapper's existing align/sideOffset; do not add a side.
|
||||
|
||||
## SubTrigger open styling
|
||||
|
||||
Base wrappers ADD `data-popup-open:bg-accent
|
||||
data-popup-open:text-accent-foreground` to SubTrigger (no radix equivalent
|
||||
class existed; the open styling was previously data-[state=open]).
|
||||
|
||||
## Select
|
||||
|
||||
- Bare re-export: `const Select = SelectPrimitive.Root` (no wrapper function,
|
||||
no data-slot on Root). `SelectPrimitive.Root.Props` is GENERIC
|
||||
(<Value, Multiple>), which breaks the usual ComponentProps pattern; the
|
||||
bare re-export sidesteps it.
|
||||
- Drop the radix `position` prop entirely; expose `alignItemWithTrigger`
|
||||
(default true) picked from Positioner.Props, `sideOffset = 4`.
|
||||
- Item anatomy: `ItemText` FIRST with `cn-select-item-text shrink-0
|
||||
whitespace-nowrap`, then `ItemIndicator render={<span
|
||||
className="cn-select-item-indicator" />}`.
|
||||
- Scroll arrows get `top-0 w-full` / `bottom-0 w-full`; List has no classes.
|
||||
|
||||
## Accordion animation placement
|
||||
|
||||
`h-(--accordion-panel-height)`, `data-starting-style:h-0`, and
|
||||
`data-ending-style:h-0` all go on the INNER div of the Panel (the element
|
||||
that previously carried the radix height animation), not on the Panel itself.
|
||||
|
||||
## Tabs
|
||||
|
||||
The base registry accepts Base UI's manual-activation default (no
|
||||
`activateOnFocus`), and does not forward `orientation` beyond what the radix
|
||||
wrapper did. Match it: flag the behavior delta, do not patch it.
|
||||
Reference in New Issue
Block a user