860 lines
40 KiB
React
860 lines
40 KiB
React
|
/*
|
||
|
This example requires some changes to your config:
|
||
|
|
||
|
```
|
||
|
// tailwind.config.js
|
||
|
module.exports = {
|
||
|
// ...
|
||
|
plugins: [
|
||
|
// ...
|
||
|
require('@tailwindcss/forms'),
|
||
|
require('@tailwindcss/aspect-ratio'),
|
||
|
],
|
||
|
}
|
||
|
```
|
||
|
*/
|
||
|
import { Fragment, useState } from 'react'
|
||
|
import { Dialog, Popover, Tab, Transition } from '@headlessui/react'
|
||
|
import { Bars3Icon, MagnifyingGlassIcon, ShoppingCartIcon, UserIcon, XMarkIcon } from '@heroicons/react/24/outline'
|
||
|
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
||
|
|
||
|
const currencies = ['CAD', 'USD', 'AUD', 'EUR', 'GBP']
|
||
|
const navigation = {
|
||
|
categories: [
|
||
|
{
|
||
|
name: 'Women',
|
||
|
featured: [
|
||
|
{ name: 'Sleep', href: '#' },
|
||
|
{ name: 'Swimwear', href: '#' },
|
||
|
{ name: 'Underwear', href: '#' },
|
||
|
],
|
||
|
collection: [
|
||
|
{ name: 'Everything', href: '#' },
|
||
|
{ name: 'Core', href: '#' },
|
||
|
{ name: 'New Arrivals', href: '#' },
|
||
|
{ name: 'Sale', href: '#' },
|
||
|
],
|
||
|
categories: [
|
||
|
{ name: 'Basic Tees', href: '#' },
|
||
|
{ name: 'Artwork Tees', href: '#' },
|
||
|
{ name: 'Bottoms', href: '#' },
|
||
|
{ name: 'Underwear', href: '#' },
|
||
|
{ name: 'Accessories', href: '#' },
|
||
|
],
|
||
|
brands: [
|
||
|
{ name: 'Full Nelson', href: '#' },
|
||
|
{ name: 'My Way', href: '#' },
|
||
|
{ name: 'Re-Arranged', href: '#' },
|
||
|
{ name: 'Counterfeit', href: '#' },
|
||
|
{ name: 'Significant Other', href: '#' },
|
||
|
],
|
||
|
},
|
||
|
{
|
||
|
name: 'Men',
|
||
|
featured: [
|
||
|
{ name: 'Casual', href: '#' },
|
||
|
{ name: 'Boxers', href: '#' },
|
||
|
{ name: 'Outdoor', href: '#' },
|
||
|
],
|
||
|
collection: [
|
||
|
{ name: 'Everything', href: '#' },
|
||
|
{ name: 'Core', href: '#' },
|
||
|
{ name: 'New Arrivals', href: '#' },
|
||
|
{ name: 'Sale', href: '#' },
|
||
|
],
|
||
|
categories: [
|
||
|
{ name: 'Artwork Tees', href: '#' },
|
||
|
{ name: 'Pants', href: '#' },
|
||
|
{ name: 'Accessories', href: '#' },
|
||
|
{ name: 'Boxers', href: '#' },
|
||
|
{ name: 'Basic Tees', href: '#' },
|
||
|
],
|
||
|
brands: [
|
||
|
{ name: 'Significant Other', href: '#' },
|
||
|
{ name: 'My Way', href: '#' },
|
||
|
{ name: 'Counterfeit', href: '#' },
|
||
|
{ name: 'Re-Arranged', href: '#' },
|
||
|
{ name: 'Full Nelson', href: '#' },
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
pages: [
|
||
|
{ name: 'Company', href: '#' },
|
||
|
{ name: 'Stores', href: '#' },
|
||
|
],
|
||
|
}
|
||
|
const products = [
|
||
|
{
|
||
|
id: 1,
|
||
|
name: 'Nomad Tumbler',
|
||
|
description:
|
||
|
'This durable and portable insulated tumbler will keep your beverage at the perfect temperature during your next adventure.',
|
||
|
href: '#',
|
||
|
price: '35.00',
|
||
|
status: 'Preparing to ship',
|
||
|
step: 1,
|
||
|
date: 'March 24, 2021',
|
||
|
datetime: '2021-03-24',
|
||
|
address: ['Floyd Miles', '7363 Cynthia Pass', 'Toronto, ON N3Y 4H8'],
|
||
|
email: 'f•••@example.com',
|
||
|
phone: '1•••••••••40',
|
||
|
imageSrc: 'https://tailwindui.com/img/ecommerce-images/confirmation-page-03-product-01.jpg',
|
||
|
imageAlt: 'Insulated bottle with white base and black snap lid.',
|
||
|
},
|
||
|
{
|
||
|
id: 2,
|
||
|
name: 'Minimalist Wristwatch',
|
||
|
description: 'This contemporary wristwatch has a clean, minimalist look and high quality components.',
|
||
|
href: '#',
|
||
|
price: '149.00',
|
||
|
status: 'Shipped',
|
||
|
step: 0,
|
||
|
date: 'March 23, 2021',
|
||
|
datetime: '2021-03-23',
|
||
|
address: ['Floyd Miles', '7363 Cynthia Pass', 'Toronto, ON N3Y 4H8'],
|
||
|
email: 'f•••@example.com',
|
||
|
phone: '1•••••••••40',
|
||
|
imageSrc: 'https://tailwindui.com/img/ecommerce-images/confirmation-page-03-product-02.jpg',
|
||
|
imageAlt:
|
||
|
'Arm modeling wristwatch with black leather band, white watch face, thin watch hands, and fine time markings.',
|
||
|
},
|
||
|
// More products...
|
||
|
]
|
||
|
const footerNavigation = {
|
||
|
account: [
|
||
|
{ name: 'Manage Account', href: '#' },
|
||
|
{ name: 'Saved Items', href: '#' },
|
||
|
{ name: 'Orders', href: '#' },
|
||
|
{ name: 'Redeem Gift card', href: '#' },
|
||
|
],
|
||
|
service: [
|
||
|
{ name: 'Shipping & Returns', href: '#' },
|
||
|
{ name: 'Warranty', href: '#' },
|
||
|
{ name: 'FAQ', href: '#' },
|
||
|
{ name: 'Find a store', href: '#' },
|
||
|
{ name: 'Get in touch', href: '#' },
|
||
|
],
|
||
|
company: [
|
||
|
{ name: 'Who we are', href: '#' },
|
||
|
{ name: 'Press', href: '#' },
|
||
|
{ name: 'Careers', href: '#' },
|
||
|
{ name: 'Terms & Conditions', href: '#' },
|
||
|
{ name: 'Privacy', href: '#' },
|
||
|
],
|
||
|
connect: [
|
||
|
{ name: 'Instagram', href: '#' },
|
||
|
{ name: 'Pinterest', href: '#' },
|
||
|
{ name: 'Twitter', href: '#' },
|
||
|
],
|
||
|
}
|
||
|
|
||
|
function classNames(...classes) {
|
||
|
return classes.filter(Boolean).join(' ')
|
||
|
}
|
||
|
|
||
|
export default function Example() {
|
||
|
const [open, setOpen] = useState(false)
|
||
|
|
||
|
return (
|
||
|
<div className="bg-gray-50">
|
||
|
{/* Mobile menu */}
|
||
|
<Transition.Root show={open} as={Fragment}>
|
||
|
<Dialog as="div" className="relative z-40 lg:hidden" onClose={setOpen}>
|
||
|
<Transition.Child
|
||
|
as={Fragment}
|
||
|
enter="transition-opacity ease-linear duration-300"
|
||
|
enterFrom="opacity-0"
|
||
|
enterTo="opacity-100"
|
||
|
leave="transition-opacity ease-linear duration-300"
|
||
|
leaveFrom="opacity-100"
|
||
|
leaveTo="opacity-0"
|
||
|
>
|
||
|
<div className="fixed inset-0 bg-black bg-opacity-25" />
|
||
|
</Transition.Child>
|
||
|
|
||
|
<div className="fixed inset-0 z-40 flex">
|
||
|
<Transition.Child
|
||
|
as={Fragment}
|
||
|
enter="transition ease-in-out duration-300 transform"
|
||
|
enterFrom="-translate-x-full"
|
||
|
enterTo="translate-x-0"
|
||
|
leave="transition ease-in-out duration-300 transform"
|
||
|
leaveFrom="translate-x-0"
|
||
|
leaveTo="-translate-x-full"
|
||
|
>
|
||
|
<Dialog.Panel className="relative flex w-full max-w-xs flex-col overflow-y-auto bg-white pb-12 shadow-xl">
|
||
|
<div className="flex px-4 pb-2 pt-5">
|
||
|
<button
|
||
|
type="button"
|
||
|
className="-m-2 inline-flex items-center justify-center rounded-md p-2 text-gray-400"
|
||
|
onClick={() => setOpen(false)}
|
||
|
>
|
||
|
<span className="sr-only">Close menu</span>
|
||
|
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||
|
</button>
|
||
|
</div>
|
||
|
|
||
|
{/* Links */}
|
||
|
<Tab.Group as="div" className="mt-2">
|
||
|
<div className="border-b border-gray-200">
|
||
|
<Tab.List className="-mb-px flex space-x-8 px-4">
|
||
|
{navigation.categories.map((category) => (
|
||
|
<Tab
|
||
|
key={category.name}
|
||
|
className={({ selected }) =>
|
||
|
classNames(
|
||
|
selected ? 'border-indigo-600 text-indigo-600' : 'border-transparent text-gray-900',
|
||
|
'flex-1 whitespace-nowrap border-b-2 px-1 py-4 text-base font-medium'
|
||
|
)
|
||
|
}
|
||
|
>
|
||
|
{category.name}
|
||
|
</Tab>
|
||
|
))}
|
||
|
</Tab.List>
|
||
|
</div>
|
||
|
<Tab.Panels as={Fragment}>
|
||
|
{navigation.categories.map((category, categoryIdx) => (
|
||
|
<Tab.Panel key={category.name} className="space-y-12 px-4 pb-6 pt-10">
|
||
|
<div className="grid grid-cols-1 items-start gap-x-6 gap-y-10">
|
||
|
<div className="grid grid-cols-1 gap-x-6 gap-y-10">
|
||
|
<div>
|
||
|
<p id={`mobile-featured-heading-${categoryIdx}`} className="font-medium text-gray-900">
|
||
|
Featured
|
||
|
</p>
|
||
|
<ul
|
||
|
role="list"
|
||
|
aria-labelledby={`mobile-featured-heading-${categoryIdx}`}
|
||
|
className="mt-6 space-y-6"
|
||
|
>
|
||
|
{category.featured.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="text-gray-500">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div>
|
||
|
<p id="mobile-categories-heading" className="font-medium text-gray-900">
|
||
|
Categories
|
||
|
</p>
|
||
|
<ul role="list" aria-labelledby="mobile-categories-heading" className="mt-6 space-y-6">
|
||
|
{category.categories.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="text-gray-500">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div className="grid grid-cols-1 gap-x-6 gap-y-10">
|
||
|
<div>
|
||
|
<p id="mobile-collection-heading" className="font-medium text-gray-900">
|
||
|
Collection
|
||
|
</p>
|
||
|
<ul role="list" aria-labelledby="mobile-collection-heading" className="mt-6 space-y-6">
|
||
|
{category.collection.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="text-gray-500">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
|
||
|
<div>
|
||
|
<p id="mobile-brand-heading" className="font-medium text-gray-900">
|
||
|
Brands
|
||
|
</p>
|
||
|
<ul role="list" aria-labelledby="mobile-brand-heading" className="mt-6 space-y-6">
|
||
|
{category.brands.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="text-gray-500">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</Tab.Panel>
|
||
|
))}
|
||
|
</Tab.Panels>
|
||
|
</Tab.Group>
|
||
|
|
||
|
<div className="space-y-6 border-t border-gray-200 px-4 py-6">
|
||
|
{navigation.pages.map((page) => (
|
||
|
<div key={page.name} className="flow-root">
|
||
|
<a href={page.href} className="-m-2 block p-2 font-medium text-gray-900">
|
||
|
{page.name}
|
||
|
</a>
|
||
|
</div>
|
||
|
))}
|
||
|
</div>
|
||
|
|
||
|
<div className="space-y-6 border-t border-gray-200 px-4 py-6">
|
||
|
<div className="flow-root">
|
||
|
<a href="#" className="-m-2 block p-2 font-medium text-gray-900">
|
||
|
Create an account
|
||
|
</a>
|
||
|
</div>
|
||
|
<div className="flow-root">
|
||
|
<a href="#" className="-m-2 block p-2 font-medium text-gray-900">
|
||
|
Sign in
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div className="space-y-6 border-t border-gray-200 px-4 py-6">
|
||
|
{/* Currency selector */}
|
||
|
<form>
|
||
|
<div className="inline-block">
|
||
|
<label htmlFor="mobile-currency" className="sr-only">
|
||
|
Currency
|
||
|
</label>
|
||
|
<div className="group relative -ml-2 rounded-md border-transparent focus-within:ring-2 focus-within:ring-white">
|
||
|
<select
|
||
|
id="mobile-currency"
|
||
|
name="currency"
|
||
|
className="flex items-center rounded-md border-transparent bg-none py-0.5 pl-2 pr-5 text-sm font-medium text-gray-700 focus:border-transparent focus:outline-none focus:ring-0 group-hover:text-gray-800"
|
||
|
>
|
||
|
{currencies.map((currency) => (
|
||
|
<option key={currency}>{currency}</option>
|
||
|
))}
|
||
|
</select>
|
||
|
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center">
|
||
|
<ChevronDownIcon className="h-5 w-5 text-gray-500" aria-hidden="true" />
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</form>
|
||
|
</div>
|
||
|
</Dialog.Panel>
|
||
|
</Transition.Child>
|
||
|
</div>
|
||
|
</Dialog>
|
||
|
</Transition.Root>
|
||
|
|
||
|
<header className="relative">
|
||
|
<nav aria-label="Top">
|
||
|
{/* Top navigation */}
|
||
|
<div className="bg-gray-900">
|
||
|
<div className="mx-auto flex h-10 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
|
||
|
{/* Currency selector */}
|
||
|
<form className="hidden lg:block lg:flex-1">
|
||
|
<div className="flex">
|
||
|
<label htmlFor="desktop-currency" className="sr-only">
|
||
|
Currency
|
||
|
</label>
|
||
|
<div className="group relative -ml-2 rounded-md border-transparent bg-gray-900 focus-within:ring-2 focus-within:ring-white">
|
||
|
<select
|
||
|
id="desktop-currency"
|
||
|
name="currency"
|
||
|
className="flex items-center rounded-md border-transparent bg-gray-900 bg-none py-0.5 pl-2 pr-5 text-sm font-medium text-white focus:border-transparent focus:outline-none focus:ring-0 group-hover:text-gray-100"
|
||
|
>
|
||
|
{currencies.map((currency) => (
|
||
|
<option key={currency}>{currency}</option>
|
||
|
))}
|
||
|
</select>
|
||
|
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center">
|
||
|
<ChevronDownIcon className="h-5 w-5 text-gray-300" aria-hidden="true" />
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</form>
|
||
|
|
||
|
<p className="flex-1 text-center text-sm font-medium text-white lg:flex-none">
|
||
|
Get free delivery on orders over $100
|
||
|
</p>
|
||
|
|
||
|
<div className="hidden lg:flex lg:flex-1 lg:items-center lg:justify-end lg:space-x-6">
|
||
|
<a href="#" className="text-sm font-medium text-white hover:text-gray-100">
|
||
|
Create an account
|
||
|
</a>
|
||
|
<span className="h-6 w-px bg-gray-600" aria-hidden="true" />
|
||
|
<a href="#" className="text-sm font-medium text-white hover:text-gray-100">
|
||
|
Sign in
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
{/* Secondary navigation */}
|
||
|
<div className="border-b border-gray-200 bg-white">
|
||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||
|
<div className="flex h-16 items-center justify-between">
|
||
|
{/* Logo (lg+) */}
|
||
|
<div className="hidden lg:flex lg:items-center">
|
||
|
<a href="#">
|
||
|
<span className="sr-only">Your Company</span>
|
||
|
<img
|
||
|
className="h-8 w-auto"
|
||
|
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
|
||
|
alt=""
|
||
|
/>
|
||
|
</a>
|
||
|
</div>
|
||
|
|
||
|
<div className="hidden h-full lg:flex">
|
||
|
{/* Mega menus */}
|
||
|
<Popover.Group className="ml-8">
|
||
|
<div className="flex h-full justify-center space-x-8">
|
||
|
{navigation.categories.map((category, categoryIdx) => (
|
||
|
<Popover key={category.name} className="flex">
|
||
|
{({ open }) => (
|
||
|
<>
|
||
|
<div className="relative flex">
|
||
|
<Popover.Button
|
||
|
className={classNames(
|
||
|
open
|
||
|
? 'border-indigo-600 text-indigo-600'
|
||
|
: 'border-transparent text-gray-700 hover:text-gray-800',
|
||
|
'relative z-10 -mb-px flex items-center border-b-2 pt-px text-sm font-medium transition-colors duration-200 ease-out'
|
||
|
)}
|
||
|
>
|
||
|
{category.name}
|
||
|
</Popover.Button>
|
||
|
</div>
|
||
|
|
||
|
<Transition
|
||
|
as={Fragment}
|
||
|
enter="transition ease-out duration-200"
|
||
|
enterFrom="opacity-0"
|
||
|
enterTo="opacity-100"
|
||
|
leave="transition ease-in duration-150"
|
||
|
leaveFrom="opacity-100"
|
||
|
leaveTo="opacity-0"
|
||
|
>
|
||
|
<Popover.Panel className="absolute inset-x-0 top-full -translate-y-px transform bg-white text-sm text-gray-500">
|
||
|
{/* Presentational element used to render the bottom shadow, if we put the shadow on the actual panel it pokes out the top, so we use this shorter element to hide the top of the shadow */}
|
||
|
<div className="absolute inset-0 top-1/2 bg-white shadow" aria-hidden="true" />
|
||
|
{/* Fake border when menu is open */}
|
||
|
<div
|
||
|
className="absolute inset-0 top-0 z-10 mx-auto h-px max-w-7xl px-8"
|
||
|
aria-hidden="true"
|
||
|
>
|
||
|
<div
|
||
|
className={classNames(
|
||
|
open ? 'bg-gray-200' : 'bg-transparent',
|
||
|
'h-px w-full transition-colors duration-200 ease-out'
|
||
|
)}
|
||
|
/>
|
||
|
</div>
|
||
|
|
||
|
<div className="relative">
|
||
|
<div className="mx-auto max-w-7xl px-8">
|
||
|
<div className="grid grid-cols-2 items-start gap-x-8 gap-y-10 pb-12 pt-10">
|
||
|
<div className="grid grid-cols-2 gap-x-8 gap-y-10">
|
||
|
<div>
|
||
|
<p
|
||
|
id={`desktop-featured-heading-${categoryIdx}`}
|
||
|
className="font-medium text-gray-900"
|
||
|
>
|
||
|
Featured
|
||
|
</p>
|
||
|
<ul
|
||
|
role="list"
|
||
|
aria-labelledby={`desktop-featured-heading-${categoryIdx}`}
|
||
|
className="mt-6 space-y-6 sm:mt-4 sm:space-y-4"
|
||
|
>
|
||
|
{category.featured.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="hover:text-gray-800">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div>
|
||
|
<p id="desktop-categories-heading" className="font-medium text-gray-900">
|
||
|
Categories
|
||
|
</p>
|
||
|
<ul
|
||
|
role="list"
|
||
|
aria-labelledby="desktop-categories-heading"
|
||
|
className="mt-6 space-y-6 sm:mt-4 sm:space-y-4"
|
||
|
>
|
||
|
{category.categories.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="hover:text-gray-800">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div className="grid grid-cols-2 gap-x-8 gap-y-10">
|
||
|
<div>
|
||
|
<p id="desktop-collection-heading" className="font-medium text-gray-900">
|
||
|
Collection
|
||
|
</p>
|
||
|
<ul
|
||
|
role="list"
|
||
|
aria-labelledby="desktop-collection-heading"
|
||
|
className="mt-6 space-y-6 sm:mt-4 sm:space-y-4"
|
||
|
>
|
||
|
{category.collection.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="hover:text-gray-800">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
|
||
|
<div>
|
||
|
<p id="desktop-brand-heading" className="font-medium text-gray-900">
|
||
|
Brands
|
||
|
</p>
|
||
|
<ul
|
||
|
role="list"
|
||
|
aria-labelledby="desktop-brand-heading"
|
||
|
className="mt-6 space-y-6 sm:mt-4 sm:space-y-4"
|
||
|
>
|
||
|
{category.brands.map((item) => (
|
||
|
<li key={item.name} className="flex">
|
||
|
<a href={item.href} className="hover:text-gray-800">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</Popover.Panel>
|
||
|
</Transition>
|
||
|
</>
|
||
|
)}
|
||
|
</Popover>
|
||
|
))}
|
||
|
|
||
|
{navigation.pages.map((page) => (
|
||
|
<a
|
||
|
key={page.name}
|
||
|
href={page.href}
|
||
|
className="flex items-center text-sm font-medium text-gray-700 hover:text-gray-800"
|
||
|
>
|
||
|
{page.name}
|
||
|
</a>
|
||
|
))}
|
||
|
</div>
|
||
|
</Popover.Group>
|
||
|
</div>
|
||
|
|
||
|
{/* Mobile menu and search (lg-) */}
|
||
|
<div className="flex flex-1 items-center lg:hidden">
|
||
|
<button
|
||
|
type="button"
|
||
|
className="-ml-2 rounded-md bg-white p-2 text-gray-400"
|
||
|
onClick={() => setOpen(true)}
|
||
|
>
|
||
|
<span className="sr-only">Open menu</span>
|
||
|
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
|
||
|
</button>
|
||
|
|
||
|
{/* Search */}
|
||
|
<a href="#" className="ml-2 p-2 text-gray-400 hover:text-gray-500">
|
||
|
<span className="sr-only">Search</span>
|
||
|
<MagnifyingGlassIcon className="h-6 w-6" aria-hidden="true" />
|
||
|
</a>
|
||
|
</div>
|
||
|
|
||
|
{/* Logo (lg-) */}
|
||
|
<a href="#" className="lg:hidden">
|
||
|
<span className="sr-only">Your Company</span>
|
||
|
<img
|
||
|
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
|
||
|
alt=""
|
||
|
className="h-8 w-auto"
|
||
|
/>
|
||
|
</a>
|
||
|
|
||
|
<div className="flex flex-1 items-center justify-end">
|
||
|
<div className="flex items-center lg:ml-8">
|
||
|
<div className="flex space-x-8">
|
||
|
<div className="hidden lg:flex">
|
||
|
<a href="#" className="-m-2 p-2 text-gray-400 hover:text-gray-500">
|
||
|
<span className="sr-only">Search</span>
|
||
|
<MagnifyingGlassIcon className="h-6 w-6" aria-hidden="true" />
|
||
|
</a>
|
||
|
</div>
|
||
|
|
||
|
<div className="flex">
|
||
|
<a href="#" className="-m-2 p-2 text-gray-400 hover:text-gray-500">
|
||
|
<span className="sr-only">Account</span>
|
||
|
<UserIcon className="h-6 w-6" aria-hidden="true" />
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<span className="mx-4 h-6 w-px bg-gray-200 lg:mx-6" aria-hidden="true" />
|
||
|
|
||
|
<div className="flow-root">
|
||
|
<a href="#" className="group -m-2 flex items-center p-2">
|
||
|
<ShoppingCartIcon
|
||
|
className="h-6 w-6 flex-shrink-0 text-gray-400 group-hover:text-gray-500"
|
||
|
aria-hidden="true"
|
||
|
/>
|
||
|
<span className="ml-2 text-sm font-medium text-gray-700 group-hover:text-gray-800">0</span>
|
||
|
<span className="sr-only">items in cart, view bag</span>
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</nav>
|
||
|
</header>
|
||
|
|
||
|
<main className="mx-auto max-w-2xl pb-24 pt-8 sm:px-6 sm:pt-16 lg:max-w-7xl lg:px-8">
|
||
|
<div className="space-y-2 px-4 sm:flex sm:items-baseline sm:justify-between sm:space-y-0 sm:px-0">
|
||
|
<div className="flex sm:items-baseline sm:space-x-4">
|
||
|
<h1 className="text-2xl font-bold tracking-tight text-gray-900 sm:text-3xl">Order #54879</h1>
|
||
|
<a href="#" className="hidden text-sm font-medium text-indigo-600 hover:text-indigo-500 sm:block">
|
||
|
View invoice
|
||
|
<span aria-hidden="true"> →</span>
|
||
|
</a>
|
||
|
</div>
|
||
|
<p className="text-sm text-gray-600">
|
||
|
Order placed{' '}
|
||
|
<time dateTime="2021-03-22" className="font-medium text-gray-900">
|
||
|
March 22, 2021
|
||
|
</time>
|
||
|
</p>
|
||
|
<a href="#" className="text-sm font-medium text-indigo-600 hover:text-indigo-500 sm:hidden">
|
||
|
View invoice
|
||
|
<span aria-hidden="true"> →</span>
|
||
|
</a>
|
||
|
</div>
|
||
|
|
||
|
{/* Products */}
|
||
|
<section aria-labelledby="products-heading" className="mt-6">
|
||
|
<h2 id="products-heading" className="sr-only">
|
||
|
Products purchased
|
||
|
</h2>
|
||
|
|
||
|
<div className="space-y-8">
|
||
|
{products.map((product) => (
|
||
|
<div
|
||
|
key={product.id}
|
||
|
className="border-b border-t border-gray-200 bg-white shadow-sm sm:rounded-lg sm:border"
|
||
|
>
|
||
|
<div className="px-4 py-6 sm:px-6 lg:grid lg:grid-cols-12 lg:gap-x-8 lg:p-8">
|
||
|
<div className="sm:flex lg:col-span-7">
|
||
|
<div className="aspect-h-1 aspect-w-1 w-full flex-shrink-0 overflow-hidden rounded-lg sm:aspect-none sm:h-40 sm:w-40">
|
||
|
<img
|
||
|
src={product.imageSrc}
|
||
|
alt={product.imageAlt}
|
||
|
className="h-full w-full object-cover object-center sm:h-full sm:w-full"
|
||
|
/>
|
||
|
</div>
|
||
|
|
||
|
<div className="mt-6 sm:ml-6 sm:mt-0">
|
||
|
<h3 className="text-base font-medium text-gray-900">
|
||
|
<a href={product.href}>{product.name}</a>
|
||
|
</h3>
|
||
|
<p className="mt-2 text-sm font-medium text-gray-900">${product.price}</p>
|
||
|
<p className="mt-3 text-sm text-gray-500">{product.description}</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div className="mt-6 lg:col-span-5 lg:mt-0">
|
||
|
<dl className="grid grid-cols-2 gap-x-6 text-sm">
|
||
|
<div>
|
||
|
<dt className="font-medium text-gray-900">Delivery address</dt>
|
||
|
<dd className="mt-3 text-gray-500">
|
||
|
<span className="block">{product.address[0]}</span>
|
||
|
<span className="block">{product.address[1]}</span>
|
||
|
<span className="block">{product.address[2]}</span>
|
||
|
</dd>
|
||
|
</div>
|
||
|
<div>
|
||
|
<dt className="font-medium text-gray-900">Shipping updates</dt>
|
||
|
<dd className="mt-3 space-y-3 text-gray-500">
|
||
|
<p>{product.email}</p>
|
||
|
<p>{product.phone}</p>
|
||
|
<button type="button" className="font-medium text-indigo-600 hover:text-indigo-500">
|
||
|
Edit
|
||
|
</button>
|
||
|
</dd>
|
||
|
</div>
|
||
|
</dl>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div className="border-t border-gray-200 px-4 py-6 sm:px-6 lg:p-8">
|
||
|
<h4 className="sr-only">Status</h4>
|
||
|
<p className="text-sm font-medium text-gray-900">
|
||
|
{product.status} on <time dateTime={product.datetime}>{product.date}</time>
|
||
|
</p>
|
||
|
<div className="mt-6" aria-hidden="true">
|
||
|
<div className="overflow-hidden rounded-full bg-gray-200">
|
||
|
<div
|
||
|
className="h-2 rounded-full bg-indigo-600"
|
||
|
style={{ width: `calc((${product.step} * 2 + 1) / 8 * 100%)` }}
|
||
|
/>
|
||
|
</div>
|
||
|
<div className="mt-6 hidden grid-cols-4 text-sm font-medium text-gray-600 sm:grid">
|
||
|
<div className="text-indigo-600">Order placed</div>
|
||
|
<div className={classNames(product.step > 0 ? 'text-indigo-600' : '', 'text-center')}>
|
||
|
Processing
|
||
|
</div>
|
||
|
<div className={classNames(product.step > 1 ? 'text-indigo-600' : '', 'text-center')}>
|
||
|
Shipped
|
||
|
</div>
|
||
|
<div className={classNames(product.step > 2 ? 'text-indigo-600' : '', 'text-right')}>
|
||
|
Delivered
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
))}
|
||
|
</div>
|
||
|
</section>
|
||
|
|
||
|
{/* Billing */}
|
||
|
<section aria-labelledby="summary-heading" className="mt-16">
|
||
|
<h2 id="summary-heading" className="sr-only">
|
||
|
Billing Summary
|
||
|
</h2>
|
||
|
|
||
|
<div className="bg-gray-100 px-4 py-6 sm:rounded-lg sm:px-6 lg:grid lg:grid-cols-12 lg:gap-x-8 lg:px-8 lg:py-8">
|
||
|
<dl className="grid grid-cols-2 gap-6 text-sm sm:grid-cols-2 md:gap-x-8 lg:col-span-7">
|
||
|
<div>
|
||
|
<dt className="font-medium text-gray-900">Billing address</dt>
|
||
|
<dd className="mt-3 text-gray-500">
|
||
|
<span className="block">Floyd Miles</span>
|
||
|
<span className="block">7363 Cynthia Pass</span>
|
||
|
<span className="block">Toronto, ON N3Y 4H8</span>
|
||
|
</dd>
|
||
|
</div>
|
||
|
<div>
|
||
|
<dt className="font-medium text-gray-900">Payment information</dt>
|
||
|
<dd className="-ml-4 -mt-1 flex flex-wrap">
|
||
|
<div className="ml-4 mt-4 flex-shrink-0">
|
||
|
<svg aria-hidden="true" width={36} height={24} viewBox="0 0 36 24" className="h-6 w-auto">
|
||
|
<rect width={36} height={24} rx={4} fill="#224DBA" />
|
||
|
<path
|
||
|
d="M10.925 15.673H8.874l-1.538-6c-.073-.276-.228-.52-.456-.635A6.575 6.575 0 005 8.403v-.231h3.304c.456 0 .798.347.855.75l.798 4.328 2.05-5.078h1.994l-3.076 7.5zm4.216 0h-1.937L14.8 8.172h1.937l-1.595 7.5zm4.101-5.422c.057-.404.399-.635.798-.635a3.54 3.54 0 011.88.346l.342-1.615A4.808 4.808 0 0020.496 8c-1.88 0-3.248 1.039-3.248 2.481 0 1.097.969 1.673 1.653 2.02.74.346 1.025.577.968.923 0 .519-.57.75-1.139.75a4.795 4.795 0 01-1.994-.462l-.342 1.616a5.48 5.48 0 002.108.404c2.108.057 3.418-.981 3.418-2.539 0-1.962-2.678-2.077-2.678-2.942zm9.457 5.422L27.16 8.172h-1.652a.858.858 0 00-.798.577l-2.848 6.924h1.994l.398-1.096h2.45l.228 1.096h1.766zm-2.905-5.482l.57 2.827h-1.596l1.026-2.827z"
|
||
|
fill="#fff"
|
||
|
/>
|
||
|
</svg>
|
||
|
<p className="sr-only">Visa</p>
|
||
|
</div>
|
||
|
<div className="ml-4 mt-4">
|
||
|
<p className="text-gray-900">Ending with 4242</p>
|
||
|
<p className="text-gray-600">Expires 02 / 24</p>
|
||
|
</div>
|
||
|
</dd>
|
||
|
</div>
|
||
|
</dl>
|
||
|
|
||
|
<dl className="mt-8 divide-y divide-gray-200 text-sm lg:col-span-5 lg:mt-0">
|
||
|
<div className="flex items-center justify-between pb-4">
|
||
|
<dt className="text-gray-600">Subtotal</dt>
|
||
|
<dd className="font-medium text-gray-900">$72</dd>
|
||
|
</div>
|
||
|
<div className="flex items-center justify-between py-4">
|
||
|
<dt className="text-gray-600">Shipping</dt>
|
||
|
<dd className="font-medium text-gray-900">$5</dd>
|
||
|
</div>
|
||
|
<div className="flex items-center justify-between py-4">
|
||
|
<dt className="text-gray-600">Tax</dt>
|
||
|
<dd className="font-medium text-gray-900">$6.16</dd>
|
||
|
</div>
|
||
|
<div className="flex items-center justify-between pt-4">
|
||
|
<dt className="font-medium text-gray-900">Order total</dt>
|
||
|
<dd className="font-medium text-indigo-600">$83.16</dd>
|
||
|
</div>
|
||
|
</dl>
|
||
|
</div>
|
||
|
</section>
|
||
|
</main>
|
||
|
|
||
|
<footer aria-labelledby="footer-heading" className="border-t border-gray-200 bg-white">
|
||
|
<h2 id="footer-heading" className="sr-only">
|
||
|
Footer
|
||
|
</h2>
|
||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||
|
<div className="grid grid-cols-2 gap-8 py-20 sm:grid-cols-2 sm:gap-y-0 lg:grid-cols-4">
|
||
|
<div className="grid grid-cols-1 gap-y-10 lg:col-span-2 lg:grid-cols-2 lg:gap-x-8 lg:gap-y-0">
|
||
|
<div>
|
||
|
<h3 className="text-sm font-medium text-gray-900">Account</h3>
|
||
|
<ul role="list" className="mt-6 space-y-6">
|
||
|
{footerNavigation.account.map((item) => (
|
||
|
<li key={item.name} className="text-sm">
|
||
|
<a href={item.href} className="text-gray-500 hover:text-gray-600">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div>
|
||
|
<h3 className="text-sm font-medium text-gray-900">Service</h3>
|
||
|
<ul role="list" className="mt-6 space-y-6">
|
||
|
{footerNavigation.service.map((item) => (
|
||
|
<li key={item.name} className="text-sm">
|
||
|
<a href={item.href} className="text-gray-500 hover:text-gray-600">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div className="grid grid-cols-1 gap-y-10 lg:col-span-2 lg:grid-cols-2 lg:gap-x-8 lg:gap-y-0">
|
||
|
<div>
|
||
|
<h3 className="text-sm font-medium text-gray-900">Company</h3>
|
||
|
<ul role="list" className="mt-6 space-y-6">
|
||
|
{footerNavigation.company.map((item) => (
|
||
|
<li key={item.name} className="text-sm">
|
||
|
<a href={item.href} className="text-gray-500 hover:text-gray-600">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div>
|
||
|
<h3 className="text-sm font-medium text-gray-900">Connect</h3>
|
||
|
<ul role="list" className="mt-6 space-y-6">
|
||
|
{footerNavigation.connect.map((item) => (
|
||
|
<li key={item.name} className="text-sm">
|
||
|
<a href={item.href} className="text-gray-500 hover:text-gray-600">
|
||
|
{item.name}
|
||
|
</a>
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div className="border-t border-gray-100 py-10 sm:flex sm:items-center sm:justify-between">
|
||
|
<div className="flex items-center justify-center text-sm text-gray-500">
|
||
|
<p>Shipping to Canada ($CAD)</p>
|
||
|
<p className="ml-3 border-l border-gray-200 pl-3">English</p>
|
||
|
</div>
|
||
|
<p className="mt-6 text-center text-sm text-gray-500 sm:mt-0">© 2021 Your Company, Inc.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</footer>
|
||
|
</div>
|
||
|
)
|
||
|
}
|