@studiolxd/brand 49.22.0 → 49.23.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,30 @@ El paquete sigue [semver](https://semver.org/lang/es/): **patch** para bug fixes
7
7
  regeneración de `dist`, **minor** para componentes/props/variantes/tokens nuevos, **major**
8
8
  para breaking changes.
9
9
 
10
+ ## [49.23.0] — 2026-10-04
11
+
12
+ > **Minor.** Ranura `logo` en `AppHeader`, a petición de Homenize. Espacio nuevo `appHeader` en
13
+ > `BrandMessages` (una clave, `logo`): el catálogo de cada app tiene que añadirla para compilar.
14
+
15
+ ### Logo en la cabecera de la aplicación
16
+
17
+ - **`logo`**: la marca del producto entre el botón de menú y `start`. Toma el alto de contenido de la
18
+ barra (`--app-header-content-height`, 40px) y el ancho de su proporción: el `Logo` del sistema a
19
+ cualquier talla, un SVG con `viewBox` o un `<img>` de cualquier proporción, sin darle medidas. Sin
20
+ `logo`, la barra queda exactamente igual que antes.
21
+ - **`logoHref`** (por defecto `/`) y **`renderLogoLink`** para el router del producto, con el mismo
22
+ contrato que `SiteHeader`: recibe `href`, `className`, `aria-label` y `children`. Tipo nuevo
23
+ exportado: `AppHeaderLogoLinkProps`.
24
+ - **`logoLabel`**, o sin él **`appHeader.logo`** del `BrandMessagesProvider` («Homenize, ir al
25
+ inicio»), como `siteHeader.logo`. Solo se lee con `logo`. Tipo nuevo: `AppHeaderMessages`.
26
+ - **Una marca a la vez con el `Sidebar`.** La cabecera está siempre a la vista, encima de la columna y
27
+ del cajón, así que el `logo` va en uno solo —mejor en la cabecera, que se ve también en rail y con la
28
+ sidebar cerrada—. Si llegan los dos, dentro de un `AppShell` manda el de la cabecera: el armazón
29
+ oculta `.sidebar__header` mientras el `AppHeader` lleve `logo` (`:has`, sin JS, sin parpadeo en SSR).
30
+ - Stories: `AppHeader` «Con logo», «Con una marca de producto», «Con logo (móvil)»; `AppShell` «Con logo
31
+ en la cabecera». Tests de story (orden, enlace, 40px de alto con `Logo xxl`, imagen 4:1 a 160×40, sin
32
+ logo nada cambia, sidebar sin marca) y unitarios (`AppHeader.test.tsx`).
33
+
10
34
  ## [49.22.0] — 2026-10-04
11
35
 
12
36
  > **Minor.** Muestra y selector de color: `ColorSwatch`, `ColorPicker` y `ColorPickerField`, sin
@@ -36,6 +36,7 @@ import type { NotificationPanelMessages } from '../molecules/NotificationPanel/N
36
36
  import type { MenuButtonMessages } from '../atoms/MenuButton/MenuButton';
37
37
  import type { AppRootMessages } from '../sections/AppRoot/AppRoot';
38
38
  import type { AppShellMessages } from '../sections/AppShell/AppShell';
39
+ import type { AppHeaderMessages } from '../sections/AppHeader/AppHeader';
39
40
  import type { SidebarMessages } from '../sections/Sidebar/Sidebar';
40
41
  import type { SidebarNavMessages } from '../molecules/SidebarNav/SidebarNav';
41
42
  import type { SiteNavMessages } from '../molecules/SiteNav/SiteNav';
@@ -142,6 +143,7 @@ export interface BrandMessages {
142
143
  menuButton: MenuButtonMessages;
143
144
  appRoot: AppRootMessages;
144
145
  appShell: AppShellMessages;
146
+ appHeader: AppHeaderMessages;
145
147
  sidebar: SidebarMessages;
146
148
  sidebarNav: SidebarNavMessages;
147
149
  siteNav: SiteNavMessages;
@@ -189,4 +191,4 @@ export interface BrandMessages {
189
191
  connectorExternalSignIn: ConnectorExternalSignInMessages;
190
192
  connectorRejection: ConnectorRejectionMessages;
191
193
  }
192
- export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, ColorPickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, };
194
+ export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, ColorPickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, AppHeaderMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, };
@@ -2,4 +2,4 @@ export { BrandMessagesProvider } from './BrandMessagesProvider';
2
2
  export type { BrandMessagesProviderProps } from './BrandMessagesProvider';
3
3
  export { useBrandMessages } from './BrandMessagesContext';
4
4
  export type { BrandMessagesReader } from './BrandMessagesContext';
