SPB Git forge

spb/ka-ui

Public
30commits 1branches 0releases
145.7 MBsize
maindefault branch
27 days agolast push
Python 33.5% JavaScript 30.1% TypeScript 25% CSS 10% Shell 1.4%
5.1 KB · 206 lines tsx
Raw Blame History
1// KA Tabbar v1 — canonique ka-ui.git/nav/KaTabbar.tsx2// Barre de navigation mobile commune Groupe KA (voir TABBAR-STANDARD.md).3// Copier dans src/ka/ avec ka-tabbar.css. Apps react-router uniquement ;4// pour Next.js (vrai-prix), adapter Link/usePathname — voir le standard.5import type { CSSProperties, ReactElement } from "react";6import { Link } from "react-router-dom";7import "./ka-tabbar.css";89export type KaTabIcon =10  | "compass" | "search" | "heart" | "user" | "map" | "pin" | "tag"11  | "home" | "grid" | "store" | "basket" | "target" | "trendup"12  | "receipt" | "book" | "chart" | "calendar";1314const ICONS: Record<KaTabIcon, ReactElement> = {15  compass: (16    <>17      <circle cx="12" cy="12" r="9" />18      <path d="m15.5 8.5-2.2 5-4.8 2 2.2-5 4.8-2z" />19    </>20  ),21  search: (22    <>23      <circle cx="11" cy="11" r="7" />24      <path d="m20.5 20.5-4.2-4.2" />25    </>26  ),27  heart: (28    <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" />29  ),30  user: (31    <>32      <circle cx="12" cy="8.2" r="3.7" />33      <path d="M4.5 20.2a7.5 7.5 0 0 1 15 0" />34    </>35  ),36  map: (37    <>38      <path d="M9 4 3.5 6v14L9 18l6 2 5.5-2V4L15 6 9 4z" />39      <path d="M9 4v14M15 6v14" />40    </>41  ),42  pin: (43    <>44      <path d="M12 21s-7-5.6-7-11a7 7 0 0 1 14 0c0 5.4-7 11-7 11z" />45      <circle cx="12" cy="10" r="2.6" />46    </>47  ),48  tag: (49    <>50      <path d="M20.6 13.4 12 22 2 12V2h10l8.6 8.6a2 2 0 0 1 0 2.8z" />51      <circle cx="7" cy="7" r="1.6" />52    </>53  ),54  home: (55    <>56      <path d="m3.5 10.5 8.5-7 8.5 7" />57      <path d="M5.5 9v11h13V9" />58    </>59  ),60  grid: (61    <>62      <rect x="4" y="4" width="7" height="7" rx="1.5" />63      <rect x="13" y="4" width="7" height="7" rx="1.5" />64      <rect x="4" y="13" width="7" height="7" rx="1.5" />65      <rect x="13" y="13" width="7" height="7" rx="1.5" />66    </>67  ),68  store: (69    <>70      <path d="M4.5 9.5 6 4.5h12l1.5 5" />71      <path d="M5 9.5h14V20H5V9.5z" />72      <path d="M10 20v-5h4v5" />73    </>74  ),75  basket: (76    <>77      <path d="M4 9h16l-1.6 10a2 2 0 0 1-2 1.7H7.6a2 2 0 0 1-2-1.7L4 9z" />78      <path d="M8.5 9 12 3l3.5 6" />79    </>80  ),81  target: (82    <>83      <circle cx="12" cy="12" r="8.5" />84      <circle cx="12" cy="12" r="4.5" />85      <circle cx="12" cy="12" r="0.8" />86    </>87  ),88  trendup: (89    <>90      <path d="m3.5 16.5 5.5-5.5 3.5 3.5 7.5-7.5" />91      <path d="M14.5 7H20v5.5" />92    </>93  ),94  receipt: (95    <>96      <path d="M6 3.5h12V21l-2-1.4-2 1.4-2-1.4-2 1.4-2-1.4L6 21V3.5z" />97      <path d="M9 8h6M9 11.5h6M9 15h4" />98    </>99  ),100  book: (101    <>102      <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" />103      <path d="M12 6.5V21" />104    </>105  ),106  chart: (107    <>108      <path d="M4 20h16" />109      <path d="M7.5 20v-6M12 20V9M16.5 20v-4" />110    </>111  ),112  calendar: (113    <>114      <rect x="3.5" y="5" width="17" height="15.5" rx="2" />115      <path d="M8 3v4M16 3v4M3.5 10h17" />116    </>117  ),118};119120export function KaTabIco({ name, size = 21 }: { name: KaTabIcon; size?: number }) {121  return (122    <svg123      width={size}124      height={size}125      viewBox="0 0 24 24"126      fill="none"127      stroke="currentColor"128      strokeWidth={1.7}129      strokeLinecap="round"130      strokeLinejoin="round"131      aria-hidden="true"132    >133      {ICONS[name]}134    </svg>135  );136}137138export type KaTab = {139  label: string;140  icon: KaTabIcon;141  /** route interne (react-router Link) */142  to?: string;143  /** lien externe (ex. hub univers KA) */144  href?: string;145  /** action locale (ex. ouvrir la recherche) — rend un <button> */146  onPress?: () => void;147  /** complément d'un lien `to` (ex. focus d'un champ une fois arrivé) */148  onClick?: () => void;149  active?: boolean;150};151152export default function KaTabbar({153  tabs,154  theme = "light",155  accent,156  className,157}: {158  tabs: KaTab[];159  theme?: "light" | "dark";160  /** couleur signature de la marque (défaut : var(--accent) du site) */161  accent?: string;162  className?: string;163}) {164  const cls =165    "ka-tabbar" +166    (theme === "dark" ? " ka-tabbar--dark" : "") +167    (className ? " " + className : "");168  const style = accent ? ({ "--ktb-accent": accent } as CSSProperties) : undefined;169  return (170    <nav className={cls} style={style} aria-label="Navigation mobile">171      {tabs.map((t) => {172        const inner = (173          <>174            <KaTabIco name={t.icon} />175            {t.label}176          </>177        );178        const c = t.active ? "active" : "";179        if (t.to)180          return (181            <Link182              key={t.label}183              to={t.to}184              className={c}185              onClick={t.onClick}186              aria-current={t.active ? "page" : undefined}187            >188              {inner}189            </Link>190          );191        if (t.href)192          return (193            <a key={t.label} href={t.href} className={c} target="_blank" rel="noreferrer">194              {inner}195            </a>196          );197        return (198          <button key={t.label} type="button" className={c} onClick={t.onPress}>199            {inner}200          </button>201        );202      })}203    </nav>204  );205}206