@axzydev/axzy_ui_system 1.7.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/index.cjs +204 -107
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.cts +22 -5
  5. package/dist/index.d.ts +22 -5
  6. package/dist/index.js +200 -104
  7. package/dist/index.js.map +1 -1
  8. package/dist/layered.css +1 -1
  9. package/package.json +1 -1
  10. package/src/components/atoms/button/button.tsx +7 -0
  11. package/src/components/atoms/input/input.tsx +5 -0
  12. package/src/components/atoms/segmented-control/segmented-control.tsx +22 -5
  13. package/src/components/molecules/card/card.props.ts +12 -0
  14. package/src/components/molecules/card/card.tsx +52 -22
  15. package/src/components/molecules/chip-input/chip-input.tsx +2 -0
  16. package/src/components/molecules/multi-select/multi-select.tsx +2 -0
  17. package/src/components/molecules/tabs/tabs.tsx +22 -8
  18. package/src/components/organisms/page-header/page-header.tsx +22 -6
  19. package/src/components/organisms/sidebar/sidebar.tsx +8 -5
  20. package/src/components/organisms/topbar/topbar.props.ts +2 -0
  21. package/src/components/organisms/topbar/topbar.tsx +56 -34
  22. package/src/components/templates/layout/layout.tsx +3 -2
  23. package/src/components/theme-provider/themeProvider.props.ts +1 -1
  24. package/src/components/theme-provider/themeProvider.tsx +54 -1
  25. package/src/index.ts +4 -4
  26. package/src/json-renderer/catalog/axzyCatalog.ts +5 -0
  27. package/src/sandbox/axzyConfig.test.ts +4 -0
  28. package/src/sandbox/axzyConfig.ts +1 -1
  29. package/src/sandbox/i18n.ts +6 -0
  30. package/src/showcases/FeedbackShowcases.tsx +2 -1
  31. package/src/showcases/StructureShowcases.tsx +17 -2
  32. package/src/theme/theme-context.ts +10 -2
  33. package/src/theme/theme.ts +1 -1
  34. package/src/theme/theme.types.ts +2 -1
@@ -58,6 +58,6 @@ export interface ITThemeProviderProps {
58
58
  radius?: number;
59
59
  /** Global shadow strength level. `0` ⇒ no shadows, `1` ⇒ subtle, `2` ⇒ default current look, `3` ⇒ pronounced. Shadows are injected as `--shadow-*`/`.shadow-*` overrides so cards, dropdowns and dialogs follow the level. @default 2 (keeps current default when omitted) */
60
60
  shadow?: number;
61
- /** Visual language of the whole system. `"soft"` keeps the current look (floating cards, tinted shadows, glass sidebar/top bar). `"flat"` switches the app shell and surfaces to flat ones: hairline borders instead of shadows on `ITCard`, a plain `ITSidebar` (no glow, no accent bar, narrower), a plain `ITTopBar` (no shadow, initials avatar) and a compact `ITPageHeader` without the icon tile. It also sets `data-it-appearance` on `<html>` so app CSS can follow it. Combine it with `shadow` and `radius` to finish the look. @default "soft" */
61
+ /** Visual language of the whole system. `"soft"` keeps the current look (floating cards, tinted shadows, glass sidebar/top bar). `"flat"` switches the app shell and surfaces to flat ones: hairline borders instead of shadows on `ITCard`, a plain `ITSidebar` (no glow, no accent bar, narrower), a plain `ITTopBar` (no shadow, initials avatar) and a compact `ITPageHeader` without the icon tile. It also sets `data-it-appearance` on `<html>` so app CSS can follow it. `"bento"` gives a modern pastel dashboard: light-gray canvas, borderless white cards with a diffuse shadow and 24px radius, pill buttons and inputs, an ink-pill active item in `ITTopBar` and a neutral-pill one in `ITSidebar`, a large `ITPageHeader` title and pastel tiles through `ITCard` `tone`; an explicit `radius`/`shadow` prop wins over the bento defaults. Combine it with `shadow` and `radius` to finish the look. @default "soft" */
62
62
  appearance?: ITThemeAppearance;
63
63
  }
