@cronos-labs/ui 0.7.2 → 0.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.
@@ -3,6 +3,9 @@ export interface FooterLinkItem {
3
3
  target: string;
4
4
  external: boolean;
5
5
  localizeTarget?: boolean;
6
+ /** Renders the link greyed and non-interactive, with `badge` beside it if given. */
7
+ disabled?: boolean;
8
+ badge?: string;
6
9
  }
7
10
  export interface FooterLinkGroup {
8
11
  group: string;
@@ -5,7 +5,7 @@ import { buildLocalizedPath } from '../locale/routes.js';
5
5
  import { useCurrentLocale } from '../locale/hooks.js';
6
6
  import { desktopViewportQuery } from '../tokens.js';
7
7
  import { useOptionalBrand } from '../brand/index.js';
8
- import { FooterColumn, FooterColumnHeading, FooterContainer, FooterCopyright, FooterColumnsGrid, FooterDesktopLocaleSlot, FooterDisclaimer, FooterDisclaimerStack, FooterGrid, FooterLegalButton, FooterLegalDivider, FooterLegalLink as FooterLegalLinkStyled, FooterLegalMeta, FooterLegalNav, FooterLegalText, FooterLocaleSlot, FooterLink as FooterLinkStyled, FooterLinkList, FooterMobileCopyright, FooterMobileDivider, FooterMobileLegalDividerTrack, FooterMobileLegalMeta, FooterMobileLegalNav, FooterShell, FooterWaitlistSlot, FooterWordmark, FooterWordmarkImage, } from './styles.js';
8
+ import { FooterColumn, FooterColumnHeading, FooterContainer, FooterCopyright, FooterColumnsGrid, FooterDesktopLocaleSlot, FooterDisclaimer, FooterDisclaimerStack, FooterGrid, FooterLegalButton, FooterLegalDivider, FooterLegalLink as FooterLegalLinkStyled, FooterLegalMeta, FooterLegalNav, FooterLegalText, FooterLocaleSlot, FooterLink as FooterLinkStyled, FooterLinkBadge, FooterLinkDisabled, FooterLinkList, FooterMobileCopyright, FooterMobileDivider, FooterMobileLegalDividerTrack, FooterMobileLegalMeta, FooterMobileLegalNav, FooterShell, FooterWaitlistSlot, FooterWordmark, FooterWordmarkImage, } from './styles.js';
9
9
  const buildFooterHref = (target, locale, localize = true) => {
10
10
  if (target.startsWith('/') && localize) {
11
11
  return buildLocalizedPath(target, locale);
@@ -38,6 +38,9 @@ export function Footer({ brandWordmarkSrc, columns, content, forceDocumentNaviga
38
38
  };
39
39
  }, []);
40
40
  const renderFooterLink = (link) => {
41
+ if (link.disabled) {
42
+ return (_jsxs(FooterLinkDisabled, { "aria-disabled": "true", "aria-label": `${link.label} ${link.badge ?? ''}`.trim(), children: [_jsx("span", { children: link.label }), link.badge ? _jsx(FooterLinkBadge, { children: link.badge }) : null] }, link.target));
43
+ }
41
44
  return (_jsx(FooterLinkStyled, { href: buildFooterHref(link.target, locale, link.localizeTarget ?? true), ...getExternalLinkProps(link.external), children: _jsx("span", { children: link.label }) }, link.target));
42
45
  };
43
46
  const renderLegalLink = (link) => {
@@ -40,6 +40,12 @@ export declare const FooterLinkList: import("styled-components/dist/types").ISty
40
40
  export declare const FooterLink: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
41
41
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
42
42
  }> & string;
43
+ export declare const FooterLinkDisabled: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
44
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
45
+ }> & string;
46
+ export declare const FooterLinkBadge: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
47
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
48
+ }> & string;
43
49
  export declare const FooterLegalMeta: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
44
50
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
45
51
  }> & string;
@@ -172,6 +172,39 @@ export const FooterLink = styled.a `
172
172
  font-size: ${({ theme }) => theme.typography.fontSize.body};
173
173
  }
174
174
  `;
