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:
bilalgursen
2026-07-20 07:46:41 +03:00
parent 4c76bd9724
commit 87f265ec15
84 changed files with 16020 additions and 89 deletions

View 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.