Vrai-Prix — l'évaluation du vrai prix des propriétés résidentielles au Québec.
TypeScript 90.2%
JavaScript 3.5%
Python 3.4%
CSS 1.9%
HTML 0.6%
1"use client";2// KA Tabbar v1 — variante Next.js du canonique ka-ui.git/nav/KaTabbar.tsx3// (Link next/link ; le CSS global ka-tabbar.css est importé par layout.tsx).4import type { CSSProperties, ReactElement } from "react";5import Link from "next/link";67export type KaTabIcon =8 | "compass" | "search" | "heart" | "user" | "map" | "pin" | "tag"9 | "home" | "grid" | "store" | "basket" | "target" | "trendup"10 | "receipt" | "book" | "chart" | "calendar";1112const ICONS: Record<KaTabIcon, ReactElement> = {13 compass: (14 <>15 <circle cx="12" cy="12" r="9" />16 <path d="m15.5 8.5-2.2 5-4.8 2 2.2-5 4.8-2z" />17 </>18 ),19 search: (20 <>21 <circle cx="11" cy="11" r="7" />22 <path d="m20.5 20.5-4.2-4.2" />23 </>24 ),25 heart: (26 <path d="M12 20.5S4.5 15.8 2.6 11.4A5.3 5.3 0 0 1 12 6.6a5.3 5.3 0 0 1 9.4 4.8C19.5 15.8 12 20.5 12 20.5z" />27 ),28 user: (29 <>30 <circle cx="12" cy="8.2" r="3.7" />31 <path d="M4.5 20.2a7.5 7.5 0 0 1 15 0" />32 </>33 ),34 map: (35 <>36 <path d="M9 4 3.5 6v14L9 18l6 2 5.5-2V4L15 6 9 4z" />37 <path d="M9 4v14M15 6v14" />38 </>39 ),40 pin: (41 <>42 <path d="M12 21s-7-5.6-7-11a7 7 0 0 1 14 0c0 5.4-7 11-7 11z" />43 <circle cx="12" cy="10" r="2.6" />44 </>45 ),46 tag: (47 <>48 <path d="M20.6 13.4 12 22 2 12V2h10l8.6 8.6a2 2 0 0 1 0 2.8z" />49 <circle cx="7" cy="7" r="1.6" />50 </>51 ),52 home: (53 <>54 <path d="m3.5 10.5 8.5-7 8.5 7" />55 <path d="M5.5 9v11h13V9" />56 </>57 ),58 grid: (59 <>60 <rect x="4" y="4" width="7" height="7" rx="1.5" />61 <rect x="13" y="4" width="7" height="7" rx="1.5" />62 <rect x="4" y="13" width="7" height="7" rx="1.5" />63 <rect x="13" y="13" width="7" height="7" rx="1.5" />64 </>65 ),66 store: (67 <>68 <path d="M4.5 9.5 6 4.5h12l1.5 5" />69 <path d="M5 9.5h14V20H5V9.5z" />70 <path d="M10 20v-5h4v5" />71 </>72 ),73 basket: (74 <>75 <path d="M4 9h16l-1.6 10a2 2 0 0 1-2 1.7H7.6a2 2 0 0 1-2-1.7L4 9z" />76 <path d="M8.5 9 12 3l3.5 6" />77 </>78 ),79 target: (80 <>81 <circle cx="12" cy="12" r="8.5" />82 <circle cx="12" cy="12" r="4.5" />83 <circle cx="12" cy="12" r="0.8" />84 </>85 ),86 trendup: (87 <>88 <path d="m3.5 16.5 5.5-5.5 3.5 3.5 7.5-7.5" />89 <path d="M14.5 7H20v5.5" />90 </>91 ),92 receipt: (93 <>94 <path d="M6 3.5h12V21l-2-1.4-2 1.4-2-1.4-2 1.4-2-1.4L6 21V3.5z" />95 <path d="M9 8h6M9 11.5h6M9 15h4" />96 </>97 ),98 book: (99 <>100 <path d="M12 6.5C10.5 5 8.5 4.5 5.5 4.5H3.5V19h2c3 0 5 .5 6.5 2 1.5-1.5 3.5-2 6.5-2h2V4.5h-2c-3 0-5 .5-6.5 2z" />101 <path d="M12 6.5V21" />102 </>103 ),104 chart: (105 <>106 <path d="M4 20h16" />107 <path d="M7.5 20v-6M12 20V9M16.5 20v-4" />108 </>109 ),110 calendar: (111 <>112 <rect x="3.5" y="5" width="17" height="15.5" rx="2" />113 <path d="M8 3v4M16 3v4M3.5 10h17" />114 </>115 ),116};117118export function KaTabIco({ name, size = 21 }: { name: KaTabIcon; size?: number }) {119 return (120 <svg121 width={size}122 height={size}123 viewBox="0 0 24 24"124 fill="none"125 stroke="currentColor"126 strokeWidth={1.7}127 strokeLinecap="round"128 strokeLinejoin="round"129 aria-hidden="true"130 >131 {ICONS[name]}132 </svg>133 );134}135136export type KaTab = {137 label: string;138 icon: KaTabIcon;139 /** route interne (react-router Link) */140 to?: string;141 /** lien externe (ex. hub univers KA) */142 href?: string;143 /** action locale (ex. ouvrir la recherche) — rend un <button> */144 onPress?: () => void;145 /** complément d'un lien `to` (ex. focus d'un champ une fois arrivé) */146 onClick?: () => void;147 active?: boolean;148};149150export default function KaTabbar({151 tabs,152 theme = "light",153 accent,154 className,155}: {156 tabs: KaTab[];157 theme?: "light" | "dark";158 /** couleur signature de la marque (défaut : var(--accent) du site) */159 accent?: string;160 className?: string;161}) {162 const cls =163 "ka-tabbar" +164 (theme === "dark" ? " ka-tabbar--dark" : "") +165 (className ? " " + className : "");166 const style = accent ? ({ "--ktb-accent": accent } as CSSProperties) : undefined;167 return (168 <nav className={cls} style={style} aria-label="Navigation mobile">169 {tabs.map((t) => {170 const inner = (171 <>172 <KaTabIco name={t.icon} />173 {t.label}174 </>175 );176 const c = t.active ? "active" : "";177 if (t.to)178 return (179 <Link180 key={t.label}181 href={t.to}182 className={c}183 onClick={t.onClick}184 aria-current={t.active ? "page" : undefined}185 >186 {inner}187 </Link>188 );189 if (t.href)190 return (191 <a key={t.label} href={t.href} className={c} target="_blank" rel="noreferrer">192 {inner}193 </a>194 );195 return (196 <button key={t.label} type="button" className={c} onClick={t.onPress}>197 {inner}198 </button>199 );200 })}201 </nav>202 );203}204