175
+ /* A greyed column link: the link's type, dimmed, with no hover. */
176
+ export const FooterLinkDisabled = styled.span `
177
+ display: inline-flex;
178
+ align-items: center;
179
+ gap: 8px;
180
+ width: fit-content;
181
+ color: ${({ theme }) => theme.colors.ink};
182
+ font-size: 0.875rem;
183
+ font-weight: ${({ theme }) => theme.fontWeight.medium};
184
+ line-height: 1.5;
185
+ opacity: 0.5;
186
+ cursor: default;
187
+
188
+ ${({ theme }) => theme.mediaQueries.lg} {
189
+ font-size: ${({ theme }) => theme.typography.fontSize.body};
190
+ }
191
+ `;
192
+ export const FooterLinkBadge = styled.span `
193
+ display: inline-flex;
194
+ align-items: center;
195
+ justify-content: center;
196
+ height: 18px;
197
+ padding: 0 8px;
198
+ border-radius: ${({ theme }) => theme.borderRadius.pill};
199
+ background: rgb(0 0 0 / 0.1);
200
+ color: currentColor;
201
+ font-size: 0.5625rem;
202
+ font-weight: ${({ theme }) => theme.fontWeight.black};
203
+ letter-spacing: 0.1em;
204
+ line-height: 1;
205
+ text-transform: uppercase;
206
+ white-space: nowrap;
207
+ `;
175
208
  export const FooterLegalMeta = styled.div `
176
209
  display: flex;
177
210
  flex-wrap: wrap;
@@ -2,10 +2,14 @@ import type { HeaderPresentationVariant } from './index.js';
2
2
  export interface NavDropdownItem {
3
3
  key: string;
4
4
  label: string;
5
- href: string;
5
+ /** Absent on a disabled item. */
6
+ href?: string | undefined;
6
7
  ariaLabel?: string | undefined;
7
8
  external?: boolean | undefined;
8
9
  onClick?: ((event: React.MouseEvent<HTMLAnchorElement>) => void) | undefined;
10
+ /** Greyed and non-interactive, with `badge` beside the label if given. */
11
+ disabled?: boolean | undefined;
12
+ badge?: string | undefined;
9
13
  }
10
14
  interface NavDropdownProps {
11
15
  label: string;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from 'react';
3
3
  import { useLocation } from 'react-router-dom';
4
- import { NavDropdown as NavDropdownRoot, NavDropdownChevron, NavDropdownLabel, NavDropdownList, NavDropdownMenu, NavDropdownOption, NavDropdownTrigger, } from './styles.js';
4
+ import { NavDropdown as NavDropdownRoot, NavDropdownChevron, NavDropdownDisabledOption, NavDropdownLabel, NavDropdownList, NavDropdownMenu, NavDropdownOption, NavDropdownOptionBadge, NavDropdownTrigger, } from './styles.js';
5
5
  const buildMenuId = (label) => `header-nav-dropdown-${label.toLowerCase().replace(/\s+/gu, '-')}`;
6
6
  export function NavDropdown({ label, items, variant, contrast, }) {
7
7
  const [isOpen, setIsOpen] = useState(false);
@@ -32,7 +32,7 @@ export function NavDropdown({ label, items, variant, contrast, }) {
32
32
  document.removeEventListener('keydown', handleKeyDown);
33
33
  };
34
34
  }, [isOpen]);
35
- return (_jsxs(NavDropdownRoot, { ref: rootRef, onMouseEnter: () => setIsOpen(true), onMouseLeave: () => setIsOpen(false), children: [_jsxs(NavDropdownTrigger, { type: "button", "$variant": variant, "$contrast": contrast, "aria-haspopup": "menu", "aria-expanded": isOpen, "aria-controls": menuId, onClick: () => setIsOpen((currentValue) => !currentValue), children: [_jsx(NavDropdownLabel, { "$contrast": contrast, children: label }), _jsx(NavDropdownChevron, { "$open": isOpen, "aria-hidden": "true" })] }), _jsx(NavDropdownMenu, { "$open": isOpen, id: menuId, role: "menu", "aria-label": label, children: _jsx(NavDropdownList, { children: items.map((item) => (_jsx(NavDropdownOption, { role: "menuitem", href: item.href, "aria-label": item.ariaLabel, onClick: (event) => {
35
+ return (_jsxs(NavDropdownRoot, { ref: rootRef, onMouseEnter: () => setIsOpen(true), onMouseLeave: () => setIsOpen(false), children: [_jsxs(NavDropdownTrigger, { type: "button", "$variant": variant, "$contrast": contrast, "aria-haspopup": "menu", "aria-expanded": isOpen, "aria-controls": menuId, onClick: () => setIsOpen((currentValue) => !currentValue), children: [_jsx(NavDropdownLabel, { "$contrast": contrast, children: label }), _jsx(NavDropdownChevron, { "$open": isOpen, "aria-hidden": "true" })] }), _jsx(NavDropdownMenu, { "$open": isOpen, id: menuId, role: "menu", "aria-label": label, children: _jsx(NavDropdownList, { children: items.map((item) => item.disabled ? (_jsxs(NavDropdownDisabledOption, { role: "menuitem", "aria-disabled": "true", "aria-label": `${item.label} ${item.badge ?? ''}`.trim(), children: [item.label, item.badge ? _jsx(NavDropdownOptionBadge, { children: item.badge }) : null] }, item.key)) : (_jsx(NavDropdownOption, { role: "menuitem", href: item.href, "aria-label": item.ariaLabel, onClick: (event) => {
36
36
  setIsOpen(false);
37
37
  item.onClick?.(event);
38
38
  }, ...(item.external ? { target: '_blank', rel: 'noreferrer' } : {}), children: item.label }, item.key))) }) })] }));
@@ -10,6 +10,13 @@ export interface HeaderNavChild {
10
10
  label: string;
11
11
  route?: string;
12
12
  external?: boolean;
13
+ /**
14
+ * Renders the child greyed and non-interactive, with `badge` beside it if
15
+ * given — for a destination that is not open yet. A disabled child needs
16
+ * no `route`.
17
+ */
18
+ disabled?: boolean;
19
+ badge?: string;
13
20
  }
14
21
  export interface HeaderNavItem {
15
22
  label: string;
@@ -29,6 +36,8 @@ export interface HeaderContent {
29
36
  export interface HeaderWaitlistCta {
30
37
  href: string;
31
38
  onClick?: (event: React.MouseEvent<HTMLAnchorElement>, ctaLocation: 'nav_desktop' | 'nav_mobile') => void;
39
+ /** Renders the CTA greyed and non-interactive, keeping its place and label. */
40
+ disabled?: boolean;
32
41
  }
33
42
  interface HeaderProps {
34
43
  /** Overrides the wordmark from `<BrandProvider>`. Optional when one is present. */
@@ -8,11 +8,11 @@ import { desktopViewportQuery } from '../tokens.js';
8
8
  import { useOptionalBrand } from '../brand/index.js';
9
9
  import { normalizePathname } from './helper.js';
10
10
  import { NavDropdown } from './NavDropdown.js';
11
- import { BrandWordmarkMask, HeaderAction, HeaderActionArrow, HeaderBrandLink, HeaderFrame, HeaderMobileNav, HeaderMobileNavDisabledItem, HeaderMobileNavGroup, HeaderMobileNavGroupChevron, HeaderMobileNavGroupPanel, HeaderMobileNavGroupPanelInner, HeaderMobileNavGroupToggle, HeaderMobileNavSubLink, HeaderMobileNavSubList, HeaderMobileNavLink, HeaderMobileOverlay, HeaderMobileLocaleSlot, HeaderMobileSheet, HeaderMobileSoonBadge, HeaderMobileToggle, HeaderMobileToggleIcon, HeaderMobileWaitlistArrow, HeaderMobileWaitlistLabel, HeaderMobileWaitlistLink, HeaderShell, Nav, NavBadge, NavBadgeLabel, Wordmark, } from './styles.js';
11
+ import { BrandWordmarkMask, HeaderAction, HeaderActionArrow, HeaderBrandLink, HeaderFrame, HeaderMobileNav, HeaderMobileNavDisabledItem, HeaderMobileNavGroup, HeaderMobileNavGroupChevron, HeaderMobileNavGroupPanel, HeaderMobileNavGroupPanelInner, HeaderMobileNavGroupToggle, HeaderMobileNavSubDisabledItem, HeaderMobileNavSubLink, HeaderMobileNavSubList, HeaderMobileNavLink, HeaderMobileOverlay, HeaderMobileLocaleSlot, HeaderMobileSheet, HeaderMobileSoonBadge, HeaderMobileToggle, HeaderMobileToggleIcon, HeaderMobileWaitlistArrow, HeaderMobileWaitlistLabel, HeaderMobileWaitlistLink, HeaderShell, Nav, NavBadge, NavBadgeLabel, Wordmark, } from './styles.js';
12
12
  function MobileNavGroup({ label, items }) {
13
13
  const [isExpanded, setIsExpanded] = useState(false);
14
14
  const panelId = `mobile-nav-group-${label.toLowerCase().replace(/\s+/gu, '-')}`;
15
- return (_jsxs(HeaderMobileNavGroup, { children: [_jsxs(HeaderMobileNavGroupToggle, { type: "button", "aria-expanded": isExpanded, "aria-controls": panelId, onClick: () => setIsExpanded((currentValue) => !currentValue), children: [label, _jsx(HeaderMobileNavGroupChevron, { "$open": isExpanded, "aria-hidden": "true" })] }), _jsx(HeaderMobileNavGroupPanel, { "$open": isExpanded, id: panelId, children: _jsx(HeaderMobileNavGroupPanelInner, { "$open": isExpanded, children: _jsx(HeaderMobileNavSubList, { "aria-hidden": !isExpanded, children: items.map((item) => (_jsx(HeaderMobileNavSubLink, { href: item.href, "aria-label": item.ariaLabel, tabIndex: isExpanded ? undefined : -1, onClick: item.onClick, ...(item.external ? { target: '_blank', rel: 'noreferrer' } : {}), children: item.label }, item.key))) }) }) })] }));
15
+ return (_jsxs(HeaderMobileNavGroup, { children: [_jsxs(HeaderMobileNavGroupToggle, { type: "button", "aria-expanded": isExpanded, "aria-controls": panelId, onClick: () => setIsExpanded((currentValue) => !currentValue), children: [label, _jsx(HeaderMobileNavGroupChevron, { "$open": isExpanded, "aria-hidden": "true" })] }), _jsx(HeaderMobileNavGroupPanel, { "$open": isExpanded, id: panelId, children: _jsx(HeaderMobileNavGroupPanelInner, { "$open": isExpanded, children: _jsx(HeaderMobileNavSubList, { "aria-hidden": !isExpanded, children: items.map((item) => item.disabled ? (_jsxs(HeaderMobileNavSubDisabledItem, { "aria-disabled": "true", "aria-label": `${item.label} ${item.badge ?? ''}`.trim(), children: [item.label, item.badge ? _jsx(HeaderMobileSoonBadge, { children: item.badge }) : null] }, item.key)) : (_jsx(HeaderMobileNavSubLink, { href: item.href, "aria-label": item.ariaLabel, tabIndex: isExpanded ? undefined : -1, onClick: item.onClick, ...(item.external ? { target: '_blank', rel: 'noreferrer' } : {}), children: item.label }, item.key))) }) }) })] }));
16
16
  }
17
17
  export function Header({ brandWordmarkSrc, content, forceDocumentNavigation = false, homeHref, isExternalHref, mobilePresentation, navItems, presentation, shouldAnimatePresentation, waitlistCta, }) {
18
18
  const brand = useOptionalBrand();
@@ -100,8 +100,16 @@ export function Header({ brandWordmarkSrc, content, forceDocumentNavigation = fa
100
100
  const label = item.label;
101
101
  if (item.children && item.children.length > 0) {
102
102
  const dropdownItems = item.children
103
- .filter((child) => Boolean(child.route))
103
+ .filter((child) => Boolean(child.route) || child.disabled)
104
104
  .map((child) => {
105
+ if (child.disabled || !child.route) {
106
+ return {
107
+ key: child.key,
108
+ label: child.label,
109
+ disabled: true,
110
+ badge: child.badge,
111
+ };
112
+ }
105
113
  const childHref = resolveHref(child.route);
106
114
  return {
107
115
  key: child.key,
@@ -129,14 +137,22 @@ export function Header({ brandWordmarkSrc, content, forceDocumentNavigation = fa
129
137
  : (event) => {
130
138
  handleInternalNavigation(event, href);
131
139
  }, ...(item.external ? { target: '_blank', rel: 'noreferrer' } : {}), children: content_ }, item.label));
132
- }) }), _jsx(HeaderMobileToggle, { type: "button", "aria-label": isMobileMenuOpen ? 'Close navigation menu' : 'Open navigation menu', "aria-expanded": isMobileMenuOpen, "aria-controls": "mobile-navigation", onClick: () => setIsMobileMenuOpen((currentValue) => !currentValue), children: _jsx(HeaderMobileToggleIcon, { "$open": isMobileMenuOpen, children: _jsx("span", {}) }) }), waitlistCta ? (_jsxs(HeaderAction, { "$variant": presentation.variant, href: resolveHref(waitlistCta.href), onClick: forceDocumentNavigation
140
+ }) }), _jsx(HeaderMobileToggle, { type: "button", "aria-label": isMobileMenuOpen ? 'Close navigation menu' : 'Open navigation menu', "aria-expanded": isMobileMenuOpen, "aria-controls": "mobile-navigation", onClick: () => setIsMobileMenuOpen((currentValue) => !currentValue), children: _jsx(HeaderMobileToggleIcon, { "$open": isMobileMenuOpen, children: _jsx("span", {}) }) }), waitlistCta?.disabled ? (_jsxs(HeaderAction, { as: "span", "$variant": presentation.variant, "$disabled": true, "aria-disabled": "true", children: [content.joinWaitlist, _jsx(HeaderActionArrow, { "aria-hidden": "true", children: "\u2192" })] })) : waitlistCta ? (_jsxs(HeaderAction, { "$variant": presentation.variant, href: resolveHref(waitlistCta.href), onClick: forceDocumentNavigation
133
141
  ? undefined
134
142
  : (event) => handleWaitlistCtaClick(event, 'nav_desktop'), children: [content.joinWaitlist, _jsx(HeaderActionArrow, { "aria-hidden": "true", children: "\u2192" })] })) : null] }), isMobileMenuOpen ? (_jsx(HeaderMobileOverlay, { onClick: () => setIsMobileMenuOpen(false), children: _jsxs(HeaderMobileSheet, { id: "mobile-navigation", role: "dialog", "aria-modal": "true", "aria-label": "Navigation menu", onClick: (event) => event.stopPropagation(), children: [_jsx(HeaderMobileNav, { "aria-label": "Mobile navigation", children: enabledNavItems.map((item) => {
135
143
  const label = item.label;
136
144
  if (item.children && item.children.length > 0) {
137
145
  const groupItems = item.children
138
- .filter((child) => Boolean(child.route))
146
+ .filter((child) => Boolean(child.route) || child.disabled)
139
147
  .map((child) => {
148
+ if (child.disabled || !child.route) {
149
+ return {
150
+ key: child.key,
151
+ label: child.label,
152
+ disabled: true,
153
+ badge: child.badge,
154
+ };
155
+ }
140
156
  const childHref = resolveHref(child.route);
141
157
  return {
142
158
  key: child.key,
@@ -165,7 +181,7 @@ export function Header({ brandWordmarkSrc, content, forceDocumentNavigation = fa
165
181
  setIsMobileMenuOpen(false);
166
182
  handleInternalNavigation(event, href);
167
183
  }, ...(item.external ? { target: '_blank', rel: 'noreferrer' } : {}), children: [label, item.badge ? (_jsx(HeaderMobileSoonBadge, { children: item.badge })) : null] }, item.label));
168
- }) }), _jsx(HeaderMobileLocaleSlot, { children: _jsx(LocaleSelector, { ariaLabel: content.localeSelectorAriaLabel, forceDocumentNavigation: forceDocumentNavigation, inlineMenu: true, menuPlacement: "down", onLocaleSelect: () => setIsMobileMenuOpen(false) }) }), waitlistCta ? (_jsxs(HeaderMobileWaitlistLink, { href: resolveHref(waitlistCta.href), onClick: forceDocumentNavigation
184
+ }) }), _jsx(HeaderMobileLocaleSlot, { children: _jsx(LocaleSelector, { ariaLabel: content.localeSelectorAriaLabel, forceDocumentNavigation: forceDocumentNavigation, inlineMenu: true, menuPlacement: "down", onLocaleSelect: () => setIsMobileMenuOpen(false) }) }), waitlistCta?.disabled ? (_jsxs(HeaderMobileWaitlistLink, { as: "span", "$disabled": true, "aria-disabled": "true", children: [_jsx(HeaderMobileWaitlistLabel, { children: content.waitlistEmailCta }), _jsx(HeaderMobileWaitlistArrow, { "aria-hidden": "true", children: "\u2192" })] })) : waitlistCta ? (_jsxs(HeaderMobileWaitlistLink, { href: resolveHref(waitlistCta.href), onClick: forceDocumentNavigation
169
185
  ? () => setIsMobileMenuOpen(false)
170
186
  : (event) => handleWaitlistCtaClick(event, 'nav_mobile'), children: [_jsx(HeaderMobileWaitlistLabel, { children: content.waitlistEmailCta }), _jsx(HeaderMobileWaitlistArrow, { "aria-hidden": "true", children: "\u2192" })] })) : null] }) })) : null] }));
171
187
  }
@@ -77,6 +77,12 @@ export declare const NavDropdownList: import("styled-components/dist/types").ISt
77
77
  export declare const NavDropdownOption: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
78
78
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
79
79
  }> & string;
80
+ export declare const NavDropdownDisabledOption: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
81
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
82
+ }> & string;
83
+ export declare const NavDropdownOptionBadge: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
84
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
85
+ }> & string;
80
86
  export declare const NavBadge: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
81
87
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
82
88
  }> & string;
@@ -87,6 +93,7 @@ export declare const HeaderAction: import("styled-components/dist/types").IStyle
87
93
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
88
94
  }, {
89
95
  $variant: HeaderPresentationVariant;
96
+ $disabled?: boolean | undefined;
90
97
  }>> & string;
91
98
  export declare const HeaderActionArrow: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
92
99
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
@@ -138,6 +145,9 @@ export declare const HeaderMobileNavSubList: import("styled-components/dist/type
138
145
  export declare const HeaderMobileNavSubLink: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
139
146
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
140
147
  }> & string;
148
+ export declare const HeaderMobileNavSubDisabledItem: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
149
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
150
+ }> & string;
141
151
  export declare const HeaderMobileNavDisabledItem: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
142
152
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
143
153
  }> & string;
@@ -147,9 +157,11 @@ export declare const HeaderMobileSoonBadge: import("styled-components/dist/types
147
157
  export declare const HeaderMobileLocaleSlot: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
148
158
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
149
159
  }> & string;
150
- export declare const HeaderMobileWaitlistLink: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
160
+ export declare const HeaderMobileWaitlistLink: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
151
161
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
152
- }> & string;
162
+ }, {
163
+ $disabled?: boolean | undefined;
164
+ }>> & string;
153
165
  export declare const HeaderMobileWaitlistLabel: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
154
166
  style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
155
167
  }> & string;
@@ -398,6 +398,43 @@ export const NavDropdownOption = styled.a `
398
398
  outline-offset: -3px;
