Files
vercel/examples/hydrogen-2/app/components/Layout.tsx
Nathan Rajlich 97659c687b [examples] Add "hydrogen-2" template (#10319)
Adds a Hydrogen v2 template which is the output of the `npm create @shopify/hydrogen@latest` command.

Note that a `vercel.json` file is being used to define the environment variables that are required at runtime. This is required for the template to deploy with zero configuration, however the user should update these values (including replacing the session secret) and migrate them to the Project settings in the Vercel dashboard.

[Live example](https://hydrogen-v2-template.vercel.app)
2023-08-10 00:11:33 +00:00

96 lines
2.3 KiB
TypeScript

import {Await} from '@remix-run/react';
import {Suspense} from 'react';
import type {
CartApiQueryFragment,
FooterQuery,
HeaderQuery,
} from 'storefrontapi.generated';
import {Aside} from '~/components/Aside';
import {Footer} from '~/components/Footer';
import {Header, HeaderMenu} from '~/components/Header';
import {CartMain} from '~/components/Cart';
import {
PredictiveSearchForm,
PredictiveSearchResults,
} from '~/components/Search';
export type LayoutProps = {
cart: Promise<CartApiQueryFragment | null>;
children?: React.ReactNode;
footer: Promise<FooterQuery>;
header: HeaderQuery;
isLoggedIn: boolean;
};
export function Layout({
cart,
children = null,
footer,
header,
isLoggedIn,
}: LayoutProps) {
return (
<>
<CartAside cart={cart} />
<SearchAside />
<MobileMenuAside menu={header.menu} />
<Header header={header} cart={cart} isLoggedIn={isLoggedIn} />
<main>{children}</main>
<Suspense>
<Await resolve={footer}>
{(footer) => <Footer menu={footer.menu} />}
</Await>
</Suspense>
</>
);
}
function CartAside({cart}: {cart: LayoutProps['cart']}) {
return (
<Aside id="cart-aside" heading="CART">
<Suspense fallback={<p>Loading cart ...</p>}>
<Await resolve={cart}>
{(cart) => {
return <CartMain cart={cart} layout="aside" />;
}}
</Await>
</Suspense>
</Aside>
);
}
function SearchAside() {
return (
<Aside id="search-aside" heading="SEARCH">
<div className="predictive-search">
<br />
<PredictiveSearchForm>
{({fetchResults, inputRef}) => (
<div>
<input
name="q"
onChange={fetchResults}
onFocus={fetchResults}
placeholder="Search"
ref={inputRef}
type="search"
/>
&nbsp;
<button type="submit">Search</button>
</div>
)}
</PredictiveSearchForm>
<PredictiveSearchResults />
</div>
</Aside>
);
}
function MobileMenuAside({menu}: {menu: HeaderQuery['menu']}) {
return (
<Aside id="mobile-menu-aside" heading="MENU">
<HeaderMenu menu={menu} viewport="mobile" />
</Aside>
);
}