Skip to content

Commit 62c67ea

Browse files
committed
feat: improve logo support and navigation on mobile menu
1 parent 0a2b6f5 commit 62c67ea

File tree

3 files changed

+139
-118
lines changed

3 files changed

+139
-118
lines changed

core/components/header/index.tsx

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -77,31 +77,21 @@ export const Header = async () => {
7777

7878
const logo = data.settings ? logoTransformer(data.settings) : '';
7979

80-
// const locales = routing.locales.map((enabledLocales) => ({
81-
// id: enabledLocales,
82-
// label: enabledLocales.toLocaleUpperCase(),
83-
// }));
84-
85-
const locales = [
86-
{ id: 'en', label: 'EN' },
87-
{ id: 'es', label: 'ES' },
88-
];
89-
90-
// const currencies = data.currencies.edges
91-
// ? data.currencies.edges
92-
// // only show transactional currencies for now until cart prices can be rendered in display currencies
93-
// .filter(({ node }) => node.isTransactional)
94-
// .map(({ node }) => ({
95-
// id: node.code,
96-
// label: node.code,
97-
// isDefault: node.isDefault,
98-
// }))
99-
// : [];
100-
101-
const currencies = [
102-
{ id: 'USD', label: 'USD', isDefault: true },
103-
{ id: 'EUR', label: 'EUR', isDefault: false },
104-
];
80+
const locales = routing.locales.map((enabledLocales) => ({
81+
id: enabledLocales,
82+
label: enabledLocales.toLocaleUpperCase(),
83+
}));
84+
85+
const currencies = data.currencies.edges
86+
? data.currencies.edges
87+
// only show transactional currencies for now until cart prices can be rendered in display currencies
88+
.filter(({ node }) => node.isTransactional)
89+
.map(({ node }) => ({
90+
id: node.code,
91+
label: node.code,
92+
isDefault: node.isDefault,
93+
}))
94+
: [];
10595

10696
const streamableLinks = Streamable.from(async () => {
10797
const customerAccessToken = await getSessionCustomerAccessToken();

core/vibes/soul/primitives/logo/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ export function Logo({ className, logo: streamableLogo, href, width, height, lab
3636
<Link
3737
aria-label={label}
3838
className={clsx(
39-
'relative outline-0 ring-[var(--logo-focus,hsl(var(--primary)))] ring-offset-4 focus-visible:ring-2',
39+
'relative inline-block outline-0 ring-[var(--logo-focus,hsl(var(--primary)))] ring-offset-4 focus-visible:ring-2',
4040
className,
4141
)}
4242
href={href}
43-
style={typeof logo === 'string' ? {} : { width, height }}
43+
style={typeof logo === 'string' ? {} : { maxWidth: `${width}px`, height: `${height}px` }}
4444
>
4545
{typeof logo === 'object' && logo !== null && logo.src !== '' ? (
4646
<Image
4747
alt={logo.alt}
48-
className="object-contain object-left"
49-
fill
50-
sizes={`${width}px`}
48+
className="h-auto w-full object-contain object-left"
49+
height={height}
5150
src={logo.src}
51+
width={width}
5252
/>
5353
) : (
5454
typeof logo === 'string' && (

core/vibes/soul/primitives/navigation/index.tsx

Lines changed: 119 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -385,14 +385,35 @@ export const Navigation = forwardRef(function Navigation<S extends SearchResult>
385385
))
386386
}
387387
</Stream>
388-
{/* Locale / Language Dropdown */}
389-
{locales && locales.length > 1 ? (
390-
<LocaleSwitcher
391-
activeLocaleId={activeLocaleId}
392-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
393-
locales={locales as [Locale, Locale, ...Locale[]]}
394-
/>
395-
) : null}
388+
<div className="p-2 @4xl:p-5">
389+
<div className="flex items-center px-3 py-1 @4xl:py-2">
390+
{/* Locale / Language Dropdown */}
391+
{locales && locales.length > 1 ? (
392+
<LocaleSwitcher
393+
activeLocaleId={activeLocaleId}
394+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
395+
locales={locales as [Locale, Locale, ...Locale[]]}
396+
/>
397+
) : null}
398+
399+
{/* Currency Dropdown */}
400+
<Stream
401+
fallback={null}
402+
value={Streamable.all([streamableCurrencies, streamableActiveCurrencyId])}
403+
>
404+
{([currencies, activeCurrencyId]) =>
405+
currencies && currencies.length > 1 && currencyAction ? (
406+
<CurrencyForm
407+
action={currencyAction}
408+
activeCurrencyId={activeCurrencyId}
409+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
410+
currencies={currencies as [Currency, ...Currency[]]}
411+
/>
412+
) : null
413+
}
414+
</Stream>
415+
</div>
416+
</div>
396417
</div>
397418
</Popover.Content>
398419
</Popover.Portal>
@@ -573,6 +594,7 @@ export const Navigation = forwardRef(function Navigation<S extends SearchResult>
573594
{locales && locales.length > 1 ? (
574595
<LocaleSwitcher
575596
activeLocaleId={activeLocaleId}
597+
className="hidden @4xl:block"
576598
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
577599
locales={locales as [Locale, Locale, ...Locale[]]}
578600
/>
@@ -588,6 +610,7 @@ export const Navigation = forwardRef(function Navigation<S extends SearchResult>
588610
<CurrencyForm
589611
action={currencyAction}
590612
activeCurrencyId={activeCurrencyId}
613+
className="hidden @4xl:block"
591614
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
592615
currencies={currencies as [Currency, ...Currency[]]}
593616
/>
@@ -855,61 +878,67 @@ const useSwitchLocale = () => {
855878
function LocaleSwitcher({
856879
locales,
857880
activeLocaleId,
881+
className,
858882
}: {
859883
activeLocaleId?: string;
860884
locales: [Locale, ...Locale[]];
885+
className?: string;
861886
}) {
862887
const activeLocale = locales.find((locale) => locale.id === activeLocaleId);
863888
const [isPending, startTransition] = useTransition();
864889
const switchLocale = useSwitchLocale();
865890

866891
return (
867-
<DropdownMenu.Root>
868-
<DropdownMenu.Trigger
869-
className={clsx(
870-
'flex items-center gap-1 text-xs uppercase transition-opacity disabled:opacity-30',
871-
navButtonClassName,
872-
)}
873-
disabled={isPending}
874-
>
875-
{activeLocale?.id ?? locales[0].id}
876-
<ChevronDown size={16} strokeWidth={1.5} />
877-
</DropdownMenu.Trigger>
878-
<DropdownMenu.Portal>
879-
<DropdownMenu.Content
880-
align="end"
881-
className="z-50 max-h-80 overflow-y-scroll rounded-xl bg-[var(--nav-locale-background,hsl(var(--background)))] p-2 shadow-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 @4xl:w-32 @4xl:rounded-2xl @4xl:p-2"
882-
sideOffset={16}
892+
<div className={className}>
893+
<DropdownMenu.Root>
894+
<DropdownMenu.Trigger
895+
className={clsx(
896+
'flex items-center gap-1 text-xs uppercase transition-opacity disabled:opacity-30',
897+
navButtonClassName,
898+
)}
899+
disabled={isPending}
883900
>
884-
{locales.map(({ id, label }) => (
885-
<DropdownMenu.Item
886-
className={clsx(
887-
'cursor-default rounded-lg bg-[var(--nav-locale-link-background,transparent)] px-2.5 py-2 font-[family-name:var(--nav-locale-link-font-family,var(--font-family-body))] text-sm font-medium text-[var(--nav-locale-link-text,hsl(var(--contrast-400)))] outline-none ring-[var(--nav-focus,hsl(var(--primary)))] transition-colors hover:bg-[var(--nav-locale-link-background-hover,hsl(var(--contrast-100)))] hover:text-[var(--nav-locale-link-text-hover,hsl(var(--foreground)))]',
888-
{
889-
'text-[var(--nav-locale-link-text-selected,hsl(var(--foreground)))]':
890-
id === activeLocaleId,
891-
},
892-
)}
893-
key={id}
894-
onSelect={() => startTransition(() => switchLocale(id))}
895-
>
896-
{label}
897-
</DropdownMenu.Item>
898-
))}
899-
</DropdownMenu.Content>
900-
</DropdownMenu.Portal>
901-
</DropdownMenu.Root>
901+
{activeLocale?.id ?? locales[0].id}
902+
<ChevronDown size={16} strokeWidth={1.5} />
903+
</DropdownMenu.Trigger>
904+
<DropdownMenu.Portal>
905+
<DropdownMenu.Content
906+
align="end"
907+
className="z-50 max-h-80 overflow-y-scroll rounded-xl bg-[var(--nav-locale-background,hsl(var(--background)))] p-2 shadow-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 @4xl:w-32 @4xl:rounded-2xl @4xl:p-2"
908+
sideOffset={16}
909+
>
910+
{locales.map(({ id, label }) => (
911+
<DropdownMenu.Item
912+
className={clsx(
913+
'cursor-default rounded-lg bg-[var(--nav-locale-link-background,transparent)] px-2.5 py-2 font-[family-name:var(--nav-locale-link-font-family,var(--font-family-body))] text-sm font-medium text-[var(--nav-locale-link-text,hsl(var(--contrast-400)))] outline-none ring-[var(--nav-focus,hsl(var(--primary)))] transition-colors hover:bg-[var(--nav-locale-link-background-hover,hsl(var(--contrast-100)))] hover:text-[var(--nav-locale-link-text-hover,hsl(var(--foreground)))]',
914+
{
915+
'text-[var(--nav-locale-link-text-selected,hsl(var(--foreground)))]':
916+
id === activeLocaleId,
917+
},
918+
)}
919+
key={id}
920+
onSelect={() => startTransition(() => switchLocale(id))}
921+
>
922+
{label}
923+
</DropdownMenu.Item>
924+
))}
925+
</DropdownMenu.Content>
926+
</DropdownMenu.Portal>
927+
</DropdownMenu.Root>
928+
</div>
902929
);
903930
}
904931

905932
function CurrencyForm({
906933
action,
907934
currencies,
908935
activeCurrencyId,
936+
className,
909937
}: {
910938
activeCurrencyId?: string;
911939
action: CurrencyAction;
912940
currencies: [Currency, ...Currency[]];
941+
className?: string;
913942
}) {
914943
const router = useRouter();
915944
const [isPending, startTransition] = useTransition();
@@ -922,52 +951,54 @@ function CurrencyForm({
922951
}, [lastResult?.error]);
923952

924953
return (
925-
<DropdownMenu.Root>
926-
<DropdownMenu.Trigger
927-
className={clsx(
928-
'flex items-center gap-1 text-xs uppercase transition-opacity disabled:opacity-30',
929-
navButtonClassName,
930-
)}
931-
disabled={isPending}
932-
>
933-
{activeCurrency?.label ?? currencies[0].label}
934-
<ChevronDown size={16} strokeWidth={1.5} />
935-
</DropdownMenu.Trigger>
936-
<DropdownMenu.Portal>
937-
<DropdownMenu.Content
938-
align="end"
939-
className="z-50 max-h-80 overflow-y-scroll rounded-xl bg-[var(--nav-locale-background,hsl(var(--background)))] p-2 shadow-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 @4xl:w-32 @4xl:rounded-2xl @4xl:p-2"
940-
sideOffset={16}
954+
<div className={className}>
955+
<DropdownMenu.Root>
956+
<DropdownMenu.Trigger
957+
className={clsx(
958+
'flex items-center gap-1 text-xs uppercase transition-opacity disabled:opacity-30',
959+
navButtonClassName,
960+
)}
961+
disabled={isPending}
941962
>
942-
{currencies.map((currency) => (
943-
<DropdownMenu.Item
944-
className={clsx(
945-
'cursor-default rounded-lg bg-[var(--nav-locale-link-background,transparent)] px-2.5 py-2 font-[family-name:var(--nav-locale-link-font-family,var(--font-family-body))] text-sm font-medium text-[var(--nav-locale-link-text,hsl(var(--contrast-400)))] outline-none ring-[var(--nav-focus,hsl(var(--primary)))] transition-colors hover:bg-[var(--nav-locale-link-background-hover,hsl(var(--contrast-100)))] hover:text-[var(--nav-locale-link-text-hover,hsl(var(--foreground)))]',
946-
{
947-
'text-[var(--nav-locale-link-text-selected,hsl(var(--foreground)))]':
948-
currency.id === activeCurrencyId,
949-
},
950-
)}
951-
key={currency.id}
952-
onSelect={() => {
953-
// eslint-disable-next-line @typescript-eslint/require-await
954-
startTransition(async () => {
955-
const formData = new FormData();
956-
957-
formData.append('id', currency.id);
958-
formAction(formData);
959-
960-
// This is needed to refresh the Data Cache after the product has been added to the cart.
961-
// The cart id is not picked up after the first time the cart is created/updated.
962-
router.refresh();
963-
});
964-
}}
965-
>
966-
{currency.label}
967-
</DropdownMenu.Item>
968-
))}
969-
</DropdownMenu.Content>
970-
</DropdownMenu.Portal>
971-
</DropdownMenu.Root>
963+
{activeCurrency?.label ?? currencies[0].label}
964+
<ChevronDown size={16} strokeWidth={1.5} />
965+
</DropdownMenu.Trigger>
966+
<DropdownMenu.Portal>
967+
<DropdownMenu.Content
968+
align="end"
969+
className="z-50 max-h-80 overflow-y-scroll rounded-xl bg-[var(--nav-locale-background,hsl(var(--background)))] p-2 shadow-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 @4xl:w-32 @4xl:rounded-2xl @4xl:p-2"
970+
sideOffset={16}
971+
>
972+
{currencies.map((currency) => (
973+
<DropdownMenu.Item
974+
className={clsx(
975+
'cursor-default rounded-lg bg-[var(--nav-locale-link-background,transparent)] px-2.5 py-2 font-[family-name:var(--nav-locale-link-font-family,var(--font-family-body))] text-sm font-medium text-[var(--nav-locale-link-text,hsl(var(--contrast-400)))] outline-none ring-[var(--nav-focus,hsl(var(--primary)))] transition-colors hover:bg-[var(--nav-locale-link-background-hover,hsl(var(--contrast-100)))] hover:text-[var(--nav-locale-link-text-hover,hsl(var(--foreground)))]',
976+
{
977+
'text-[var(--nav-locale-link-text-selected,hsl(var(--foreground)))]':
978+
currency.id === activeCurrencyId,
979+
},
980+
)}
981+
key={currency.id}
982+
onSelect={() => {
983+
// eslint-disable-next-line @typescript-eslint/require-await
984+
startTransition(async () => {
985+
const formData = new FormData();
986+
987+
formData.append('id', currency.id);
988+
formAction(formData);
989+
990+
// This is needed to refresh the Data Cache after the product has been added to the cart.
991+
// The cart id is not picked up after the first time the cart is created/updated.
992+
router.refresh();
993+
});
994+
}}
995+
>
996+
{currency.label}
997+
</DropdownMenu.Item>
998+
))}
999+
</DropdownMenu.Content>
1000+
</DropdownMenu.Portal>
1001+
</DropdownMenu.Root>
1002+
</div>
9721003
);
9731004
}

0 commit comments

Comments
 (0)