top section complete

This commit is contained in:
Sol Irvine 2023-08-13 13:39:20 +09:00
parent 7dfc481d40
commit d4ea4ac8d2
23 changed files with 185 additions and 101 deletions

View File

@ -1,6 +1,6 @@
module.exports = { module.exports = {
extends: ['next', 'prettier'], extends: ['next', 'prettier', 'plugin:tailwindcss/recommended'],
plugins: ['unicorn'], plugins: ['unicorn', 'prettier', 'tailwindcss', 'unused-imports'],
rules: { rules: {
'no-unused-vars': [ 'no-unused-vars': [
'error', 'error',
@ -18,6 +18,32 @@ module.exports = {
{ {
case: 'kebabCase' case: 'kebabCase'
} }
],
"prettier/prettier": "warn",
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"no-template-curly-in-string": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_"
}
]
},
"settings": {
"tailwindcss": {
"config": "./tailwind.config.js",
"callees": ["cx"]
},
"tailwindcss/classnames-order": [
true,
{
"callees": ["cx"],
"config": "./tailwind.config.js"
}
] ]
} }
}; };

View File

@ -3,6 +3,7 @@
"typescript.enablePromptUseWorkspaceTsdk": true, "typescript.enablePromptUseWorkspaceTsdk": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll": true, "source.fixAll": true,
"source.addMissingImports": true,
"source.organizeImports": true, "source.organizeImports": true,
"source.sortMembers": true "source.sortMembers": true
} }

View File