5
- export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, ColorPickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, } from './BrandMessages';
5
+ export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, ColorPickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, AppHeaderMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, } from './BrandMessages';
@@ -1,6 +1,41 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import './AppHeader.css';
3
+ export type AppHeaderLogoLinkProps = {
4
+ href: string;
5
+ className: string;
6
+ 'aria-label': string;
7
+ children: ReactNode;
8
+ };
9
+ /**
10
+ * El único texto propio de la barra, y solo cuando lleva `logo`: es **cromo**,
11
+ * qué hace el logotipo («ir al inicio»), no qué marca es — el mismo criterio
12
+ * que `siteHeader.logo`.
13
+ */
14
+ export interface AppHeaderMessages {
15
+ /** Texto accesible del enlace del logotipo. */
16
+ logo: string;
17
+ }
3
18
  export interface AppHeaderProps {
19
+ /**
20
+ * La marca del producto, entre el botón de menú y `start`: un `Logo`, un SVG
21
+ * o una imagen de cualquier proporción. Toma el alto de contenido de la barra
22
+ * (`--app-header-content-height`) y el ancho que le dé su proporción; no hay
23
+ * que darle medidas. Sin `logo`, la barra no cambia.
24
+ */
25
+ logo?: ReactNode;
26
+ /** Destino del logotipo. Solo se usa con `logo`. */
27
+ logoHref?: string;
28
+ /**
29
+ * Texto accesible del enlace del logotipo. **Sin default**: sin él, sale de
30
+ * `appHeader.logo` del `BrandMessagesProvider`. Solo se lee con `logo`.
31
+ */
32
+ logoLabel?: string;
33
+ /**
34
+ * Enlace del logotipo para el router del producto. Recibe `href`, `className`,
35
+ * `aria-label` y `children`, y debe reenviarlos todos. Mismo contrato que en
36
+ * `SiteHeader`.
37
+ */
38
+ renderLogoLink?: (props: AppHeaderLogoLinkProps) => ReactNode;
4
39
  /** Tras el botón de menú: breadcrumb, buscador, título de página… */
5
40
  start?: ReactNode;
6
41
  /** Antes del avatar: la campana con su contador. Sitio fijo. */
@@ -24,6 +59,6 @@ export interface AppHeaderProps {
24
59
  * La barra superior de la aplicación, en todos los anchos. A la izquierda el
25
60
  * botón de menú, que abre el cajón en móvil y pliega/despliega la sidebar en
26
61
  * escritorio; a la derecha, notificaciones y cuenta. Entre medias, lo que la
27
- * página necesite.
62
+ * página necesite. Con `logo`, la marca del producto va justo tras el botón.
28
63
  */
29
- export declare function AppHeader({ start, notifications, end, menuLabel, menuCloseLabel, sidebarId, }: AppHeaderProps): import("react/jsx-runtime").JSX.Element;
64
+ export declare function AppHeader({ logo, logoHref, logoLabel, renderLogoLink, start, notifications, end, menuLabel, menuCloseLabel, sidebarId, }: AppHeaderProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- .app-header{align-items:center;gap:var(--app-header-gap);block-size:var(--app-header-height);padding-inline:var(--app-header-padding-inline);box-sizing:content-box;background-color:var(--app-header-bg);box-shadow:0 var(--app-header-border-width) 0 var(--app-header-border-color);z-index:var(--app-header-z-index);flex-shrink:0;padding-block-start:env(safe-area-inset-top);display:flex;position:sticky;inset-block-start:0}.app-header__start{flex:1;align-items:center;min-inline-size:0;display:flex}.app-header__notifications,.app-header__end{flex-shrink:0;align-items:center;display:flex}
1
+ .app-header{align-items:center;gap:var(--app-header-gap);block-size:var(--app-header-height);padding-inline:var(--app-header-padding-inline);box-sizing:content-box;background-color:var(--app-header-bg);box-shadow:0 var(--app-header-border-width) 0 var(--app-header-border-color);z-index:var(--app-header-z-index);flex-shrink:0;padding-block-start:env(safe-area-inset-top);display:flex;position:sticky;inset-block-start:0}.app-header__start{flex:1;align-items:center;min-inline-size:0;display:flex}.app-header__notifications,.app-header__end{flex-shrink:0;align-items:center;display:flex}.app-header__logo{box-shadow:none;color:inherit;--logo-height-sm:var(--app-header-content-height);--logo-height-md:var(--app-header-content-height);--logo-height-lg:var(--app-header-content-height);--logo-height-xl:var(--app-header-content-height);--logo-height-xxl:var(--app-header-content-height);flex-shrink:0;align-items:center;padding-block-end:0;display:flex}.app-header__logo:hover{box-shadow:none;color:inherit}.app-header__logo>*{block-size:var(--app-header-content-height);inline-size:auto}
@@ -1,37 +1,50 @@
1
1
  'use client';
2
2
  import './app-header.css';
3
- import { MenuButton as e } from "./menu-button.js";
4
- import { t } from "./_shared/appshellcontext.js";
5
- import { useContext as n, useState as r } from "react";
6
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
3
+ import { n as e } from "./_shared/brandmessagescontext.js";
4
+ import { MenuButton as t } from "./menu-button.js";
5
+ import { t as n } from "./_shared/appshellcontext.js";
6
+ import { useContext as r, useState as i } from "react";
7
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
8
  //#region src/stories/sections/AppHeader/AppHeader.tsx
8
- function o({ start: o, notifications: s, end: c, menuLabel: l, menuCloseLabel: u, sidebarId: d }) {
9
- let f = n(t), [p, m] = r(!1), h = f ? f.sidebar === "open" : p;
10
- return /* @__PURE__ */ a("header", {
9
+ function s({ children: e, ...t }) {
10
+ return /* @__PURE__ */ a("a", {
11
+ ...t,
12
+ children: e
13
+ });
14
+ }
15
+ function c({ logo: c, logoHref: l = "/", logoLabel: u, renderLogoLink: d = s, start: f, notifications: p, end: m, menuLabel: h, menuCloseLabel: g, sidebarId: _ }) {
16
+ let v = r(n), [y, b] = i(!1), x = v ? v.sidebar === "open" : y, S = v ? v.toggleSidebar : () => b((e) => !e), C = e("appHeader");
17
+ return /* @__PURE__ */ o("header", {
11
18
  className: "app-header",
12
19
  children: [
13
- /* @__PURE__ */ i(e, {
14
- isOpen: h,
15
- onClick: f ? f.toggleSidebar : () => m((e) => !e),
16
- label: l,
17
- closeLabel: u,
18
- "aria-controls": d,
19
- "aria-expanded": h
20
+ /* @__PURE__ */ a(t, {
21
+ isOpen: x,
22
+ onClick: S,
23
+ label: h,
24
+ closeLabel: g,
25
+ "aria-controls": _,
26
+ "aria-expanded": x
20
27
  }),
21
- /* @__PURE__ */ i("div", {
28
+ c && d({
29
+ href: l,
30
+ className: "app-header__logo",
31
+ "aria-label": C("logo", u),
32
+ children: c
33
+ }),
34
+ /* @__PURE__ */ a("div", {
22
35
  className: "app-header__start",
23
- children: o
36
+ children: f
24
37
  }),
25
- s && /* @__PURE__ */ i("div", {
38
+ p && /* @__PURE__ */ a("div", {
26
39
  className: "app-header__notifications",
27
- children: s
40
+ children: p
28
41
  }),
29
- c && /* @__PURE__ */ i("div", {
42
+ m && /* @__PURE__ */ a("div", {
30
43
  className: "app-header__end",
31
- children: c
44
+ children: m
32
45
  })
33
46
  ]
34
47
  });
35
48
  }
36
49
  //#endregion
37
- export { o as AppHeader };
50
+ export { c as AppHeader };
@@ -1 +1 @@
1
- .app-shell{--app-shell-sidebar-width:var(--sidebar-width);--app-shell-banner-height:0px;--app-shell-chrome-block-start:calc(var(--app-shell-banner-height) + var(--app-header-height) + env(safe-area-inset-top));flex-direction:column;block-size:100dvh;display:flex;overflow:clip}.app-shell__banner{flex-shrink:0}.app-shell__body{flex:1;min-block-size:0;display:flex;position:relative}.app-shell__content{min-inline-size:0;padding-inline:var(--section-padding-inline);padding-block:var(--section-padding-block-lg);flex:1;padding-block-end:max(var(--section-padding-block-lg), env(safe-area-inset-bottom));padding-inline-end:max(var(--section-padding-inline), env(safe-area-inset-right));overflow:auto}.app-shell__content.app-shell__content--flush{padding-block:0;padding-inline:0;padding-block-end:env(safe-area-inset-bottom);padding-inline-end:env(safe-area-inset-right)}.app-shell__backdrop{inset:0;background-color:var(--sidebar-backdrop-bg);opacity:var(--sidebar-backdrop-opacity);z-index:var(--sidebar-backdrop-z-index);position:fixed;inset-block-start:var(--app-shell-chrome-block-start)}
1
+ .app-shell{--app-shell-sidebar-width:var(--sidebar-width);--app-shell-banner-height:0px;--app-shell-chrome-block-start:calc(var(--app-shell-banner-height) + var(--app-header-height) + env(safe-area-inset-top));flex-direction:column;block-size:100dvh;display:flex;overflow:clip}.app-shell__banner{flex-shrink:0}.app-shell__body{flex:1;min-block-size:0;display:flex;position:relative}.app-shell__content{min-inline-size:0;padding-inline:var(--section-padding-inline);padding-block:var(--section-padding-block-lg);flex:1;padding-block-end:max(var(--section-padding-block-lg), env(safe-area-inset-bottom));padding-inline-end:max(var(--section-padding-inline), env(safe-area-inset-right));overflow:auto}.app-shell__content.app-shell__content--flush{padding-block:0;padding-inline:0;padding-block-end:env(safe-area-inset-bottom);padding-inline-end:env(safe-area-inset-right)}.app-shell__backdrop{inset:0;background-color:var(--sidebar-backdrop-bg);opacity:var(--sidebar-backdrop-opacity);z-index:var(--sidebar-backdrop-z-index);position:fixed;inset-block-start:var(--app-shell-chrome-block-start)}.app-shell:has(.app-header__logo) .sidebar__header{display:none}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiolxd/brand",
3
- "version": "49.22.0",
3
+ "version": "49.23.0",
4
4
  "description": "El sistema de diseño de Studio LXD: componentes React, tokens y documentación de la suite SLXD.",
5
5
  "repository": {
6
6
  "type": "git",