@shopify/create-hydrogen 1.0.9 → 2.0.2

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/commands/init.js +133 -62
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +12 -8
  6. package/templates/template-hydrogen-default/.devcontainer/devcontainer.json +0 -18
  7. package/templates/template-hydrogen-default/.eslintrc.js +0 -3
  8. package/templates/template-hydrogen-default/.gitignore +0 -7
  9. package/templates/template-hydrogen-default/.stylelintrc.js +0 -17
  10. package/templates/template-hydrogen-default/.vscode/extensions.json +0 -8
  11. package/templates/template-hydrogen-default/README.md +0 -40
  12. package/templates/template-hydrogen-default/_gitignore +0 -80
  13. package/templates/template-hydrogen-default/index.html +0 -20
  14. package/templates/template-hydrogen-default/package.json.liquid +0 -48
  15. package/templates/template-hydrogen-default/postcss.config.js +0 -6
  16. package/templates/template-hydrogen-default/public/favicon.ico +0 -0
  17. package/templates/template-hydrogen-default/shopify.config.js +0 -5
  18. package/templates/template-hydrogen-default/src/App.server.jsx +0 -27
  19. package/templates/template-hydrogen-default/src/components/Button.client.jsx +0 -65
  20. package/templates/template-hydrogen-default/src/components/Cart.client.jsx +0 -265
  21. package/templates/template-hydrogen-default/src/components/CartIcon.jsx +0 -33
  22. package/templates/template-hydrogen-default/src/components/CartIconWithItems.client.jsx +0 -28
  23. package/templates/template-hydrogen-default/src/components/CartProvider.client.jsx +0 -35
  24. package/templates/template-hydrogen-default/src/components/CartToggle.client.jsx +0 -30
  25. package/templates/template-hydrogen-default/src/components/CartUIProvider.client.jsx +0 -45
  26. package/templates/template-hydrogen-default/src/components/CountrySelector.client.jsx +0 -116
  27. package/templates/template-hydrogen-default/src/components/DefaultSeo.server.jsx +0 -36
  28. package/templates/template-hydrogen-default/src/components/FeaturedCollection.jsx +0 -26
  29. package/templates/template-hydrogen-default/src/components/Footer.server.jsx +0 -103
  30. package/templates/template-hydrogen-default/src/components/Gallery.client.jsx +0 -66
  31. package/templates/template-hydrogen-default/src/components/Header.client.jsx +0 -62
  32. package/templates/template-hydrogen-default/src/components/Layout.server.jsx +0 -86
  33. package/templates/template-hydrogen-default/src/components/LoadMoreProducts.client.jsx +0 -56
  34. package/templates/template-hydrogen-default/src/components/LoadingFallback.jsx +0 -26
  35. package/templates/template-hydrogen-default/src/components/MobileCountrySelector.client.jsx +0 -64
  36. package/templates/template-hydrogen-default/src/components/MobileNavigation.client.jsx +0 -98
  37. package/templates/template-hydrogen-default/src/components/MoneyCompareAtPrice.client.jsx +0 -14
  38. package/templates/template-hydrogen-default/src/components/MoneyPrice.client.jsx +0 -15
  39. package/templates/template-hydrogen-default/src/components/Navigation.client.jsx +0 -23
  40. package/templates/template-hydrogen-default/src/components/NotFound.server.jsx +0 -93
  41. package/templates/template-hydrogen-default/src/components/OpenIcon.jsx +0 -33
  42. package/templates/template-hydrogen-default/src/components/ProductCard.jsx +0 -50
  43. package/templates/template-hydrogen-default/src/components/ProductDetails.client.jsx +0 -233
  44. package/templates/template-hydrogen-default/src/components/ProductOptions.client.jsx +0 -49
  45. package/templates/template-hydrogen-default/src/components/Welcome.server.jsx +0 -188
  46. package/templates/template-hydrogen-default/src/index.css +0 -68
  47. package/templates/template-hydrogen-default/src/pages/collections/[handle].server.jsx +0 -105
  48. package/templates/template-hydrogen-default/src/pages/index.server.jsx +0 -241
  49. package/templates/template-hydrogen-default/src/pages/pages/[handle].server.jsx +0 -37
  50. package/templates/template-hydrogen-default/src/pages/products/[handle].server.jsx +0 -66
  51. package/templates/template-hydrogen-default/src/pages/redirect.server.jsx +0 -4
  52. package/templates/template-hydrogen-default/src/pages/robots.txt.server.js +0 -40
  53. package/templates/template-hydrogen-default/src/pages/sitemap.xml.server.jsx +0 -151
  54. package/templates/template-hydrogen-default/src/routes/collections/[handle].server.jsx +0 -105
  55. package/templates/template-hydrogen-default/src/routes/index.server.jsx +0 -241
  56. package/templates/template-hydrogen-default/src/routes/pages/[handle].server.jsx +0 -37
  57. package/templates/template-hydrogen-default/src/routes/products/[handle].server.jsx +0 -66
  58. package/templates/template-hydrogen-default/src/routes/redirect.server.jsx +0 -4
  59. package/templates/template-hydrogen-default/src/routes/robots.txt.server.js +0 -40
  60. package/templates/template-hydrogen-default/src/routes/sitemap.xml.server.jsx +0 -151
  61. package/templates/template-hydrogen-default/tailwind.config.js +0 -26
  62. package/templates/template-hydrogen-default/vite.config.js +0 -10
  63. package/templates/template-hydrogen-minimal/README.md +0 -8
  64. package/templates/template-hydrogen-minimal/package.json +0 -14
