Skip to content

Commit

Permalink
feat: navbar top simple mobile (#2830)
Browse files Browse the repository at this point in the history
* feat: navbar top with simple mobile

* feat: navbar top with simple mobile

* fix: smaller iframe for navbars top
  • Loading branch information
justyna-13 committed Jun 23, 2023
1 parent e20f8b1 commit e3c66d5
Show file tree
Hide file tree
Showing 5 changed files with 559 additions and 2 deletions.
34 changes: 32 additions & 2 deletions apps/docs/components/blocks/NavbarTop.md
Expand Up @@ -11,7 +11,7 @@ hideToc: true

## NavbarTop with white background

<Showcase showcase-name="NavbarTop/NavbarTop" no-paddings style="min-height: 500px;">
<Showcase showcase-name="NavbarTop/NavbarTop" no-paddings style="min-height: 150px;">

<!-- vue -->
<<<../../preview/nuxt/pages/showcases/NavbarTop/NavbarTop.vue
Expand All @@ -24,7 +24,7 @@ hideToc: true

## NavbarTop with filled background

<Showcase showcase-name="NavbarTop/NavbarTopFilled" no-paddings style="min-height: 500px;">
<Showcase showcase-name="NavbarTop/NavbarTopFilled" no-paddings style="min-height: 150px;">

<!-- vue -->
<<<../../preview/nuxt/pages/showcases/NavbarTop/NavbarTopFilled.vue
Expand All @@ -34,3 +34,33 @@ hideToc: true
<!-- end react -->

</Showcase>

## NavbarTop with white background and simple mobile bar

The alternate NavbarTop variant designed to work seamlessly with the NavbarBottom, providing a cohesive mobile navigation experience.

By combining with the NavbarBottom, you can create a unified navigation structure that accommodates both top and bottom navigation elements on mobile devices. This ensures a smooth and intuitive user experience, allowing users to access important navigation options easily.

<Showcase showcase-name="NavbarTop/NavbarTopSimpleMobile" no-paddings style="min-height: 150px;">

<!-- vue -->
<<<../../preview/nuxt/pages/showcases/NavbarTop/NavbarTopSimpleMobile.vue
<!-- end vue -->
<!-- react -->
<<<../../preview/next/pages/showcases/NavbarTop/NavbarTopSimpleMobile.tsx#source
<!-- end react -->

</Showcase>

## NavbarTop with filled background and simple mobile bar

<Showcase showcase-name="NavbarTop/NavbarTopFilledSimpleMobile" no-paddings style="min-height: 150px;">

<!-- vue -->
<<<../../preview/nuxt/pages/showcases/NavbarTop/NavbarTopFilledSimpleMobile.vue
<!-- end vue -->
<!-- react -->
<<<../../preview/next/pages/showcases/NavbarTop/NavbarTopFilledSimpleMobile.tsx#source
<!-- end react -->

</Showcase>
@@ -0,0 +1,134 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import { ShowcasePageLayout } from '../../showcases';
// #region source
import { useState } from 'react';
import {
SfButton,
SfIconShoppingCart,
SfIconFavorite,
SfIconPerson,
SfIconExpandMore,
SfInput,
SfIconSearch,
SfIconMenu,
SfIconArrowBack,
} from '@storefront-ui/react';

export default function TopNavFilled() {
const [inputValue, setInputValue] = useState('');

const actionItems = [
{
icon: <SfIconShoppingCart />,
label: '',
ariaLabel: 'Cart',
role: 'button',
},
{
icon: <SfIconFavorite />,
label: '',
ariaLabel: 'Wishlist',
role: 'button',
},
{
label: 'Log in',
icon: <SfIconPerson />,
ariaLabel: 'Log in',
role: 'login',
},
];

const search = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
alert(`Successfully found 10 results for ${inputValue}`);
};

return (
<header className="flex justify-center w-full py-2 px-4 lg:py-5 lg:px-6 text-white border-0 bg-primary-700">
<div className="flex flex-wrap lg:flex-nowrap justify-between items-center flex-row md:justify-start h-full max-w-[1536px] w-full">
<SfButton variant="tertiary" className="md:hidden text-white" aria-label="Go back">
<SfIconArrowBack />
</SfButton>
<a
href="#"
aria-label="SF Homepage"
className="inline-block mr-4 focus-visible:outline focus-visible:outline-offset focus-visible:rounded-sm shrink-0"
>
<img
src="http://localhost:3100/@assets/vsf_logo_white.svg"
alt="Sf Logo"
className="w-[175px] md:h-6 md:w-[176px] lg:w-[12.5rem] lg:h-[1.75rem]"
/>
</a>
<SfButton variant="tertiary" className="md:hidden text-white" aria-label="Search">
<SfIconSearch />
</SfButton>
<SfButton
aria-label="Open categories"
className="hidden md:block lg:hidden order-first lg:order-1 mr-4 text-white hover:text-white active:text-white hover:bg-primary-800 active:bg-primary-900"
square
variant="tertiary"
>
<SfIconMenu />
</SfButton>
<SfButton
className="hidden lg:flex lg:mr-4 text-white hover:text-white active:text-white hover:bg-primary-800 active:bg-primary-900"
type="button"
variant="tertiary"
slotSuffix={<SfIconExpandMore className="hidden lg:block" />}
>
<span className="hidden lg:flex whitespace-nowrap">Browse products</span>
</SfButton>
<form
role="search"
className="hidden md:flex flex-[100%] order-last lg:order-3 mt-2 lg:mt-0 pb-2 lg:pb-0"
onSubmit={search}
>
<SfInput
value={inputValue}
type="search"
className="[&::-webkit-search-cancel-button]:appearance-none"
placeholder="Search"
wrapperClassName="flex-1 h-10 pr-0"
size="base"
slotSuffix={
<span className="flex items-center">
<SfButton
variant="tertiary"
square
aria-label="search"
type="submit"
className="rounded-l-none hover:bg-transparent active:bg-transparent"
>
<SfIconSearch />
</SfButton>
</span>
}
onChange={(event) => setInputValue(event.target.value)}
/>
</form>
<nav className="flex-1 hidden md:flex justify-end lg:order-last lg:ml-4">
<div className="flex flex-row flex-nowrap">
{actionItems.map((actionItem) => (
<SfButton
key={actionItem.ariaLabel}
className="mr-2 -ml-0.5 rounded-md text-white hover:text-white active:text-white hover:bg-primary-800 active:bg-primary-900"
aria-label={actionItem.ariaLabel}
variant="tertiary"
square
slotPrefix={actionItem.icon}
>
{actionItem.role === 'login' && (
<p className="hidden xl:inline-flex whitespace-nowrap">{actionItem.label}</p>
)}
</SfButton>
))}
</div>
</nav>
</div>
</header>
);
}