399
399
  }
400
400
  `;
401
+ /* A greyed dropdown entry: the option's shape without its hover or link
402
+ semantics, the badge in the disabled nav item's muted pill. */
403
+ export const NavDropdownDisabledOption = styled.span `
404
+ display: flex;
405
+ align-items: center;
406
+ gap: 8px;
407
+ width: 100%;
408
+ min-height: 44px;
409
+ padding: 12px;
410
+ border-radius: 8px;
411
+ color: inherit;
412
+ font-size: 1rem;
413
+ font-weight: ${({ theme }) => theme.fontWeight.semibold};
414
+ letter-spacing: -0.02em;
415
+ line-height: ${({ theme }) => theme.typography.lineHeight.tight};
416
+ text-align: left;
417
+ white-space: nowrap;
418
+ opacity: 0.5;
419
+ cursor: default;
420
+ `;
421
+ export const NavDropdownOptionBadge = styled.span `
422
+ display: inline-flex;
423
+ align-items: center;
424
+ justify-content: center;
425
+ min-width: 44px;
426
+ height: 18px;
427
+ padding: 0 8px;
428
+ border-radius: ${({ theme }) => theme.borderRadius.pill};
429
+ background: rgb(0 0 0 / 0.08);
430
+ color: currentColor;
431
+ font-size: 0.5625rem;
432
+ font-weight: ${({ theme }) => theme.fontWeight.black};
433
+ letter-spacing: 0.1em;
434
+ line-height: ${({ theme }) => theme.typography.lineHeight.tight};
435
+ text-transform: uppercase;
436
+ white-space: nowrap;
437
+ `;
401
438
  export const NavBadge = styled.span `
