mirror of
https://github.com/vercel/commerce.git
synced 2025-05-13 13:17:51 +00:00
fix: update PLP display
Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
parent
f5a2237d43
commit
78a79a44b7
@ -1,4 +1,4 @@
|
|||||||
import { getCollection, getCollectionProducts, getMenu } from 'lib/shopify';
|
import { getCollection, getCollectionProducts } from 'lib/shopify';
|
||||||
import { Metadata } from 'next';
|
import { Metadata } from 'next';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
|
|
||||||
@ -9,6 +9,8 @@ import ProductGridItems from 'components/layout/product-grid-items';
|
|||||||
import FiltersList from 'components/layout/search/filters/filters-list';
|
import FiltersList from 'components/layout/search/filters/filters-list';
|
||||||
import MobileFilters from 'components/layout/search/filters/mobile-filters';
|
import MobileFilters from 'components/layout/search/filters/mobile-filters';
|
||||||
import SubMenu from 'components/layout/search/filters/sub-menu';
|
import SubMenu from 'components/layout/search/filters/sub-menu';
|
||||||
|
import Header, { HeaderPlaceholder } from 'components/layout/search/header';
|
||||||
|
import ProductsGridPlaceholder from 'components/layout/search/placeholder';
|
||||||
import SortingMenu from 'components/layout/search/sorting-menu';
|
import SortingMenu from 'components/layout/search/sorting-menu';
|
||||||
import {
|
import {
|
||||||
AVAILABILITY_FILTER_ID,
|
AVAILABILITY_FILTER_ID,
|
||||||
@ -90,7 +92,7 @@ const constructFilterInput = (filters: {
|
|||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function CategoryPage({
|
async function CategoryPage({
|
||||||
params,
|
params,
|
||||||
searchParams
|
searchParams
|
||||||
}: {
|
}: {
|
||||||
@ -101,42 +103,23 @@ export default async function CategoryPage({
|
|||||||
const { sortKey, reverse } = sorting.find((item) => item.slug === sort) || defaultSort;
|
const { sortKey, reverse } = sorting.find((item) => item.slug === sort) || defaultSort;
|
||||||
|
|
||||||
const filtersInput = constructFilterInput(rest);
|
const filtersInput = constructFilterInput(rest);
|
||||||
const productsData = getCollectionProducts({
|
const { products, filters } = await getCollectionProducts({
|
||||||
collection: params.collection,
|
collection: params.collection,
|
||||||
sortKey,
|
sortKey,
|
||||||
reverse,
|
reverse,
|
||||||
...(filtersInput.length ? { filters: filtersInput } : {})
|
...(filtersInput.length ? { filters: filtersInput } : {})
|
||||||
});
|
});
|
||||||
const collectionData = getCollection(params.collection);
|
|
||||||
const menuData = getMenu('main-menu');
|
|
||||||
|
|
||||||
const [{ products, filters }, collection, menu] = await Promise.all([
|
|
||||||
productsData,
|
|
||||||
collectionData,
|
|
||||||
menuData
|
|
||||||
]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-2">
|
|
||||||
<Suspense fallback={<BreadcrumbHome />}>
|
|
||||||
<Breadcrumb type="collection" handle={params.collection} />
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
|
||||||
{collection ? (
|
|
||||||
<div className="mb-3 mt-3 max-w-5xl lg:mb-1">
|
|
||||||
<h1 className="text-4xl font-bold tracking-tight text-gray-900">{collection.title}</h1>
|
|
||||||
<p className="mt-2 text-base text-gray-500">{collection.description}</p>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<div className="flex w-full items-center justify-between gap-2 lg:justify-end">
|
<div className="flex w-full items-center justify-between gap-2 lg:justify-end">
|
||||||
<MobileFilters collection={params.collection} filters={filters} menu={menu} />
|
<MobileFilters filters={filters} menu={<SubMenu collection={params.collection} />} />
|
||||||
<SortingMenu />
|
<SortingMenu />
|
||||||
</div>
|
</div>
|
||||||
<section>
|
<section>
|
||||||
<Grid className="pt-5 lg:grid-cols-3 lg:gap-x-8 xl:grid-cols-4">
|
<Grid className="pt-5 lg:grid-cols-3 lg:gap-x-8 xl:grid-cols-4">
|
||||||
<aside className="hidden lg:block">
|
<aside className="hidden lg:block">
|
||||||
<SubMenu menu={menu} collection={params.collection} />
|
<SubMenu collection={params.collection} />
|
||||||
<h3 className="sr-only">Filters</h3>
|
<h3 className="sr-only">Filters</h3>
|
||||||
<FiltersList filters={filters} />
|
<FiltersList filters={filters} />
|
||||||
</aside>
|
</aside>
|
||||||
@ -154,3 +137,24 @@ export default async function CategoryPage({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default function CategorySearchPage(props: {
|
||||||
|
params: { collection: string };
|
||||||
|
searchParams?: { [key: string]: string | string[] | undefined };
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="mb-2">
|
||||||
|
<Suspense fallback={<BreadcrumbHome />}>
|
||||||
|
<Breadcrumb type="collection" handle={props.params.collection} />
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
<Suspense fallback={<HeaderPlaceholder />}>
|
||||||
|
<Header collection={props.params.collection} />
|
||||||
|
</Suspense>
|
||||||
|
<Suspense fallback={<ProductsGridPlaceholder />}>
|
||||||
|
<CategoryPage {...props} />
|
||||||
|
</Suspense>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import Footer from 'components/layout/footer';
|
import Footer from 'components/layout/footer';
|
||||||
import { Suspense } from 'react';
|
|
||||||
|
|
||||||
export default function SearchLayout({ children }: { children: React.ReactNode }) {
|
export default function SearchLayout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<Suspense>
|
<>
|
||||||
<div className="mx-auto max-w-screen-2xl px-8 pb-4">{children}</div>
|
<div className="mx-auto min-h-[500px] max-w-screen-2xl px-8 pb-4 lg:min-h-[800px]">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</Suspense>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,11 @@ type BreadcrumbProps = {
|
|||||||
|
|
||||||
const findParentCollection = (menu: Menu[], collection: string): Menu | null => {
|
const findParentCollection = (menu: Menu[], collection: string): Menu | null => {
|
||||||
let parentCollection: Menu | null = null;
|
let parentCollection: Menu | null = null;
|
||||||
|
|
||||||
for (const item of menu) {
|
for (const item of menu) {
|
||||||
if (item.items.length) {
|
if (item.items.length) {
|
||||||
const hasParent = item.items.some((subItem) => subItem.path.includes(collection));
|
const hasParent = item.items.some((subItem) => subItem.path.includes(collection));
|
||||||
if (hasParent) {
|
if (hasParent) {
|
||||||
parentCollection = item;
|
return item;
|
||||||
} else {
|
} else {
|
||||||
parentCollection = findParentCollection(item.items, collection);
|
parentCollection = findParentCollection(item.items, collection);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ function ThreeItemGridItem({
|
|||||||
<div
|
<div
|
||||||
className={size === 'full' ? 'md:col-span-4 md:row-span-2' : 'md:col-span-2 md:row-span-1'}
|
className={size === 'full' ? 'md:col-span-4 md:row-span-2' : 'md:col-span-2 md:row-span-1'}
|
||||||
>
|
>
|
||||||
<Link className="relative block aspect-square h-full w-full" href={`/product/${item.handle}`}>
|
<Link className="aspect-square relative block h-full w-full" href={`/product/${item.handle}`}>
|
||||||
<GridTileImage
|
<GridTileImage
|
||||||
src={item.featuredImage.url}
|
src={item.featuredImage.url}
|
||||||
fill
|
fill
|
||||||
@ -26,7 +26,6 @@ function ThreeItemGridItem({
|
|||||||
priority={priority}
|
priority={priority}
|
||||||
alt={item.title}
|
alt={item.title}
|
||||||
label={{
|
label={{
|
||||||
position: size === 'full' ? 'center' : 'bottom',
|
|
||||||
title: item.title as string,
|
title: item.title as string,
|
||||||
amount: item.priceRange.maxVariantPrice.amount,
|
amount: item.priceRange.maxVariantPrice.amount,
|
||||||
currencyCode: item.priceRange.maxVariantPrice.currencyCode
|
currencyCode: item.priceRange.maxVariantPrice.currencyCode
|
||||||
|
@ -1,49 +1,45 @@
|
|||||||
|
import { PhotoIcon } from '@heroicons/react/24/outline';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import Label from '../label';
|
import Label from '../label';
|
||||||
|
|
||||||
export function GridTileImage({
|
export function GridTileImage({
|
||||||
isInteractive = true,
|
|
||||||
active,
|
active,
|
||||||
label,
|
label,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
isInteractive?: boolean;
|
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
label?: {
|
label?: {
|
||||||
title: string;
|
title: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
currencyCode: string;
|
currencyCode: string;
|
||||||
position?: 'bottom' | 'center';
|
|
||||||
};
|
};
|
||||||
} & React.ComponentProps<typeof Image>) {
|
} & React.ComponentProps<typeof Image>) {
|
||||||
return (
|
return (
|
||||||
|
<div className="group">
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'group flex h-full w-full items-center justify-center overflow-hidden rounded-lg border bg-white hover:border-secondary dark:bg-black',
|
'aspect-h-1 aspect-w-1 relative overflow-hidden rounded-lg bg-gray-200 group-hover:opacity-75',
|
||||||
{
|
{
|
||||||
relative: label,
|
|
||||||
'border-2 border-secondary': active,
|
'border-2 border-secondary': active,
|
||||||
'border-neutral-200 dark:border-neutral-800': !active
|
'border-neutral-200': !active
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{props.src ? (
|
{props.src ? (
|
||||||
// eslint-disable-next-line jsx-a11y/alt-text -- `alt` is inherited from `props`, which is being enforced with TypeScript
|
// eslint-disable-next-line jsx-a11y/alt-text -- `alt` is inherited from `props`, which is being enforced with TypeScript
|
||||||
<Image
|
<Image className={clsx('h-full w-full object-cover object-center')} {...props} />
|
||||||
className={clsx('relative h-full w-full object-contain', {
|
) : (
|
||||||
'transition duration-300 ease-in-out group-hover:scale-105': isInteractive
|
<div
|
||||||
})}
|
className="flex h-full w-full items-center justify-center text-gray-400"
|
||||||
{...props}
|
title="Missing product image"
|
||||||
/>
|
>
|
||||||
) : null}
|
<PhotoIcon className="size-7" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
{label ? (
|
{label ? (
|
||||||
<Label
|
<Label title={label.title} amount={label.amount} currencyCode={label.currencyCode} />
|
||||||
title={label.title}
|
|
||||||
amount={label.amount}
|
|
||||||
currencyCode={label.currencyCode}
|
|
||||||
position={label.position}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,33 +1,24 @@
|
|||||||
import clsx from 'clsx';
|
|
||||||
import Price from './price';
|
import Price from './price';
|
||||||
|
|
||||||
const Label = ({
|
const Label = ({
|
||||||
title,
|
title,
|
||||||
amount,
|
amount,
|
||||||
currencyCode,
|
currencyCode
|
||||||
position = 'bottom'
|
|
||||||
}: {
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
currencyCode: string;
|
currencyCode: string;
|
||||||
position?: 'bottom' | 'center';
|
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="flex flex-col">
|
||||||
className={clsx('absolute bottom-0 left-0 flex w-full px-4 pb-4 @container/label', {
|
<h3 className="mt-4 text-sm text-gray-700">{title}</h3>
|
||||||
'lg:px-20 lg:pb-[35%]': position === 'center'
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<div className="flex items-center rounded-full border bg-white/70 p-1 text-xs font-semibold text-black backdrop-blur-md dark:border-neutral-800 dark:bg-black/70 dark:text-white">
|
|
||||||
<h3 className="mr-4 line-clamp-2 flex-grow pl-2 leading-none tracking-tight">{title}</h3>
|
|
||||||
<Price
|
<Price
|
||||||
className="flex-none rounded-full bg-blue-600 p-2 text-white"
|
className="text-lg font-medium text-gray-900"
|
||||||
amount={amount}
|
amount={amount}
|
||||||
currencyCode={currencyCode}
|
currencyCode={currencyCode}
|
||||||
currencyCodeClassName="hidden @[275px]/label:inline"
|
currencyCodeClassName="hidden @[275px]/label:inline"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ export default function ProductGridItems({ products }: { products: Product[] })
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{products.map((product) => (
|
{products.map((product) => (
|
||||||
<Grid.Item key={product.handle} className="animate-fadeIn">
|
<Grid.Item key={product.handle} className="animate-fadeIn rounded-lg">
|
||||||
<Link className="relative inline-block h-full w-full" href={`/product/${product.handle}`}>
|
<Link className="relative inline-block h-full w-full" href={`/product/${product.handle}`}>
|
||||||
<GridTileImage
|
<GridTileImage
|
||||||
alt={product.title}
|
alt={product.title}
|
||||||
|
@ -3,20 +3,11 @@
|
|||||||
import { Dialog, DialogPanel, Transition, TransitionChild } from '@headlessui/react';
|
import { Dialog, DialogPanel, Transition, TransitionChild } from '@headlessui/react';
|
||||||
import { FunnelIcon } from '@heroicons/react/24/outline';
|
import { FunnelIcon } from '@heroicons/react/24/outline';
|
||||||
import { XMarkIcon } from '@heroicons/react/24/solid';
|
import { XMarkIcon } from '@heroicons/react/24/solid';
|
||||||
import { Filter, Menu } from 'lib/shopify/types';
|
import { Filter } from 'lib/shopify/types';
|
||||||
import { Fragment, useState } from 'react';
|
import { Fragment, ReactNode, useState } from 'react';
|
||||||
import Filters from './filters-list';
|
import Filters from './filters-list';
|
||||||
import SubMenu from './sub-menu';
|
|
||||||
|
|
||||||
const MobileFilters = ({
|
const MobileFilters = ({ filters, menu }: { filters: Filter[]; menu: ReactNode }) => {
|
||||||
collection,
|
|
||||||
filters,
|
|
||||||
menu
|
|
||||||
}: {
|
|
||||||
collection: string;
|
|
||||||
filters: Filter[];
|
|
||||||
menu: Menu[];
|
|
||||||
}) => {
|
|
||||||
const [openDialog, setOpenDialog] = useState(false);
|
const [openDialog, setOpenDialog] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -64,7 +55,7 @@ const MobileFilters = ({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 border-t border-gray-200 px-4 pt-4">
|
<div className="mt-4 border-t border-gray-200 px-4 pt-4">
|
||||||
<SubMenu collection={collection} menu={menu} />
|
{menu}
|
||||||
<Filters filters={filters} defaultOpen={false} />
|
<Filters filters={filters} defaultOpen={false} />
|
||||||
</div>
|
</div>
|
||||||
</DialogPanel>
|
</DialogPanel>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { Menu } from 'lib/shopify/types';
|
import { getMenu } from 'lib/shopify';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
const SubMenu = ({ menu, collection }: { menu: Menu[]; collection: string }) => {
|
const SubMenu = async ({ collection }: { collection: string }) => {
|
||||||
|
const menu = await getMenu('main-menu');
|
||||||
|
|
||||||
const subMenu = menu.find((item) => item.path === `/search/${collection}`)?.items || [];
|
const subMenu = menu.find((item) => item.path === `/search/${collection}`)?.items || [];
|
||||||
|
|
||||||
return subMenu.length ? (
|
return subMenu.length ? (
|
||||||
|
21
components/layout/search/header.tsx
Normal file
21
components/layout/search/header.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { getCollection } from 'lib/shopify';
|
||||||
|
|
||||||
|
const Header = async ({ collection }: { collection: string }) => {
|
||||||
|
const collectionData = await getCollection(collection);
|
||||||
|
|
||||||
|
return collectionData ? (
|
||||||
|
<div className="mb-3 mt-3 max-w-5xl lg:mb-1">
|
||||||
|
<h1 className="text-4xl font-bold tracking-tight text-gray-900">{collectionData.title}</h1>
|
||||||
|
<p className="mt-2 text-base text-gray-500">{collectionData.description}</p>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HeaderPlaceholder = () => {
|
||||||
|
return (
|
||||||
|
<div className="mb-3 mt-3 max-w-5xl lg:mb-1">
|
||||||
|
<div className="h-10 w-1/2 rounded bg-gray-200" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Header;
|
25
components/layout/search/placeholder.tsx
Normal file
25
components/layout/search/placeholder.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import Grid from 'components/grid';
|
||||||
|
|
||||||
|
const ProductsGridPlaceholder = () => {
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<Grid className="animate-pulse pt-5 lg:grid-cols-3 lg:gap-x-8 xl:grid-cols-4">
|
||||||
|
<aside className="hidden lg:flex lg:flex-col lg:gap-4">
|
||||||
|
<div className="h-32 w-full rounded bg-gray-200" />
|
||||||
|
<div className="h-32 w-full rounded bg-gray-200" />
|
||||||
|
<div className="h-32 w-full rounded bg-gray-200" />
|
||||||
|
<div className="h-32 w-full rounded bg-gray-200" />
|
||||||
|
</aside>
|
||||||
|
<div className="lg:col-span-2 xl:col-span-3">
|
||||||
|
<Grid className="grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{Array.from({ length: 9 }).map((_, index) => (
|
||||||
|
<div key={index} className="h-96 w-full rounded-lg bg-gray-200" />
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductsGridPlaceholder;
|
@ -28,7 +28,7 @@ export function Gallery({ images }: { images: { src: string; altText: string }[]
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="relative aspect-square h-full max-h-[550px] w-full overflow-hidden">
|
<div className="relative aspect-1 h-full max-h-[550px] w-full overflow-hidden">
|
||||||
{images[imageIndex] && (
|
{images[imageIndex] && (
|
||||||
<Image
|
<Image
|
||||||
className="h-full w-full object-contain"
|
className="h-full w-full object-contain"
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"tailwind-merge": "^2.2.2"
|
"tailwind-merge": "^2.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@tailwindcss/typography": "^0.5.11",
|
"@tailwindcss/typography": "^0.5.11",
|
||||||
|
11
pnpm-lock.yaml
generated
11
pnpm-lock.yaml
generated
@ -40,6 +40,9 @@ dependencies:
|
|||||||
version: 2.2.2
|
version: 2.2.2
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@tailwindcss/aspect-ratio':
|
||||||
|
specifier: ^0.4.2
|
||||||
|
version: 0.4.2(tailwindcss@3.4.1)
|
||||||
'@tailwindcss/container-queries':
|
'@tailwindcss/container-queries':
|
||||||
specifier: ^0.1.1
|
specifier: ^0.1.1
|
||||||
version: 0.1.1(tailwindcss@3.4.1)
|
version: 0.1.1(tailwindcss@3.4.1)
|
||||||
@ -688,6 +691,14 @@ packages:
|
|||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@tailwindcss/aspect-ratio@0.4.2(tailwindcss@3.4.1):
|
||||||
|
resolution: {integrity: sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==}
|
||||||
|
peerDependencies:
|
||||||
|
tailwindcss: '>=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1'
|
||||||
|
dependencies:
|
||||||
|
tailwindcss: 3.4.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.1):
|
/@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.1):
|
||||||
resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==}
|
resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -57,6 +57,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
require('@tailwindcss/forms')
|
require('@tailwindcss/forms'),
|
||||||
|
require('@tailwindcss/aspect-ratio')
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user