@@ -1,116 +0,0 @@
1
- import {useCallback, useMemo} from 'react';
2
- import {useAvailableCountries, useCountry} from '@shopify/hydrogen/client';
3
- import {Listbox} from '@headlessui/react';
4
-
5
- /**
6
- * A client component that selects the appropriate country to display for products on a website
7
- */
8
- export default function CountrySelector() {
9
- const availableCountries = useAvailableCountries();
10
-
11
- const countries = useMemo(
12
- () => [...availableCountries].sort((a, b) => a.name.localeCompare(b.name)),
13
- [availableCountries],
14
- );
15
-
16
- const [selectedCountry, setSelectedCountry] = useCountry();
17
-
18
- const setCountry = useCallback(
19
- (isoCode) => {
20
- setSelectedCountry(
21
- countries.find((country) => country.isoCode === isoCode),
22
- );
23
- },
24
- [countries, setSelectedCountry],
25
- );
26
-
27
- return (
28
- <div className="hidden lg:block">
29
- <Listbox onChange={setCountry}>
30
- {({open}) => (
31
- <>
32
- <Listbox.Button className="font-medium text-sm h-8 p-2 flex items-center">
33
- <span className="mr-4">{selectedCountry.name}</span>
34
- <ArrowIcon isOpen={open} />
35
- </Listbox.Button>
36
-
37
- <Listbox.Options className="absolute z-10 mt-2">
38
- <div className="bg-white p-4 rounded-lg drop-shadow-2xl">
39
- <Listbox.Option
40
- disabled
41
- className="p-2 text-md text-left font-medium uppercase"
42
- >
43
- Country
44
- </Listbox.Option>
45
- {countries.map((country) => {
46
- const isSelected =
47
- country.isoCode === selectedCountry.isoCode;
48
- return (
49
- <Listbox.Option
50
- key={country.isoCode}
51
- value={country.isoCode}
52
- >
53
- {({active}) => (
54
- <div
55
- className={`w-36 py-2 px-3 flex justify-between items-center text-left cursor-pointer rounded
56
- ${active ? 'bg-gray-200' : null}`}
57
- >
58
- {country.name}
59
- {isSelected ? <CheckIcon /> : null}
60
- </div>
61
- )}
62
- </Listbox.Option>
63
- );
64
- })}
65
- </div>
66
- </Listbox.Options>
67
- </>
68
- )}
69
- </Listbox>
70
- </div>
71
- );
72
- }
73
-
74
- export function CheckIcon() {
75
- return (
76
- <svg
77
- width="20"
78
- height="20"
79
- viewBox="0 0 20 20"
80
- fill="none"
81
- xmlns="http://www.w3.org/2000/svg"
82
- aria-hidden="true"
83
- >
84
- <path
85
- d="M7 10L9 12L13 8M19 10C19 14.9706 14.9706 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1C14.9706 1 19 5.02944 19 10Z"
86
- stroke="#354CF6"
87
- strokeWidth="2"
88
- strokeLinecap="round"
89
- strokeLinejoin="round"
90
- />
91
- </svg>
92
- );
93
- }
94
-
95
- export function ArrowIcon({isOpen}) {
96
- return (
97
- <svg
98
- className={`transition-transform duration-300 ${
99
- isOpen ? 'rotate-180' : null
100
- }`}
101
- aria-hidden="true"
102
- width="10"
103
- height="6"
104
- viewBox="0 0 10 6"
105
- fill="none"
106
- xmlns="http://www.w3.org/2000/svg"
107
- >
108
- <path
109
- fillRule="evenodd"
110
- clipRule="evenodd"
111
- d="M0.292893 0.292893C0.683416 -0.097631 1.31658 -0.097631 1.7071 0.292893L4.99999 3.58579L8.29288 0.292893C8.6834 -0.0976311 9.31657 -0.0976311 9.70709 0.292893C10.0976 0.683417 10.0976 1.31658 9.70709 1.70711L5.7071 5.70711C5.31657 6.09763 4.68341 6.09763 4.29289 5.70711L0.292893 1.70711C-0.0976309 1.31658 -0.0976309 0.683417 0.292893 0.292893Z"
112
- fill="#374151"
113
- />
114
- </svg>
115
- );
116
- }
@@ -1,36 +0,0 @@
1
- import {useShopQuery, Seo, CacheDays} from '@shopify/hydrogen';
2
- import gql from 'graphql-tag';
3
-
4
- /**
5
- * A server component that fetches a `shop.name` and sets default values and templates for every page on a website
6
- */
7
- export default function DefaultSeo() {
8
- const {
9
- data: {
10
- shop: {name: shopName, description: shopDescription},
11
- },
12
- } = useShopQuery({
13
- query: QUERY,
14
- cache: CacheDays(),
15
- preload: '*',
16
- });
17
-
18
- return (
19
- <Seo
20
- type="defaultSeo"
21
- data={{
22
- title: shopName,
23
- description: shopDescription,
24
- }}
25
- />
26
- );
27
- }
28
-
29
- const QUERY = gql`
30
- query shopInfo {
31
- shop {
32
- name
33
- description
34
- }
35
- }
36
- `;
@@ -1,26 +0,0 @@
1
- import {Image, Link} from '@shopify/hydrogen';
2
-
3
- /**
4
- * A shared component that defines a single featured collection to display on a storefront
5
- */
6
- export default function FeaturedCollection({collection}) {
7
- return collection ? (
8
- <div className="shadow-xl rounded-xl grid grid-cols-1 lg:grid-cols-2 items-center bg-white overflow-hidden">
9
- {collection.image ? (
10
- <Image width="622" height="465" data={collection.image} />
11
- ) : null}
12
- <div className="px-10 py-10 lg:py-0">
13
- <h2 className="text-gray-700 text-3xl font-bold mb-5">
14
- {collection.title}
15
- </h2>
16
- <p className="text-lg text-gray-500 mb-6">{collection.description}</p>
17
- <Link
18
- to={`/collections/${collection.handle}`}
19
- className="inline-block bg-gray-900 text-white text-lg font-medium rounded-md py-4 px-16 uppercase"
20
- >
21
- Shop Collection
22
- </Link>
23
- </div>
24
- </div>
25
- ) : null;
26
- }
@@ -1,103 +0,0 @@
1
- import {Link} from '@shopify/hydrogen';
2
-
3
- /**
4
- * A server component that specifies the content of the footer on the website
5
- */
6
- export default function Footer({collection, product}) {
7
- return (
8
- <footer role="contentinfo">
9
- <div className="relative bg-white border-t border-b border-black border-opacity-5">
10
- <div className="mx-auto max-w-7xl px-4 py-14 md:px-8 grid grid-cols-1 md:grid-cols-3 gap-12">
11
- <div>
12
- <h2 className="text-md font-medium uppercase mb-4">Community</h2>
13
- <ul className="mt-8 space-y-4">
14
- <li className="text-sm font-medium text-gray-600 hover:text-gray-900">
15
- <a
16
- href="https://github.com/Shopify/hydrogen/discussions"
17
- target="_blank"
18
- rel="noreferrer"
19
- className="flex items-center"
20
- >
21
- <svg
22
- aria-hidden="true"
23
- className="fill-current text-gray-600 mr-3"
24
- width="26"
25
- height="20"
26
- viewBox="0 0 21 20"
27
- fill="none"
28
- xmlns="http://www.w3.org/2000/svg"
29
- >
30
- <path
31
- fillRule="evenodd"
32
- clipRule="evenodd"
33
- d="M10.1319 0.000976562C4.60874 0.000976562 0.135254 4.58917 0.135254 10.2539C0.135254 14.7908 2.99679 18.6229 6.97045 19.9814C7.47028 20.0711 7.65772 19.7635 7.65772 19.4944C7.65772 19.2509 7.64522 18.4434 7.64522 17.5848C5.13357 18.059 4.48379 16.9568 4.28385 16.38C4.17139 16.0853 3.68406 15.1753 3.2592 14.9318C2.90932 14.7396 2.40949 14.2654 3.2467 14.2526C4.03394 14.2397 4.59625 14.9959 4.78369 15.3035C5.68338 16.8542 7.1204 16.4185 7.6952 16.1494C7.78267 15.4829 8.04508 15.0343 8.33249 14.778C6.10824 14.5217 3.78402 13.6374 3.78402 9.71564C3.78402 8.60063 4.17139 7.67786 4.80868 6.96016C4.70871 6.70383 4.35883 5.65291 4.90864 4.24313C4.90864 4.24313 5.74586 3.97399 7.65772 5.29406C8.45745 5.06336 9.30716 4.94802 10.1569 4.94802C11.0066 4.94802 11.8563 5.06336 12.656 5.29406C14.5679 3.96117 15.4051 4.24313 15.4051 4.24313C15.9549 5.65291 15.605 6.70383 15.5051 6.96016C16.1424 7.67786 16.5297 8.58781 16.5297 9.71564C16.5297 13.6502 14.193 14.5217 11.9688 14.778C12.3311 15.0984 12.6435 15.7136 12.6435 16.6748C12.6435 18.0461 12.631 19.1483 12.631 19.4944C12.631 19.7635 12.8185 20.0839 13.3183 19.9814C15.3028 19.2943 17.0273 17.9861 18.2489 16.2411C19.4706 14.4962 20.128 12.4022 20.1285 10.2539C20.1285 4.58917 15.655 0.000976562 10.1319 0.000976562Z"
34
- />
35
- </svg>
36
- Github discussions
37
- </a>
38
- </li>
39
- <li className="text-sm font-medium text-gray-600 hover:text-gray-900">
40
- <a
41
- href="https://discord.gg/ppSbThrFaS"
42
- target="_blank"
43
- rel="noreferrer"
44
- className="flex items-center"
45
- >
46
- <svg
47
- aria-hidden="true"
48
- className="fill-current text-gray-600 mr-3"
49
- width="26"
50
- height="20"
51
- viewBox="0 0 26 20"
52
- fill="none"
53
- xmlns="http://www.w3.org/2000/svg"
54
- >
55
- <path d="M21.3103 1.67597C19.691 0.893476 17.9595 0.324791 16.1494 0.000976562C15.9271 0.416095 15.6673 0.974439 15.4883 1.4186C13.564 1.11972 11.6574 1.11972 9.76855 1.4186C9.58952 0.974439 9.3239 0.416095 9.0996 0.000976562C7.28746 0.324791 5.55403 0.895566 3.93472 1.68012C0.668559 6.77767 -0.216844 11.7486 0.225859 16.649C2.39215 18.3198 4.49155 19.3348 6.55551 19.9989C7.06512 19.2745 7.51962 18.5045 7.91116 17.693C7.16546 17.4003 6.45123 17.0392 5.77638 16.6199C5.95541 16.4829 6.13054 16.3397 6.29973 16.1923C10.4159 18.1807 14.8882 18.1807 18.9551 16.1923C19.1263 16.3397 19.3014 16.4829 19.4785 16.6199C18.8016 17.0412 18.0855 17.4024 17.3398 17.6951C17.7313 18.5045 18.1838 19.2766 18.6954 20.001C20.7614 19.3368 22.8627 18.3219 25.029 16.649C25.5484 10.9682 24.1416 6.04292 21.3103 1.67597ZM8.47192 13.6353C7.2363 13.6353 6.22299 12.4439 6.22299 10.9931C6.22299 9.5423 7.21466 8.34886 8.47192 8.34886C9.72922 8.34886 10.7425 9.54021 10.7209 10.9931C10.7228 12.4439 9.72922 13.6353 8.47192 13.6353ZM16.7829 13.6353C15.5473 13.6353 14.534 12.4439 14.534 10.9931C14.534 9.5423 15.5256 8.34886 16.7829 8.34886C18.0402 8.34886 19.0535 9.54021 19.0319 10.9931C19.0319 12.4439 18.0402 13.6353 16.7829 13.6353Z" />
56
- </svg>
57
- Discord
58
- </a>
59
- </li>
60
- </ul>
61
- </div>
62
- <div>
63
- <h2 className="text-md font-medium uppercase mb-4">Templates</h2>
64
- <ul className="mt-8 space-y-4">
65
- <li className="flex items-center text-sm font-medium text-gray-600 hover:text-gray-900">
66
- <Link to="/home">Home</Link>
67
- </li>
68
- <li className="flex items-center text-sm font-medium text-gray-600 hover:text-gray-900">
69
- <Link to={`/products/${product?.handle}`}>Product</Link>
70
- </li>
71
- <li className="flex items-center text-sm font-medium text-gray-600 hover:text-gray-900">
72
- <Link to={`/collections/${collection?.handle}`}>
73
- Collection
74
- </Link>
75
- </li>
76
- <li className="flex items-center text-sm font-medium text-gray-600 hover:text-gray-900">
77
- <Link to="/404">404</Link>
78
- </li>
79
- </ul>
80
- </div>
81
- <div>
82
- <h2 className="text-md font-medium uppercase mb-4">Docs</h2>
83
- <ul className="mt-8 space-y-4">
84
- <li className="flex items-center text-sm font-medium text-gray-600 hover:text-gray-900">
85
- <a href="https://shopify.dev/custom-storefronts/hydrogen">
86
- Hydrogen overview
87
- </a>
88
- </li>
89
- <li className="flex items-center text-sm font-medium text-gray-600 hover:text-gray-900">
90
- <a href="https://shopify.dev/custom-storefronts/hydrogen/reference">
91
- Hydrogen reference
92
- </a>
93
- </li>
94
- </ul>
95
- </div>
96
- </div>
97
- </div>
98
- <div className="py-6 px-4 md:px-8 bg-gray-50">
99
- <p className="text-gray-600">© {new Date().getFullYear()} Shopify</p>
100
- </div>
101
- </footer>
102
- );
103
- }
@@ -1,66 +0,0 @@
1
- import {useProduct, MediaFile, Image} from '@shopify/hydrogen/client';
2
-
3
- /**
4
- * A client component that defines a media gallery for hosting images, 3D models, and videos of products
5
- */
6
- export default function Gallery() {
7
- const {media, selectedVariant} = useProduct();
8
-
9
- const featuredMedia = selectedVariant.image || media[0]?.image;
10
- const featuredMediaSrc = featuredMedia?.url.split('?')[0];
11
- const galleryMedia = media.filter((med) => {
12
- if (
13
- med.mediaContentType === MODEL_3D_TYPE ||
14
- med.mediaContentType === VIDEO_TYPE ||
15
- med.mediaContentType === EXTERNAL_VIDEO_TYPE
16
- ) {
17
- return true;
18
- }
19
-
20
- return !med.image.url.includes(featuredMediaSrc);
21
- });
22
-
23
- if (!media.length) {
24
- return null;
25
- }
26
-
27
- return (
28
- <div
29
- className="gap-4 flex md:grid md:grid-cols-2 overflow-x-scroll no-scrollbar scroll-snap-x scroll-smooth h-[485px] md:h-auto place-content-start"
30
- tabIndex="-1"
31
- >
32
- <Image
33
- data={selectedVariant.image}
34
- className="w-[80vw] md:w-full h-full md:h-auto object-cover object-center flex-shrink-0 md:flex-shrink-none snap-start md:col-span-2 border border-gray-200 rounded-lg"
35
- />
36
- {galleryMedia.map((med) => {
37
- let extraProps = {};
38
-
39
- if (med.mediaContentType === MODEL_3D_TYPE) {
40
- extraProps = MODEL_3D_PROPS;
41
- }
42
-
43
- return (
44
- <MediaFile
45
- tabIndex="0"
46
- key={med.id || med.image.id}
47
- className="w-[80vw] md:w-auto h-full md:h-auto object-cover object-center transition-all snap-start border border-gray-200 flex-shrink-0 rounded-lg"
48
- data={med}
49
- options={{
50
- height: '485',
51
- crop: 'center',
52
- }}
53
- {...extraProps}
54
- />
55
- );
56
- })}
57
- </div>
58
- );
59
- }
60
-
61
- const MODEL_3D_TYPE = 'MODEL_3D';
62
- const MODEL_3D_PROPS = {
63
- interactionPromptThreshold: '0',
64
- };
65
- const VIDEO_TYPE = 'VIDEO';
66
- const EXTERNAL_VIDEO_TYPE = 'EXTERNAL_VIDEO';
@@ -1,62 +0,0 @@
1
- import {useEffect, useState} from 'react';
2
- import {Link} from '@shopify/hydrogen/client';
3
-
4
- import CartToggle from './CartToggle.client';
5
- import {useCartUI} from './CartUIProvider.client';
6
- import CountrySelector from './CountrySelector.client';
7
- import Navigation from './Navigation.client';
8
- import MobileNavigation from './MobileNavigation.client';
9
-
10
- /**
11
- * A client component that specifies the content of the header on the website
12
- */
13
- export default function Header({collections, storeName}) {
14
- const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
15
- const [scrollbarWidth, setScrollbarWidth] = useState(0);
16
- const {isCartOpen} = useCartUI();
17
-
18
- useEffect(() => {
19
- const scrollbarWidth =
20
- window.innerWidth - document.documentElement.clientWidth;
21
-
22
- setScrollbarWidth(scrollbarWidth);
23
- }, [isCartOpen]);
24
-
25
- return (
26
- <header className="h-20 lg:h-32" role="banner">
27
- <div
28
- className={`fixed z-20 h-20 lg:h-32 w-full border-b border-gray-200 px-6 md:px-8 md:py-6 lg:pt-8 lg:pb-0 mx-auto bg-white ${
29
- isMobileNavOpen ? '' : 'bg-opacity-95'
30
- }`}
31
- >
32
- <div
33
- className="h-full flex lg:flex-col place-content-between"
34
- style={{
35
- paddingRight: isCartOpen ? scrollbarWidth : 0,
36
- }}
37
- >
38
- <div className="text-center w-full flex justify-between items-center">
39
- <CountrySelector />
40
- <MobileNavigation
41
- collections={collections}
42
- isOpen={isMobileNavOpen}
43
- setIsOpen={setIsMobileNavOpen}
44
- />
45
- <Link
46
- className="font-black uppercase text-3xl tracking-widest"
47
- to="/"
48
- >
49
- {storeName}
50
- </Link>
51
- <CartToggle
52
- handleClick={() => {
53
- if (isMobileNavOpen) setIsMobileNavOpen(false);
54
- }}
55
- />
56
- </div>
57
- <Navigation collections={collections} storeName={storeName} />
58
- </div>
59
- </div>
60
- </header>
61
- );
62
- }
@@ -1,86 +0,0 @@
1
- import {
2
- Image,
3
- useShopQuery,
4
- flattenConnection,
5
- LocalizationProvider,
6
- CacheHours,
7
- } from '@shopify/hydrogen';
8
- import gql from 'graphql-tag';
9
-
10
- import Header from './Header.client';
11
- import Footer from './Footer.server';
12
- import Cart from './Cart.client';
13
- import {Suspense} from 'react';
14
-
15
- /**
16
- * A server component that defines a structure and organization of a page that can be used in different parts of the Hydrogen app
17
- */
18
- export default function Layout({children, hero}) {
19
- const {data} = useShopQuery({
20
- query: QUERY,
21
- variables: {
22
- numCollections: 3,
23
- },
24
- cache: CacheHours(),
25
- preload: '*',
26
- });
27
- const collections = data ? flattenConnection(data.collections) : null;
28
- const products = data ? flattenConnection(data.products) : null;
29
- const storeName = data ? data.shop.name : '';
30
-
31
- return (
32
- <LocalizationProvider preload="*">
33
- <div className="absolute top-0 left-0">
34
- <a
35
- href="#mainContent"
36
- className="p-4 focus:block sr-only focus:not-sr-only"
37
- >
38
- Skip to content
39
- </a>
40
- </div>
41
- <div className="min-h-screen max-w-screen text-gray-700 font-sans">
42
- {/* TODO: Find out why Suspense needs to be here to prevent hydration errors. */}
43
- <Suspense fallback={null}>
44
- <Header collections={collections} storeName={storeName} />
45
- <Cart />
46
- </Suspense>
47
- <main role="main" id="mainContent" className="relative bg-gray-50">
48
- {hero}
49
- <div className="mx-auto max-w-7xl p-4 md:py-5 md:px-8">
50
- {children}
51
- </div>
52
- </main>
53
- <Footer collection={collections[0]} product={products[0]} />
54
- </div>
55
- </LocalizationProvider>
56
- );
57
- }
58
-
59
- const QUERY = gql`
60
- query layoutContent($numCollections: Int!) {
61
- shop {
62
- name
63
- }
64
- collections(first: $numCollections) {
65
- edges {
66
- node {
67
- description
68
- handle
69
- id
70
- title
71
- image {
72
- ...ImageFragment
73
- }
74
- }
75
- }
76
- }
77
- products(first: 1) {
78
- edges {
79
- node {
80
- handle
81
- }
82
- }
83
- }
84
- }
85
- ${Image.Fragment}
86
- `;
@@ -1,56 +0,0 @@
1
- import {useServerState} from '@shopify/hydrogen/client';
2
-
3
- /**
4
- * A client component that provides functionality to initially show a subset of products and a button to load more products
5
- */
6
- export default function LoadMoreProducts({startingCount}) {
7
- const {pending, serverState, setServerState} = useServerState();
8
-
9
- return (
10
- <div className="flex justify-center h-14">
11
- {pending ? (
12
- <SpinnerIcon />
13
- ) : (
14
- <button
15
- type="button"
16
- disabled={pending}
17
- className={`uppercase border-4 bg-white border-black text-black text-center px-5 py-3 font-mono font-bold drop-shadow-lg active:drop-shadow-none hover:bg-black hover:text-white hover:border-white ${
18
- pending ? 'opacity-50' : undefined
19
- }`}
20
- onClick={() => {
21
- setServerState(
22
- 'collectionProductCount',
23
- serverState.collectionProductCount
24
- ? serverState.collectionProductCount + 24
25
- : startingCount + 1,
26
- );
27
- }}
28
- >
29
- Load more
30
- </button>
31
- )}
32
- </div>
33
- );
34
- }
35
-
36
- function SpinnerIcon() {
37
- return (
38
- <svg
39
- width="54"
40
- height="54"
41
- viewBox="0 0 54 54"
42
- fill="none"
43
- xmlns="http://www.w3.org/2000/svg"
44
- className="animate-spin"
45
- >
46
- <path
47
- d="M43.6663 27.0002C43.6663 36.2049 36.2044 43.6668 26.9997 43.6668C17.7949 43.6668 10.333 36.2049 10.333 27.0002C10.333 17.7954 17.7949 10.3335 26.9997 10.3335C36.2044 10.3335 43.6663 17.7954 43.6663 27.0002ZM13.6663 27.0002C13.6663 34.364 19.6359 40.3335 26.9997 40.3335C34.3635 40.3335 40.333 34.364 40.333 27.0002C40.333 19.6364 34.3635 13.6668 26.9997 13.6668C19.6359 13.6668 13.6663 19.6364 13.6663 27.0002Z"
48
- fill="#E6E7EB"
49
- />
50
- <path
51
- d="M26.9997 10.3332C29.1884 10.3332 31.3556 10.7643 33.3777 11.6018C35.3998 12.4394 37.2371 13.6671 38.7848 15.2147C40.3324 16.7624 41.5601 18.5997 42.3977 20.6218C43.2352 22.6439 43.6663 24.8111 43.6663 26.9998L40.333 26.9998C40.333 25.2489 39.9881 23.5151 39.3181 21.8974C38.648 20.2797 37.6659 18.8099 36.4278 17.5717C35.1896 16.3336 33.7198 15.3515 32.1021 14.6814C30.4844 14.0114 28.7506 13.6665 26.9997 13.6665L26.9997 10.3332Z"
52
- fill="black"
53
- />
54
- </svg>
55
- );
56
- }
@@ -1,26 +0,0 @@
1
- import CartIcon from './CartIcon';
2
- import OpenIcon from './OpenIcon';
3
-
4
- /**
5
- * A shared component and Suspense call that's used in `App.server.jsx` to let your app wait for code to load while declaring a loading state
6
- */
7
- export default function LoadingFallback() {
8
- return (
9
- <header className="h-20 lg:h-32 max-w-screen text-gray-700">
10
- <div className="fixed z-10 h-20 lg:h-32 w-full bg-white/90 border-b border-black border-opacity-5 px-6 md:px-8 md:py-6 lg:pt-8 lg:pb-0 mx-auto">
11
- <div className="h-full flex lg:flex-col place-content-between">
12
- <div className="text-center w-full flex justify-between items-center">
13
- <div className="hidden lg:block w-16" />
14
- <div className="lg:hidden flex justify-center items-center w-7 h-full">
15
- <OpenIcon />
16
- </div>
17
- <p className="font-black uppercase text-3xl tracking-widest">
18
- Snowdevil
19
- </p>
20
- <CartIcon />
21
- </div>
22
- </div>
23
- </div>
24
- </header>
25
- );
26
- }
@@ -1,64 +0,0 @@
1
- import {useCallback} from 'react';
2
- import {useAvailableCountries, useCountry} from '@shopify/hydrogen/client';
3
- import {Listbox} from '@headlessui/react';
4
-
5
- import {ArrowIcon, CheckIcon} from './CountrySelector.client';
6
-
7
- /**
8
- * A client component that selects the appropriate country to display for products on a mobile storefront
9
- */
10
- export default function MobileCountrySelector() {
11
- const countries = [...useAvailableCountries()].sort((a, b) =>
12
- a.name.localeCompare(b.name),
13
- );
14
- const [selectedCountry, setSelectedCountry] = useCountry();
15
-
16
- const setCountry = useCallback(
17
- (isoCode) => {
18
- setSelectedCountry(
19
- countries.find((country) => country.isoCode === isoCode),
20
- );
21
- },
22
- [countries, setSelectedCountry],
23
- );
24
-
25
- return (
26
- <div className="mt-8 rounded border border-gray-200 w-full">
27
- <Listbox onChange={setCountry}>
28
- {({open}) => (
29
- <>
30
- <Listbox.Button className="w-full flex justify-between text-sm items-center py-5 px-7">
31
- {selectedCountry.name}
32
- <ArrowIcon isOpen={open} />
33
- </Listbox.Button>
34
- <Listbox.Options className="w-full px-3 pb-2 text-lg">
35
- <Listbox.Option
36
- disabled
37
- className="font-medium px-4 pb-4 w-full text-left uppercase"
38
- >
39
- Country
40
- </Listbox.Option>
41
- {countries.map((country) => {
42
- const isSelected = country.isoCode === selectedCountry.isoCode;
43
- return (
44
- <Listbox.Option key={country.isoCode} value={country.isoCode}>
45
- {({active}) => (
46
- <div
47
- className={`py-2 px-4 rounded flex justify-between items-center text-left w-full cursor-pointer ${
48
- active ? 'bg-gray-100' : null
49
- }`}
50
- >
51
- {country.name}
52
- {isSelected ? <CheckIcon /> : null}
53
- </div>
54
- )}
55
- </Listbox.Option>
56
- );
57
- })}
58
- </Listbox.Options>
59
- </>
60
- )}
61
- </Listbox>
62
- </div>
63
- );
64
- }