@ -37,11 +37,13 @@ const inter = Inter({
export default async function RootLayout({ children }: { children: ReactNode }) { export default async function RootLayout({ children }: { children: ReactNode }) {
return ( return (
<html lang="en" className={inter.variable}> <html lang="en" className={inter.variable}>
<body className="bg-neutral-50 text-black selection:bg-teal-300 dark:bg-neutral-900 dark:text-white dark:selection:bg-pink-500 dark:selection:text-white"> <body className="bg-dark text-white selection:bg-green-800 selection:text-green-400">
<div className="mx-auto max-w-screen-2xl">
<Navbar /> <Navbar />
<Suspense> <Suspense>
<main>{children}</main> <main>{children}</main>
</Suspense> </Suspense>
</div>
</body> </body>
</html> </html>
); );

View File

@ -1,6 +1,8 @@
import { Carousel } from 'components/carousel'; import { Carousel } from 'components/carousel';
import { ThreeItemGrid } from 'components/grid/three-items'; import { ThreeItemGrid } from 'components/grid/three-items';
import Footer from 'components/layout/footer'; import Footer from 'components/layout/footer';
import Image from 'next/image';
import Namemark from 'public/assets/images/namemark.png';
import { Suspense } from 'react'; import { Suspense } from 'react';
export const runtime = 'edge'; export const runtime = 'edge';
@ -15,6 +17,9 @@ export const metadata = {
export default async function HomePage() { export default async function HomePage() {
return ( return (
<> <>
<div className="px-12 pb-12">
<Image src={Namemark} alt="narai by suginomori brewery" />
</div>
<ThreeItemGrid /> <ThreeItemGrid />
<Suspense> <Suspense>
<Carousel /> <Carousel />

View File

@ -1,4 +1,4 @@
import { ShoppingCartIcon } from '@heroicons/react/24/outline'; import { ShoppingBagIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx'; import clsx from 'clsx';
export default function OpenCart({ export default function OpenCart({
@ -9,13 +9,17 @@ export default function OpenCart({
quantity?: number; quantity?: number;
}) { }) {
return ( return (
<div className="relative flex h-11 w-11 items-center justify-center rounded-md border border-neutral-200 text-black transition-colors dark:border-neutral-700 dark:text-white"> <div className="relative flex h-11 w-11 items-center justify-center">
<ShoppingCartIcon <ShoppingBagIcon
className={clsx('h-4 transition-all ease-in-out hover:scale-110 ', className)} className={clsx(
'h-10 stroke-current transition-all ease-in-out hover:scale-110',
className
)}
strokeWidth={0.7}
/> />
{quantity ? ( {quantity ? (
<div className="absolute right-0 top-0 -mr-2 -mt-2 h-4 w-4 rounded bg-blue-600 text-[11px] font-medium text-white"> <div className="absolute right-[23%] top-[85%] -mr-2 -mt-2 h-5 w-5 -translate-x-1/2 -translate-y-1/2 transform text-[12px] font-medium text-white">
{quantity} {quantity}
</div> </div>
) : null} ) : null}

File diff suppressed because one or more lines are too long

18
components/icons/menu.tsx Normal file
View File

@ -0,0 +1,18 @@
export default function MenuIcon(props: React.ComponentProps<'svg'>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={0.7}
stroke="currentColor"
className="h-10 w-10"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
/>
</svg>
);
}

View File

@ -15,10 +15,10 @@ export default async function Footer() {
const copyrightName = COMPANY_NAME || SITE_NAME || ''; const copyrightName = COMPANY_NAME || SITE_NAME || '';
return ( return (
<footer className="text-sm text-neutral-500 dark:text-neutral-400"> <footer className="text-sm">
<div className="mx-auto flex w-full max-w-7xl flex-col gap-6 border-t border-neutral-200 px-6 py-12 text-sm dark:border-neutral-700 md:flex-row md:gap-12 md:px-4 xl:px-0"> <div className="mx-auto flex w-full max-w-7xl flex-col gap-6 border-t border-white/20 px-6 py-12 text-sm md:flex-row md:gap-12 md:px-4 xl:px-0">
<div> <div>
<Link className="flex items-center gap-2 text-black dark:text-white md:pt-1" href="/"> <Link className="flex items-center gap-2 md:pt-1" href="/">
<LogoSquare size="sm" /> <LogoSquare size="sm" />
<span className="uppercase">{SITE_NAME}</span> <span className="uppercase">{SITE_NAME}</span>
</Link> </Link>
@ -37,32 +37,15 @@ export default async function Footer() {
> >
<FooterMenu menu={menu} /> <FooterMenu menu={menu} />
</Suspense> </Suspense>
<div className="md:ml-auto">
<a
className="flex h-8 flex-none items-center justify-center rounded-md border border-neutral-200 bg-white text-xs text-black dark:border-neutral-700 dark:bg-black dark:text-white"
aria-label="Deploy on Vercel"
href="https://vercel.com/templates/next.js/nextjs-commerce"
>
<span className="px-3"></span>
<hr className="h-full border-r border-neutral-200 dark:border-neutral-700" />
<span className="px-3">Deploy</span>
</a>
</div> </div>
</div> <div className="border-t border-white/20 py-6 text-sm dark:border-neutral-700">
<div className="border-t border-neutral-200 py-6 text-sm dark:border-neutral-700">
<div className="mx-auto flex w-full max-w-7xl flex-col items-center gap-1 px-4 md:flex-row md:gap-0 md:px-4 xl:px-0"> <div className="mx-auto flex w-full max-w-7xl flex-col items-center gap-1 px-4 md:flex-row md:gap-0 md:px-4 xl:px-0">
<p> <p>
&copy; {copyrightDate} {copyrightName} &copy; {copyrightDate} {copyrightName}
{copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved. {copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved.
</p> </p>
<hr className="mx-4 hidden h-4 w-[1px] border-l border-neutral-400 md:inline-block" /> <hr className="mx-4 hidden h-4 w-[1px] border-l border-neutral-400 md:inline-block" />
<p>Designed in California</p> <p>Designed in Japan</p>
<p className="md:ml-auto">
Crafted by{' '}
<a href="https://vercel.com" className="text-black dark:text-white">
Vercel
</a>
</p>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -1,57 +1,18 @@
import Cart from 'components/cart'; import Cart from 'components/cart';
import OpenCart from 'components/cart/open-cart'; import OpenCart from 'components/cart/open-cart';
import LogoSquare from 'components/logo-square'; import Menu from 'components/menu';
import { getMenu } from 'lib/shopify';
import { Menu } from 'lib/shopify/types';
import Link from 'next/link';
import { Suspense } from 'react'; import { Suspense } from 'react';
import MobileMenu from './mobile-menu';
import Search from './search';
const { SITE_NAME } = process.env;
export default async function Navbar() { export default async function Navbar() {
const menu = await getMenu('next-js-frontend-header-menu');
return ( return (
<nav className="relative flex items-center justify-between p-4 lg:px-6"> <nav className="sticky top-12 z-10">
<div className="block flex-none md:hidden"> <div className="flex w-full justify-end pr-12">
<MobileMenu menu={menu} />
</div>
<div className="flex w-full items-center">
<div className="flex w-full md:w-1/3">
<Link
href="/"
aria-label="Go back home"
className="mr-2 flex w-full items-center justify-center md:w-auto lg:mr-6"
>
<LogoSquare />
<div className="ml-2 flex-none text-sm font-medium uppercase md:hidden lg:block">
{SITE_NAME}
</div>
</Link>
{menu.length ? (
<ul className="hidden gap-6 text-sm md:flex md:items-center">
{menu.map((item: Menu) => (
<li key={item.title}>
<Link
href={item.path}
className="text-neutral-500 underline-offset-4 hover:text-black hover:underline dark:text-neutral-400 dark:hover:text-neutral-300"
>
{item.title}
</Link>
</li>
))}
</ul>
) : null}
</div>
<div className="hidden justify-center md:flex md:w-1/3">
<Search />
</div>
<div className="flex justify-end md:w-1/3">
<Suspense fallback={<OpenCart />}> <Suspense fallback={<OpenCart />}>
<div className="flex flex-row items-center justify-center space-x-6">
<Cart /> <Cart />
</Suspense> <Menu />
</div> </div>
</Suspense>
</div> </div>
</nav> </nav>
); );

View File

@ -4,13 +4,10 @@ import LogoIcon from './icons/logo';
export default function LogoSquare({ size }: { size?: 'sm' | undefined }) { export default function LogoSquare({ size }: { size?: 'sm' | undefined }) {
return ( return (
<div <div
className={clsx( className={clsx('flex flex-none items-center justify-center', {
'flex flex-none items-center justify-center border border-neutral-200 bg-white dark:border-neutral-700 dark:bg-black',
{
'h-[40px] w-[40px] rounded-xl': !size, 'h-[40px] w-[40px] rounded-xl': !size,
'h-[30px] w-[30px] rounded-lg': size === 'sm' 'h-[30px] w-[30px] rounded-lg': size === 'sm'
} })}
)}
> >
<LogoIcon <LogoIcon
className={clsx({ className={clsx({

11
components/menu/index.tsx Normal file
View File

@ -0,0 +1,11 @@
'use client';
import MenuIcon from 'components/icons/menu';
export default function Menu() {
return (
<button type="button" onClick={() => console.debug('showmenu')}>
<MenuIcon />
</button>
);
}

View File

@ -26,7 +26,10 @@
"@headlessui/react": "^1.7.15", "@headlessui/react": "^1.7.15",
"@heroicons/react": "^2.0.18", "@heroicons/react": "^2.0.18",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"eslint-plugin-tailwindcss": "^3.13.0",
"eslint-plugin-unused-imports": "^3.0.0",
"next": "13.4.13-canary.15", "next": "13.4.13-canary.15",
"prettier-plugin-organize-imports": "^3.2.3",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0" "react-dom": "18.2.0"
}, },

View File

@ -4,7 +4,8 @@ module.exports = {
trailingComma: 'none', trailingComma: 'none',
printWidth: 100, printWidth: 100,
tabWidth: 2, tabWidth: 2,
// pnpm doesn't support plugin autoloading useTabs: false,
// https://github.com/tailwindlabs/prettier-plugin-tailwindcss#installation semi: true,
plugins: [require('prettier-plugin-tailwindcss')] proseWrap: 'never',
plugins: ['prettier-plugin-organize-imports', 'prettier-plugin-tailwindcss']
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,10 +1,14 @@
const plugin = require('tailwindcss/plugin'); const plugin = require('tailwindcss/plugin');
const colors = require('tailwindcss/colors');
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], content: ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
theme: { theme: {
extend: { extend: {
colors: {
dark: '#212720'
},
fontFamily: { fontFamily: {
sans: ['var(--font-inter)'] sans: ['var(--font-inter)']
}, },

View File

@ -1183,11 +1183,14 @@ __metadata:
eslint: ^8.45.0 eslint: ^8.45.0
eslint-config-next: ^13.4.12 eslint-config-next: ^13.4.12
eslint-config-prettier: ^8.8.0 eslint-config-prettier: ^8.8.0
eslint-plugin-tailwindcss: ^3.13.0
eslint-plugin-unicorn: ^48.0.0 eslint-plugin-unicorn: ^48.0.0
eslint-plugin-unused-imports: ^3.0.0
lint-staged: ^13.2.3 lint-staged: ^13.2.3
next: 13.4.13-canary.15 next: 13.4.13-canary.15
postcss: ^8.4.27 postcss: ^8.4.27
prettier: 3.0.1 prettier: 3.0.1
prettier-plugin-organize-imports: ^3.2.3
prettier-plugin-tailwindcss: ^0.4.1 prettier-plugin-tailwindcss: ^0.4.1
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0 react-dom: 18.2.0
@ -1706,6 +1709,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-tailwindcss@npm:^3.13.0":
version: 3.13.0
resolution: "eslint-plugin-tailwindcss@npm:3.13.0"
dependencies:
fast-glob: ^3.2.5
postcss: ^8.4.4
peerDependencies:
tailwindcss: ^3.3.2
checksum: 0ed226300b613987e59d1374c611c374add3205b73647e8ec910ad2409a2a07f9605cb7e6e7a34bda7702946681aef4a289c6b6bcf9f1357fa6bc4e0ee8f508b
languageName: node
linkType: hard
"eslint-plugin-unicorn@npm:^48.0.0": "eslint-plugin-unicorn@npm:^48.0.0":
version: 48.0.1 version: 48.0.1
resolution: "eslint-plugin-unicorn@npm:48.0.1" resolution: "eslint-plugin-unicorn@npm:48.0.1"
@ -1731,6 +1746,28 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-unused-imports@npm:^3.0.0":
version: 3.0.0
resolution: "eslint-plugin-unused-imports@npm:3.0.0"
dependencies:
eslint-rule-composer: ^0.3.0
peerDependencies:
"@typescript-eslint/eslint-plugin": ^6.0.0
eslint: ^8.0.0
peerDependenciesMeta:
"@typescript-eslint/eslint-plugin":
optional: true
checksum: 51666f62cc8dccba2895ced83f3c1e0b78b68c357e17360e156c4db548bfdeda34cbd8725192fb4903f22d5069400fb22ded6039631df01ee82fd618dc307247
languageName: node
linkType: hard
"eslint-rule-composer@npm:^0.3.0":
version: 0.3.0
resolution: "eslint-rule-composer@npm:0.3.0"
checksum: c2f57cded8d1c8f82483e0ce28861214347e24fd79fd4144667974cd334d718f4ba05080aaef2399e3bbe36f7d6632865110227e6b176ed6daa2d676df9281b1
languageName: node
linkType: hard
"eslint-scope@npm:^7.2.2": "eslint-scope@npm:^7.2.2":
version: 7.2.2 version: 7.2.2
resolution: "eslint-scope@npm:7.2.2" resolution: "eslint-scope@npm:7.2.2"
@ -1886,7 +1923,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": "fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0":
version: 3.3.1 version: 3.3.1
resolution: "fast-glob@npm:3.3.1" resolution: "fast-glob@npm:3.3.1"
dependencies: dependencies:
@ -3818,7 +3855,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"postcss@npm:^8.4.23, postcss@npm:^8.4.27": "postcss@npm:^8.4.23, postcss@npm:^8.4.27, postcss@npm:^8.4.4":
version: 8.4.27 version: 8.4.27
resolution: "postcss@npm:8.4.27" resolution: "postcss@npm:8.4.27"
dependencies: dependencies:
@ -3836,6 +3873,23 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"prettier-plugin-organize-imports@npm:^3.2.3":
version: 3.2.3
resolution: "prettier-plugin-organize-imports@npm:3.2.3"
peerDependencies:
"@volar/vue-language-plugin-pug": ^1.0.4
"@volar/vue-typescript": ^1.0.4
prettier: ">=2.0"
typescript: ">=2.9"
peerDependenciesMeta:
"@volar/vue-language-plugin-pug":
optional: true
"@volar/vue-typescript":
optional: true
checksum: e97dd707ce88960885df9598c2c0b8187169ff4664e7a5083a8603eabfb457aa0a0eafdf5cb60877a1085e2da5f9cb19fa441061227aa23524e5fe1709bae0cf
languageName: node
linkType: hard
"prettier-plugin-tailwindcss@npm:^0.4.1": "prettier-plugin-tailwindcss@npm:^0.4.1":
version: 0.4.1 version: 0.4.1
resolution: "prettier-plugin-tailwindcss@npm:0.4.1" resolution: "prettier-plugin-tailwindcss@npm:0.4.1"