// #endregion source
TopNavFilled.getLayout = ShowcasePageLayout;
135 changes: 135 additions & 0 deletions apps/preview/next/pages/showcases/NavbarTop/NavbarTopSimpleMobile.tsx
@@ -0,0 +1,135 @@
/* eslint-disable no-alert */
/* eslint-disable jsx-a11y/anchor-is-valid */
import { ShowcasePageLayout } from '../../showcases';
// #region source
import { useState } from 'react';
import {
SfButton,
SfIconShoppingCart,
SfIconFavorite,
SfIconPerson,
SfIconExpandMore,
SfInput,
SfIconSearch,
SfIconMenu,
SfIconArrowBack,
} from '@storefront-ui/react';

export default function TopNavSimpleMobile() {
const [inputValue, setInputValue] = useState('');

const actionItems = [
{
icon: <SfIconShoppingCart />,
label: '',
ariaLabel: 'Cart',
role: 'button',
},
{
icon: <SfIconFavorite />,
label: '',
ariaLabel: 'Wishlist',
role: 'button',
},
{
label: 'Log in',
icon: <SfIconPerson />,
ariaLabel: 'Log in',
role: 'login',
},
];

const search = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
alert(`Successfully found 10 results for ${inputValue}`);
};

return (
<header className="flex justify-center w-full py-2 px-4 lg:py-5 lg:px-6 bg-white border-b border-neutral-200">
<div className="flex flex-wrap justify-between lg:flex-nowrap items-center flex-row md:justify-start h-full max-w-[1536px] w-full">
<SfButton variant="tertiary" className="md:hidden" aria-label="Go back">
<SfIconArrowBack />
</SfButton>
<a
href="#"
aria-label="SF Homepage"
className="inline-block mr-4 focus-visible:outline focus-visible:outline-offset focus-visible:rounded-sm shrink-0"
>
<img
src="http://localhost:3100/@assets/vsf_logo.svg"
alt="Sf Logo"
className="w-[175px] md:h-6 md:w-[176px] lg:w-[12.5rem] lg:h-[1.75rem]"
/>
</a>
<SfButton variant="tertiary" className="md:hidden" aria-label="Search">
<SfIconSearch />
</SfButton>
<SfButton
aria-label="Open categories"
className="hidden md:block lg:hidden order-first lg:order-1 mr-4"
square
variant="tertiary"
>
<SfIconMenu />
</SfButton>
<SfButton
className="hidden lg:flex lg:mr-4"
type="button"
variant="tertiary"
slotSuffix={<SfIconExpandMore className="hidden lg:block" />}
>
<span className="hidden lg:flex whitespace-nowrap">Browse products</span>
</SfButton>
<form
role="search"
className="hidden md:flex flex-[100%] order-last lg:order-3 mt-2 lg:mt-0 pb-2 lg:pb-0"
onSubmit={search}
>
<SfInput
value={inputValue}
type="search"
className="[&::-webkit-search-cancel-button]:appearance-none"
placeholder="Search"
wrapperClassName="flex-1 h-10 pr-0"
size="base"
slotSuffix={
<span className="flex items-center">
<SfButton
variant="tertiary"
square
aria-label="search"
type="submit"
className="rounded-l-none hover:bg-transparent active:bg-transparent"
>
<SfIconSearch />
</SfButton>
</span>
}
onChange={(event) => setInputValue(event.target.value)}
/>
</form>
<nav className="flex-1 hidden md:flex justify-end lg:order-last lg:ml-4">
<div className="flex flex-row flex-nowrap">
{actionItems.map((actionItem) => (
<SfButton
key={actionItem.ariaLabel}
className="mr-2 -ml-0.5 rounded-md text-primary-700 hover:bg-primary-100 active:bg-primary-200 hover:text-primary-600 active:text-primary-700"
aria-label={actionItem.ariaLabel}
variant="tertiary"
square
slotPrefix={actionItem.icon}
>
{actionItem.role === 'login' && (
<p className="hidden xl:inline-flex whitespace-nowrap">{actionItem.label}</p>
)}
</SfButton>
))}
</div>
</nav>
</div>
</header>
);
}

// #endregion source
TopNavSimpleMobile.getLayout = ShowcasePageLayout;

0 comments on commit e3c66d5

Please sign in to comment.