402
439
  display: inline-flex;
403
440
  align-items: center;
@@ -458,6 +495,20 @@ export const HeaderAction = styled.a `
458
495
  outline-offset: 3px;
459
496
  }
460
497
 
498
+ /* Disabled: rendered as a span, so no hover lift and no focus ring;
499
+ dimmed in place so the layout does not move when it goes live. */
500
+ ${({ $disabled }) => $disabled
501
+ ? `
502
+ opacity: 0.55;
503
+ cursor: default;
504
+
505
+ &:hover {
506
+ opacity: 0.55;
507
+ transform: none;
508
+ }
509
+ `
510
+ : ''}
511
+
461
512
  ${({ theme }) => theme.mediaQueries.lg} {
462
513
  display: inline-flex;
463
514
  min-width: ${({ theme }) => theme.layout.headerActionWidth};
@@ -698,6 +749,22 @@ export const HeaderMobileNavSubLink = styled.a `
698
749
  outline-offset: -4px;
699
750
  }
700
751
  `;
752
+ /* A greyed entry inside an expanded mobile group: the sub-link's shape,
753
+ dimmed, with no hover. */
754
+ export const HeaderMobileNavSubDisabledItem = styled.span `
755
+ display: flex;
756
+ align-items: center;
757
+ gap: 6px;
758
+ min-height: 40px;
759
+ padding: 8px 12px;
760
+ color: ${({ theme }) => theme.colors.textDarkSubtle};
761
+ font-size: ${({ theme }) => theme.typography.fontSize.bodySm};
762
+ font-weight: ${({ theme }) => theme.fontWeight.semibold};
763
+ letter-spacing: -0.02em;
764
+ line-height: ${({ theme }) => theme.typography.lineHeight.compact};
765
+ opacity: 0.55;
766
+ cursor: default;
767
+ `;
701
768
  export const HeaderMobileNavDisabledItem = styled.span `
702
769
  display: inline-flex;
703
770
  align-items: center;
@@ -751,6 +818,8 @@ export const HeaderMobileWaitlistLink = styled.a `
751
818
  color: ${({ theme }) => theme.colors.textDarkSubtle};
752
819
  text-decoration: none;
753
820
  overflow: hidden;
821
+ opacity: ${({ $disabled }) => ($disabled ? 0.55 : 1)};
822
+ cursor: ${({ $disabled }) => ($disabled ? 'default' : 'pointer')};
754
823
 
755
824
  &:focus-visible {
756
825
  outline: 2px solid ${({ theme }) => theme.colors.ink};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cronos-labs/ui",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "Shared Header, Footer, Seo, locale and theme primitives for Cronos web properties.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",