@@ -83,7 +83,7 @@ const PRESET_I18N_KEY: Record<string, string> = {
83
83
  // Contexto y hooks (useITTheme / useITThemeSafe) viven en @/theme/theme-context.
84
84
  // Re-exportados desde aquí para mantener compatibilidad de la API pública.
85
85
  // eslint-disable-next-line react-refresh/only-export-components
86
- export { useITTheme, useITThemeSafe, useITFlatAppearance } from "@/theme/theme-context";
86
+ export { useITTheme, useITThemeSafe, useITFlatAppearance, useITAppearance } from "@/theme/theme-context";
87
87
 
88
88
  const getNestedValue = (obj: any, path: string) => {
89
89
  return path.split(".").reduce((acc, part) => acc && acc[part], obj);
@@ -343,6 +343,59 @@ export default function ITThemeProvider({
343
343
  };
344
344
  }, [radius, shadow]);
345
345
 
346
+ // Tokens del lenguaje "bento": solo se inyectan con appearance="bento".
347
+ // Los componentes leen estos vars (con fallback al aspecto base), así que un
348
+ // `radius`/`shadow` explícito gana: en ese caso no se definen los vars de
349
+ // radio/sombra y los componentes caen a la escala global.
350
+ useLayoutEffect(() => {
351
+ const STYLE_ID = "it-theme-bento-tokens";
352
+ let tag = document.getElementById(STYLE_ID) as HTMLStyleElement | null;
353
+ if (appearance !== "bento") {
354
+ tag?.remove();
355
+ return;
356
+ }
357
+ if (!tag) {
358
+ tag = document.createElement("style");
359
+ tag.id = STYLE_ID;
360
+ document.head.appendChild(tag);
361
+ }
362
+ const hasRadius = typeof radius === "number" && isFinite(radius);
363
+ const hasShadow = shadowLevel(shadow) !== null;
364
+ const shapeLight = hasRadius
365
+ ? ""
366
+ : "--it-bento-card-radius:24px;--it-bento-pill-radius:9999px;--it-bento-field-radius:1rem;--it-input-radius:var(--it-bento-pill-radius);";
367
+ const shadowLight = hasShadow
368
+ ? ""
369
+ : "--it-bento-card-shadow:0 1px 2px rgba(16,24,40,.04),0 12px 32px -16px rgba(16,24,40,.10);--it-bento-card-shadow-hover:0 1px 2px rgba(16,24,40,.06),0 18px 40px -16px rgba(16,24,40,.18);";
370
+ const shadowDark = hasShadow
371
+ ? ""
372
+ : "--it-bento-card-shadow:0 1px 2px rgba(0,0,0,.4),0 12px 32px -16px rgba(0,0,0,.55);--it-bento-card-shadow-hover:0 1px 2px rgba(0,0,0,.5),0 18px 40px -16px rgba(0,0,0,.7);";
373
+ // El item activo del sidebar sigue los tokens bento (píldora neutra, texto tinta).
374
+ const navTokens =
375
+ "--it-sidebar-active-bg:var(--it-bento-nav-active-bg);--it-sidebar-active-color:var(--it-bento-nav-active-text);--it-sidebar-active-icon:var(--it-bento-nav-active-text);";
376
+ const light =
377
+ "--it-layout-bg:#f4f4f6;--it-card-bg:#ffffff;--it-bento-card-padding:1.5rem;" +
378
+ "--it-input-bg:#f1f5f9;--it-input-border:transparent;" +
379
+ "--it-input-focus-ring:0 0 0 2px color-mix(in srgb,var(--color-primary) 50%,transparent);" +
380
+ "--it-bento-control-bg:#f1f5f9;--it-bento-control-bg-hover:#e2e8f0;--it-bento-control-text:#475569;" +
381
+ "--it-bento-ink-bg:#0f172a;--it-bento-ink-text:#ffffff;" +
382
+ "--it-bento-nav-active-bg:#f1f5f9;--it-bento-nav-active-text:#0f172a;" + navTokens;
383
+ const dark =
384
+ "--it-layout-bg:#020617;--it-card-bg:#0f172a;" +
385
+ "--it-input-bg:#1e293b;--it-input-border:transparent;" +
386
+ "--it-bento-control-bg:#1e293b;--it-bento-control-bg-hover:#334155;--it-bento-control-text:#cbd5e1;" +
387
+ "--it-bento-ink-bg:#ffffff;--it-bento-ink-text:#0f172a;" +
388
+ "--it-bento-nav-active-bg:#1e293b;--it-bento-nav-active-text:#ffffff;" + navTokens;
389
+ const A = '[data-it-appearance="bento"]';
390
+ tag.textContent =
391
+ `:root${A}{${light}${shapeLight}${shadowLight}}` +
392
+ `:root${A}.dark,:root${A} .dark,:root${A} [data-theme="dark"]{${dark}${shadowDark}}` +
393
+ `:root${A} [data-theme="light"]{${light}${shadowLight}}`;
394
+ return () => {
395
+ tag?.remove();
396
+ };
397
+ }, [appearance, radius, shadow]);
398
+
346
399
  // Inyectar variables CSS en el :root al cambiar la paleta o tema resuelto
347
400
  useEffect(() => {
348
401
  const injectStyles = (obj: any, prefix = "") => {
package/src/index.ts CHANGED
@@ -171,7 +171,7 @@ import type { ITBadgetProps } from "./components/atoms/badget/badget.props";
171
171
  import type { ITBreadcrumbsProps, ITBreadcrumbItem } from "./components/molecules/breadcrumbs/breadcrumbs.props";
172
172
  import type { ITButtonProps } from "./components/atoms/button/button.props";
173
173
  import type { ITCalendarProps } from "./components/molecules/calendar/calendar.props";
174
- import type { ITCardProps } from "./components/molecules/card/card.props";
174
+ import type { ITCardProps, ITCardTone } from "./components/molecules/card/card.props";
175
175
  import type { ITCheckboxProps } from "./components/atoms/checkbox/checkbox.props";
176
176
  import type { ITChipProps } from "./components/atoms/chip/chip.props";
177
177
  import type { ITChipInputProps } from "./components/molecules/chip-input/chip-input.props";
@@ -232,7 +232,7 @@ import ITLoader from "./components/atoms/loader/loader";
232
232
  import type { LoaderProps as ITLoaderProps } from "./components/atoms/loader/loader.props";
233
233
  import ITStepper from "./components/molecules/stepper/stepper";
234
234
  import type { ITStepperProps } from "./components/molecules/stepper/stepper.props";
235
- import ITThemeProvider, { useITTheme, useITThemeSafe, useITFlatAppearance } from "./components/theme-provider/themeProvider";
235
+ import ITThemeProvider, { useITTheme, useITThemeSafe, useITFlatAppearance, useITAppearance } from "./components/theme-provider/themeProvider";
236
236
  import type { ITThemeProviderProps, ITThemePalette, ITThemeAppearance } from "./components/theme-provider/themeProvider.props";
237
237
  import ITTimePicker from "./components/molecules/time-picker/timePicker";
238
238
  import type { ITTimePickerProps } from "./components/molecules/time-picker/timePicker.props";
@@ -262,7 +262,7 @@ export {
262
262
  ITSearchTable,
263
263
  ITSegmentedControl, ITSidebar, ITSkeleton, ITSlideToggle, ITSlider, ITStack, ITStatCard, ITStepper, ITLineBarChart,
264
264
  ITTable, ITTabs, ITText, ITTextarea, ITTripleFilter, ITThemeProvider,
265
- useITTheme, useITThemeSafe, useITFlatAppearance, ITTimePicker, ITToast, ITWysiwyg,
265
+ useITTheme, useITThemeSafe, useITFlatAppearance, useITAppearance, ITTimePicker, ITToast, ITWysiwyg,
266
266
  UploadStatus, FileTypeEnum,
267
267
  getContrastTextColor, isLightColor, resolveCssColor,
268
268
  ITI18nProvider, useITTranslation, esMessages, enMessages,
@@ -288,7 +288,7 @@ export {
288
288
  ITAlertProps, ITAvatarProps, ITBadgetProps,
289
289
  ITBreadcrumbItem, ITBreadcrumbsProps, ITButtonProps,
290
290
  ITCalendarProps,
291
- ITCardProps, ITCheckboxProps, ITChipProps, ITChipInputProps, ITConfirmDialogProps,
291
+ ITCardProps, ITCardTone, ITCheckboxProps, ITChipProps, ITChipInputProps, ITConfirmDialogProps,
292
292
  ITDropdownMenuItem, ITDropdownMenuProps, ITFieldProps, ITMaskedInputProps, ITMultiSelectOption, ITMultiSelectProps,
293
293
  ITDataTableFetchParams, ITDataTableProps, ITDataTableResponse, ITDatePickerProps,
294
294
  ITDialogProps, ITDividerProps, ITDrawerProps,
@@ -91,6 +91,11 @@ export const AXZY_CATALOG_ENTRIES: CatalogEntry[] = [
91
91
  summary: "Tarjeta con título, imagen y contenido.",
92
92
  props: {
93
93
  title: { kind: "string" },
94
+ tone: {
95
+ kind: "enum",
96
+ values: ["primary", "secondary", "ternary", "success", "info", "warning", "danger"],
97
+ doc: "Tinte pastel de la tarjeta (token --color-<tone>-soft).",
98
+ },
94
99
  image: { kind: "string", doc: "URL de la imagen de cabecera." },
95
100
  alt: { kind: "string" },
96
101
  onClick: { kind: "action" },
@@ -16,6 +16,10 @@ describe("axzy.json", () => {
16
16
  expect(config.showFab).toBe(true);
17
17
  });
18
18
 
19
+ it("acepta la apariencia bento", () => {
20
+ expect(mergeAxzyConfig({ appearance: "bento" }).appearance).toBe("bento");
21
+ });
22
+
19
23
  it("recorta fuera de rango en vez de romper", () => {
20
24
  const config = mergeAxzyConfig({ density: 9, radius: 99, shadow: -3 });
21
25
  expect(config.density).toBe(1.5);
@@ -71,7 +71,7 @@ export function mergeAxzyConfig(raw: unknown): AxzyConfig {
71
71
  density: clamp(entrada.density, 0.5, 1.5, DEFAULT_AXZY_CONFIG.density),
72
72
  radius: clamp(entrada.radius, 0, 24, DEFAULT_AXZY_CONFIG.radius, 0),
73
73
  shadow: clamp(entrada.shadow, 0, 3, DEFAULT_AXZY_CONFIG.shadow, 0),
74
- appearance: entrada.appearance === "flat" || entrada.appearance === "soft" ? entrada.appearance : DEFAULT_AXZY_CONFIG.appearance,
74
+ appearance: entrada.appearance === "flat" || entrada.appearance === "soft" || entrada.appearance === "bento" ? entrada.appearance : DEFAULT_AXZY_CONFIG.appearance,
75
75
  showFab: typeof entrada.showFab === "boolean" ? entrada.showFab : DEFAULT_AXZY_CONFIG.showFab,
76
76
  };
77
77
  }
@@ -698,6 +698,9 @@ export const sandboxMessages: ITMessagesByLocale = {
698
698
  "Layouts de card listos para producción construidos con ITCard",
699
699
  "showcase.structure.patternCourseProgress": "Progreso del curso",
700
700
  "showcase.structure.patternPricing": "Plan de precios destacado",
701
+ "showcase.structure.cardToneTitle": "Tarjetas pastel (tone)",
702
+ "showcase.structure.cardToneSubtitle": "La prop tone tiñe el fondo con el token --color-<tone>-soft; funciona en soft, flat y bento.",
703
+ "showcase.structure.cardToneBody": "Fondo tintado con el token suave del color.",
701
704
  "showcase.structure.patternActivity": "Item de feed de actividad",
702
705
  "showcase.structure.patternTeamMember": "Perfil de miembro del equipo",
703
706
  "showcase.structure.textDesc":
@@ -1770,6 +1773,9 @@ export const sandboxMessages: ITMessagesByLocale = {
1770
1773
  "Production-ready card layouts built with ITCard",
1771
1774
  "showcase.structure.patternCourseProgress": "Course progress",
1772
1775
  "showcase.structure.patternPricing": "Featured pricing plan",
1776
+ "showcase.structure.cardToneTitle": "Pastel cards (tone)",
1777
+ "showcase.structure.cardToneSubtitle": "The tone prop tints the background with the --color-<tone>-soft token; it works in soft, flat and bento.",
1778
+ "showcase.structure.cardToneBody": "Background tinted with the soft color token.",
1773
1779
  "showcase.structure.patternActivity": "Activity feed item",
1774
1780
  "showcase.structure.patternTeamMember": "Team member profile",
1775
1781
  "showcase.structure.textDesc":
@@ -362,6 +362,7 @@ export const ThemeProviderShowcase = () => {
362
362
  '<ITThemeProvider><App /></ITThemeProvider>',
363
363
  '<ITThemeProvider theme={{ primary: "#3b82f6", layout: { sidebarBg: "#0f172a" } }} showFab={false}><App /></ITThemeProvider>',
364
364
  '<ITThemeProvider density={0.9} radius={8} shadow={1} appearance="flat"><App /></ITThemeProvider>',
365
+ '<ITThemeProvider appearance="bento"><App /></ITThemeProvider>',
365
366
  ],
366
367
  props: [
367
368
  { name: "theme", type: "Partial<ITThemePalette>", description: "Overrides de paleta fusionados (deep merge) con el tema por defecto: `primary`, `secondary`, `ternary`, `danger`, `success`, `info`, `alert`, `warning`, `layout` y `table`." },
@@ -370,7 +371,7 @@ export const ThemeProviderShowcase = () => {
370
371
  { name: "density", type: "number", default: "1", description: "Factor de densidad global: escala el `font-size` raíz para compactar todo lo basado en `rem`. Se limita a `0.5`–`1.5`." },
371
372
  { name: "radius", type: "number", default: "—", description: "Radio global en px aplicado a toda la escala `--radius-*`; `0` deja las esquinas totalmente cuadradas." },
372
373
  { name: "shadow", type: "number", default: "—", description: "Fuerza global de sombras: `0` ninguna, `1` sutiles, `2` look actual, `3` marcadas." },
373
- { name: "appearance", type: '"soft" | "flat"', default: '"soft"', description: "Lenguaje visual del sistema; `\"flat\"` usa superficies planas con bordes de 1 px y fija `data-it-appearance` en `<html>`." },
374
+ { name: "appearance", type: '"soft" | "flat" | "bento"', default: '"soft"', description: "Lenguaje visual del sistema; `\"flat\"` usa superficies planas con bordes de 1 px; `\"bento\"` usa lienzo gris claro, tarjetas blancas sin borde con sombra difusa y radio de 24 px, controles en píldora y navegación con píldora tinta. Fija `data-it-appearance` en `<html>`; un `radius`/`shadow` explícito gana sobre los valores bento." },
374
375
  ],
375
376
  notes: [
376
377
  "`useITTheme()` lanza error si se usa fuera del provider; `useITThemeSafe()` devuelve `undefined` en ese caso.",
@@ -372,6 +372,19 @@ export const CardShowcase = () => {
372
372
  }
373
373
  gallery={
374
374
  <ITStack spacing={8}>
375
+ <GallerySection
376
+ title={t("showcase.structure.cardToneTitle")}
377
+ subtitle={t("showcase.structure.cardToneSubtitle")}
378
+ >
379
+ <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
380
+ {(["primary", "secondary", "ternary", "success", "info", "warning", "danger"] as const).map((tone) => (
381
+ <ITCard key={tone} tone={tone} title={tone}>
382
+ {t("showcase.structure.cardToneBody")}
383
+ </ITCard>
384
+ ))}
385
+ </div>
386
+ </GallerySection>
387
+
375
388
  <GallerySection
376
389
  title={t("showcase.structure.galleryRealCases")}
377
390
  subtitle={t("showcase.structure.galleryCardsSubtitle")}
@@ -537,13 +550,14 @@ export const CardShowcase = () => {
537
550
  }
538
551
  doc={{
539
552
  summary: "Contenedor de tarjeta con imagen, título, cuerpo y pie de acciones opcionales; con onClick se vuelve interactivo.",
540
- description: "Pieza base de composición para agrupar contenido relacionado. Borde, radio y sombra se adaptan al aspecto del tema (flat / soft).",
553
+ description: "Pieza base de composición para agrupar contenido relacionado. Borde, radio y sombra se adaptan al aspecto del tema (soft / flat / bento).",
541
554
  examples: [
542
555
  '<ITCard title="Ingresos del mes" actions={<ITButton label="Ver detalle" size="sm" />}>$48.230</ITCard>',
543
556
  '<ITCard title="Curso" image="/courses/ts.jpg" imageClassName="h-32" onClick={() => open(course.id)}>…</ITCard>',
544
557
  '<ITCard className="max-w-sm"><ITText muted>Tarjeta estática, sin cabecera ni acciones.</ITText></ITCard>',
545
558
  ],
546
559
  props: [
560
+ { name: "tone", type: '"primary" | "secondary" | "ternary" | "success" | "info" | "warning" | "danger"', default: "—", description: "Tarjeta pastel: tiñe el fondo con el token --color-<tone>-soft (sustituye al blanco). En soft/flat usa --color-<tone>-soft-border como borde; en bento sigue sin borde." },
547
561
  { name: "onClick", type: "() => void", default: "—", description: "Al recibirlo la tarjeta se vuelve clicable: cursor pointer, transición de sombra y elevación en hover. Sin él es estática." },
548
562
  { name: "title", type: "string", default: "—", description: "Título de la cabecera; se renderiza como h3 mediante ITText." },
549
563
  { name: "image", type: "string", default: "—", description: "URL de la imagen superior, a ancho completo con h-48 object-cover." },
@@ -559,7 +573,8 @@ export const CardShowcase = () => {
559
573
  notes: [
560
574
  "El aspecto del tema decide borde y sombra: en flat el borde es un hairline y solo hay sombra en hover si la tarjeta es clicable; en soft flota con --shadow-sm y sube a --shadow-lg con translateY(-2px).",
561
575
  "Variables CSS: --it-card-bg, --it-card-border, --it-card-flat-border y --it-card-radius.",
562
- "El padding es fijo (cuerpo 1.25rem, pie 1rem): no hay prop de tamaño.",
576
+ "En bento la tarjeta no tiene borde, usa --it-bento-card-shadow (más marcada en hover si es clicable, sin translateY), radio de 24 px y padding de 1.5rem; un radius/shadow explícito en el provider gana.",
577
+ "El padding es fijo (cuerpo 1.25rem, 1.5rem en bento; pie 1rem): no hay prop de tamaño.",
563
578
  ],
564
579
  }}
565
580
  />
@@ -38,10 +38,18 @@ export const useITThemeSafe = (): ITThemeContextType | undefined => {
38
38
  return useContext(ITThemeContext);
39
39
  };
40
40
 
41
+ /**
42
+ * Lenguaje visual activo (`"soft"` | `"flat"` | `"bento"`).
43
+ * Fuera de un ITThemeProvider devuelve `"soft"` (aspecto por defecto).
44
+ */
45
+ export const useITAppearance = (): ITThemeAppearance => {
46
+ return useContext(ITThemeContext)?.appearance ?? "soft";
47
+ };
48
+
41
49
  /**
42
50
  * `true` cuando el provider pide el lenguaje visual plano (`appearance="flat"`).
43
51
  * Fuera de un ITThemeProvider devuelve `false` (aspecto por defecto).
44
52
  */
45
53
  export const useITFlatAppearance = (): boolean => {
46
- return useContext(ITThemeContext)?.appearance === "flat";
47
- };
54
+ return useITAppearance() === "flat";
55
+ };
@@ -322,7 +322,7 @@ export const components = {
322
322
  input: {
323
323
  backgroundColor: 'var(--it-input-bg, #ffffff)',
324
324
  borderColor: `var(--it-input-border, ${semanticColors.gray[300]})`,
325
- borderRadius: 'var(--radius-md)',
325
+ borderRadius: 'var(--it-input-radius, var(--radius-md))',
326
326
  focus: {
327
327
  borderColor: `var(--it-input-focus-border, ${semanticColors.primary[500]})`,
328
328
  ring: `var(--it-input-focus-ring, 0 0 0 3px ${semanticColors.primary[100]})`,
@@ -16,8 +16,9 @@ export type ColorScale = {
16
16
  * Visual language of the whole system.
17
17
  * - `"soft"`: soft depth — floating cards, tinted shadows, glass sidebar and top bar (default).
18
18
  * - `"flat"`: flat surfaces — hairline borders instead of shadows, plain sidebar and top bar, compact page headers.
19
+ * - `"bento"`: modern pastel "bento" dashboards — light-gray canvas, borderless white cards with a diffuse shadow and 24px radius, pill controls (buttons, inputs), ink-pill navigation and pastel tiles via `ITCard` `tone`.
19
20
  */
20
- export type ITThemeAppearance = "soft" | "flat";
21
+ export type ITThemeAppearance = "soft" | "flat" | "bento";
21
22
 
22
23
  export interface ITThemePalette {
23
24
  /** Main brand accent color (hex). Drives primary buttons, active nav items, focus rings, links, and the `--color-primary` CSS variable. @default "#06b6d4" */