Product Collections
Ported from HyperUI’s Product Collections — see Attribution.
const _photoUrl = 'https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160';
class ProductCollections1Example extends StatelessWidget { const ProductCollections1Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8', children: [ const Style( 'text-xl font-bold text-gray-900 sm:text-3xl', child: Text('Product Collection'), ), const Style( 'mt-4 max-w-md text-gray-500', child: Text( 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque ' 'praesentium cumque iure dicta incidunt est ipsam, officia dolor ' 'fugit natus?', ), ), Style( 'mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-4', children: [ Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), ], ), ], ); }}<section> <div class="mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8"> <header> <h2 class="text-xl font-bold text-gray-900 sm:text-3xl">Product Collection</h2>
<p class="mt-4 max-w-md text-gray-500"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque praesentium cumque iure dicta incidunt est ipsam, officia dolor fugit natus? </p> </header>
<ul class="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-4"> <li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li> </ul> </div></section>Base with centered title
Section titled “Base with centered title”const _photoUrl = 'https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160';
class ProductCollections2Example extends StatelessWidget { const ProductCollections2Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8', children: [ Style( 'text-center', children: [ const Style( 'text-xl font-bold text-gray-900 sm:text-3xl', child: Text('Product Collection'), ), const Style( 'mx-auto mt-4 max-w-md text-gray-500', child: Text( 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque ' 'praesentium cumque iure dicta incidunt est ipsam, officia dolor ' 'fugit natus?', ), ), ], ), Style( 'mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-4', children: [ Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), ], ), ], ); }}<section> <div class="mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8"> <header class="text-center"> <h2 class="text-xl font-bold text-gray-900 sm:text-3xl">Product Collection</h2>
<p class="mx-auto mt-4 max-w-md text-gray-500"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque praesentium cumque iure dicta incidunt est ipsam, officia dolor fugit natus? </p> </header>
<ul class="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-4"> <li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li> </ul> </div></section>Filtering (Dropdown)
Section titled “Filtering (Dropdown)”class CurrentColorIcon extends StatelessWidget implements StyleReplacedElementWrapper { const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override Widget build(BuildContext context) { final color = IconTheme.of(context).color ?? const Color(0xFF000000); return SvgPicture.string(svg, theme: SvgTheme(currentColor: color)); }}
const _photoUrl = 'https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160';
const _chevronDownSvg = '''<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5"/></svg>''';
const _filterToggleSvg = '''<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5"/></svg>''';
Widget _buildPriceField(BuildContext context, {required String hintText}) { final isSmUp = MediaQuery.sizeOf(context).width >= 640; final fontSize = isSmUp ? 14.0 : 16.0; final lineHeight = isSmUp ? 20.0 : 24.0; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return DecoratedBox( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all(color: const Color(0xFFE5E7EB)), boxShadow: const [ BoxShadow(color: Color(0x0D000000), offset: Offset(0, 1), blurRadius: 2), ], ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Text( hintText, style: baseStyle.copyWith( fontSize: fontSize, height: lineHeight / fontSize, color: tailwindColors['gray']![400], letterSpacing: 0, ), ), ), );}
class ProductCollections3Example extends StatefulWidget { const ProductCollections3Example({super.key});
@override State<ProductCollections3Example> createState() => _ProductCollections3ExampleState();}
class _ProductCollections3ExampleState extends State<ProductCollections3Example> { var _availabilityOpen = false; var _priceOpen = false;
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8', children: [ const Style( 'text-xl font-bold text-gray-900 sm:text-3xl', child: Text('Product Collection'), ), const Style( 'mt-4 max-w-md text-gray-500', child: Text( 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque ' 'praesentium cumque iure dicta incidunt est ipsam, officia dolor ' 'fugit natus?', ), ), Style( 'mt-8 sm:flex sm:items-center sm:justify-between', children: [ Style( 'block sm:hidden', child: Style( 'flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Filters & Sorting'), ), const Style( 'size-4 rtl:rotate-180', child: CurrentColorIcon(_filterToggleSvg), ), ], ), ), Style( 'hidden sm:flex sm:gap-4', children: [ Style( 'relative', child: Style( 'group [&_summary::-webkit-details-marker]:hidden', open: _availabilityOpen, children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState( () => _availabilityOpen = !_availabilityOpen, ), child: Style( 'flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Availability'), ), Style( 'transition group-open:-rotate-180', child: const Style( 'size-4', child: CurrentColorIcon(_chevronDownSvg), ), ), ], ), ), if (_availabilityOpen) Style( 'z-50 group-open:absolute group-open:top-auto group-open:mt-2 ltr:group-open:start-0', child: Style( 'w-96 rounded-sm border border-gray-200 bg-white', children: [ Style( 'flex items-center justify-between p-4', children: const [ Style( 'text-sm text-gray-700', display: DisplayType.inline, child: Text('0 Selected'), ), Style( 'text-sm text-gray-900 underline underline-offset-4', child: Text('Reset'), ), ], ), Style( 'space-y-1 border-t border-gray-200 p-4', children: const [ Padding( padding: EdgeInsets.only(bottom: 7), child: Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('In Stock (5+)'), ), ], ), ), Padding( padding: EdgeInsets.only(bottom: 7), child: Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Pre Order (3+)'), ), ], ), ), Padding( padding: EdgeInsets.only(bottom: 7), child: Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Out of Stock (10+)'), ), ], ), ), ], ), ], ), ), ], ), ), Style( 'relative', child: Style( 'group [&_summary::-webkit-details-marker]:hidden', open: _priceOpen, children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _priceOpen = !_priceOpen), child: Style( 'flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Price'), ), Style( 'transition group-open:-rotate-180', child: const Style( 'size-4', child: CurrentColorIcon(_chevronDownSvg), ), ), ], ), ), if (_priceOpen) Style( 'z-50 group-open:absolute group-open:top-auto group-open:mt-2 ltr:group-open:start-0', child: Style( 'w-96 rounded-sm border border-gray-200 bg-white', children: [ const Style( 'flex items-center justify-between p-4', children: [ Style( 'text-sm text-gray-700', display: DisplayType.inline, child: Text('The highest price is \$600'), ), Style( 'text-sm text-gray-900 underline underline-offset-4', child: Text('Reset'), ), ], ), Style( 'border-t border-gray-200 p-4', child: Style( 'flex justify-between gap-4', children: [ Style( 'flex items-center gap-2', children: [ const Style( 'text-sm text-gray-600', display: DisplayType.inline, child: Text('\$'), ), Style( 'w-full rounded-md border-gray-200 shadow-xs sm:text-sm', child: _buildPriceField( context, hintText: 'From', ), ), ], ), Style( 'flex items-center gap-2', children: [ const Style( 'text-sm text-gray-600', display: DisplayType.inline, child: Text('\$'), ), Style( 'w-full rounded-md border-gray-200 shadow-xs sm:text-sm', child: _buildPriceField( context, hintText: 'To', ), ), ], ), ], ), ), ], ), ), ], ), ), ], ), Style( 'hidden sm:block', children: [ const Style('sr-only', child: Text('SortBy')), Style( 'h-10 rounded-sm border-gray-300 text-sm', child: Builder( builder: (context) { final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(2), border: Border.all( color: const Color(0xFFD1D5DB), ), ), padding: const EdgeInsets.symmetric(horizontal: 12), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( 'Sort By', style: baseStyle.copyWith( fontSize: 14, height: 20 / 14, color: const Color(0xFF111827), letterSpacing: 0, ), ), Padding( padding: const EdgeInsets.only(left: 8), child: SvgPicture.string( _selectChevronSvg, width: 21, height: 21, ), ), ], ), ); }, ), ), ], ), ], ), Style( 'mt-4 grid gap-4 sm:grid-cols-2 lg:grid-cols-4', children: [ Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), ], ), ], ); }}
const _selectChevronSvg = '''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"><path stroke="#6b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 8l4 4 4-4"/></svg>''';<section> <div class="mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8"> <header> <h2 class="text-xl font-bold text-gray-900 sm:text-3xl">Product Collection</h2>
<p class="mt-4 max-w-md text-gray-500"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque praesentium cumque iure dicta incidunt est ipsam, officia dolor fugit natus? </p> </header>
<div class="mt-8 sm:flex sm:items-center sm:justify-between"> <div class="block sm:hidden"> <button class="flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600" > <span class="text-sm font-medium"> Filters & Sorting </span>
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4 rtl:rotate-180" > <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /> </svg> </button> </div>
<div class="hidden sm:flex sm:gap-4"> <div class="relative"> <details class="group [&_summary::-webkit-details-marker]:hidden"> <summary class="flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600" > <span class="text-sm font-medium"> Availability </span>
<span class="transition group-open:-rotate-180"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" /> </svg> </span> </summary>
<div class="z-50 group-open:absolute group-open:top-auto group-open:mt-2 ltr:group-open:start-0" > <div class="w-96 rounded-sm border border-gray-200 bg-white"> <header class="flex items-center justify-between p-4"> <span class="text-sm text-gray-700"> 0 Selected </span>
<button type="button" class="text-sm text-gray-900 underline underline-offset-4" > Reset </button> </header>
<ul class="space-y-1 border-t border-gray-200 p-4"> <li> <label for="FilterInStock" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterInStock" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> In Stock (5+) </span> </label> </li>
<li> <label for="FilterPreOrder" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterPreOrder" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Pre Order (3+) </span> </label> </li>
<li> <label for="FilterOutOfStock" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterOutOfStock" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Out of Stock (10+) </span> </label> </li> </ul> </div> </div> </details> </div>
<div class="relative"> <details class="group [&_summary::-webkit-details-marker]:hidden"> <summary class="flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600" > <span class="text-sm font-medium"> Price </span>
<span class="transition group-open:-rotate-180"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" /> </svg> </span> </summary>
<div class="z-50 group-open:absolute group-open:top-auto group-open:mt-2 ltr:group-open:start-0" > <div class="w-96 rounded-sm border border-gray-200 bg-white"> <header class="flex items-center justify-between p-4"> <span class="text-sm text-gray-700"> The highest price is $600 </span>
<button type="button" class="text-sm text-gray-900 underline underline-offset-4" > Reset </button> </header>
<div class="border-t border-gray-200 p-4"> <div class="flex justify-between gap-4"> <label for="FilterPriceFrom" class="flex items-center gap-2"> <span class="text-sm text-gray-600">$</span>
<input type="number" id="FilterPriceFrom" placeholder="From" class="w-full rounded-md border-gray-200 shadow-xs sm:text-sm" /> </label>
<label for="FilterPriceTo" class="flex items-center gap-2"> <span class="text-sm text-gray-600">$</span>
<input type="number" id="FilterPriceTo" placeholder="To" class="w-full rounded-md border-gray-200 shadow-xs sm:text-sm" /> </label> </div> </div> </div> </div> </details> </div> </div>
<div class="hidden sm:block"> <label for="SortBy" class="sr-only">SortBy</label>
<select id="SortBy" class="h-10 rounded-sm border-gray-300 text-sm"> <option>Sort By</option> <option value="Title, DESC">Title, DESC</option> <option value="Title, ASC">Title, ASC</option> <option value="Price, DESC">Price, DESC</option> <option value="Price, ASC">Price, ASC</option> </select> </div> </div>
<ul class="mt-4 grid gap-4 sm:grid-cols-2 lg:grid-cols-4"> <li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li> </ul> </div></section>Filtering (Side)
Section titled “Filtering (Side)”class CurrentColorIcon extends StatelessWidget implements StyleReplacedElementWrapper { const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override Widget build(BuildContext context) { final color = IconTheme.of(context).color ?? const Color(0xFF000000); return SvgPicture.string(svg, theme: SvgTheme(currentColor: color)); }}
const _photoUrl = 'https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160';
const _chevronDownSvg = '''<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5"/></svg>''';
const _filterToggleSvg = '''<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5"/></svg>''';
const _selectChevronSvg = '''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"><path stroke="#6b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 8l4 4 4-4"/></svg>''';
class ProductCollections4Example extends StatefulWidget { const ProductCollections4Example({super.key});
@override State<ProductCollections4Example> createState() => _ProductCollections4ExampleState();}
class _ProductCollections4ExampleState extends State<ProductCollections4Example> { var _availabilityOpen = false; var _priceOpen = false; var _colorsOpen = false;
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8', children: [ const Style( 'text-xl font-bold text-gray-900 sm:text-3xl', child: Text('Product Collection'), ), const Style( 'mt-4 max-w-md text-gray-500', child: Text( 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque ' 'praesentium cumque iure dicta incidunt est ipsam, officia dolor ' 'fugit natus?', ), ), Style( 'mt-8 block lg:hidden', child: Style( 'flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Filters & Sorting'), ), const Style( 'size-4 rtl:rotate-180', child: CurrentColorIcon(_filterToggleSvg), ), ], ), ), Style( 'mt-4 lg:mt-8 lg:grid lg:grid-cols-4 lg:items-start lg:gap-8', children: [ Style( 'hidden space-y-4 lg:block', children: [ Style.empty( children: [ const Style( 'block text-xs font-medium text-gray-700', child: Text('Sort By'), ), Style( 'mt-1 rounded-sm border-gray-300 text-sm', child: Builder( builder: (context) { final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular( 2, ), border: Border.all( color: const Color( 0xFFD1D5DB, ), ), ), padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 8, ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( 'Sort By', style: baseStyle.copyWith( fontSize: 14, height: 20 / 14, color: const Color(0xFF111827), letterSpacing: 0, ), ), Padding( padding: const EdgeInsets.only(left: 8), child: SvgPicture.string( _selectChevronSvg, width: 21, height: 21, ), ), ], ), ); }, ), ), ], ), Style.empty( children: [ const Style( 'block text-xs font-medium text-gray-700', child: Text('Filters'), ), Style( 'mt-1 space-y-2', children: [ Style( 'overflow-hidden rounded-sm border border-gray-300 [&_summary::-webkit-details-marker]:hidden', children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState( () => _availabilityOpen = !_availabilityOpen, ), child: Style( 'flex cursor-pointer items-center justify-between gap-2 p-4 text-gray-900 transition', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Availability'), ), const Style( 'transition group-open:-rotate-180', child: Style( 'size-4', child: CurrentColorIcon(_chevronDownSvg), ), ), ], ), ), if (_availabilityOpen) Style( 'border-t border-gray-200 bg-white', children: [ const Style( 'flex items-center justify-between p-4', children: [ Style( 'text-sm text-gray-700', display: DisplayType.inline, child: Text('0 Selected'), ), Style( 'text-sm text-gray-900 underline underline-offset-4', child: Text('Reset'), ), ], ), Style( 'space-y-1 border-t border-gray-200 p-4', children: const [ Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('In Stock (5+)'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Pre Order (3+)'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Out of Stock (10+)'), ), ], ), ], ), ], ), ], ), Style( 'overflow-hidden rounded-sm border border-gray-300 [&_summary::-webkit-details-marker]:hidden', children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _priceOpen = !_priceOpen), child: Style( 'flex cursor-pointer items-center justify-between gap-2 p-4 text-gray-900 transition', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Price'), ), const Style( 'transition group-open:-rotate-180', child: Style( 'size-4', child: CurrentColorIcon(_chevronDownSvg), ), ), ], ), ), if (_priceOpen) Style( 'border-t border-gray-200 bg-white', children: [ const Style( 'flex items-center justify-between p-4', children: [ Style( 'text-sm text-gray-700', display: DisplayType.inline, child: Text( 'The highest price is \$600', ), ), Style( 'text-sm text-gray-900 underline underline-offset-4', child: Text('Reset'), ), ], ), Style( 'border-t border-gray-200 p-4', child: Style( 'flex justify-between gap-4', children: [ Style( 'flex items-center gap-2', children: [ const Style( 'text-sm text-gray-600', display: DisplayType.inline, child: Text('\$'), ), Style( 'w-full rounded-md border-gray-200 shadow-xs sm:text-sm', child: Builder( builder: (context) => _buildPriceField( context, hintText: 'From', ), ), ), ], ), Style( 'flex items-center gap-2', children: [ const Style( 'text-sm text-gray-600', display: DisplayType.inline, child: Text('\$'), ), Style( 'w-full rounded-md border-gray-200 shadow-xs sm:text-sm', child: Builder( builder: (context) => _buildPriceField( context, hintText: 'To', ), ), ), ], ), ], ), ), ], ), ], ), Style( 'overflow-hidden rounded-sm border border-gray-300 [&_summary::-webkit-details-marker]:hidden', children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _colorsOpen = !_colorsOpen), child: Style( 'flex cursor-pointer items-center justify-between gap-2 p-4 text-gray-900 transition', cursor: SystemMouseCursors.click, children: [ const Style( 'text-sm font-medium', display: DisplayType.inline, child: Text('Colors'), ), const Style( 'transition group-open:-rotate-180', child: Style( 'size-4', child: CurrentColorIcon(_chevronDownSvg), ), ), ], ), ), if (_colorsOpen) Style( 'border-t border-gray-200 bg-white', children: [ const Style( 'flex items-center justify-between p-4', children: [ Style( 'text-sm text-gray-700', display: DisplayType.inline, child: Text('0 Selected'), ), Style( 'text-sm text-gray-900 underline underline-offset-4', child: Text('Reset'), ), ], ), Style( 'space-y-1 border-t border-gray-200 p-4', children: const [ Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Red'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Blue'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Green'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Orange'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Purple'), ), ], ), Style( 'inline-flex items-center gap-2', children: [ Style( 'size-5 rounded-sm border-gray-300 shadow-sm', formControl: true, ), Style( 'text-sm font-medium text-gray-700', display: DisplayType.inline, child: Text('Teal'), ), ], ), ], ), ], ), ], ), ], ), ], ), ], ), Style( 'lg:col-span-3', child: Style( 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3', children: [ Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), Style( 'group block overflow-hidden', cursor: SystemMouseCursors.click, children: [ Style( 'h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5', child: Image.network(_photoUrl, fit: BoxFit.cover), ), Style( 'relative bg-white pt-3', children: [ const Style( 'text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4', child: Text('Basic Tee'), ), Style( 'mt-2', children: const [ Style('sr-only', child: Text('Regular Price')), Style( 'tracking-wider text-gray-900', child: Text('£24.00 GBP'), ), ], ), ], ), ], ), ], ), ), ], ), ], ); }}
Widget _buildPriceField(BuildContext context, {required String hintText}) { final isSmUp = MediaQuery.sizeOf(context).width >= 640; final fontSize = isSmUp ? 14.0 : 16.0; final lineHeight = isSmUp ? 20.0 : 24.0; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all(color: const Color(0xFFE5E7EB)), boxShadow: const [ BoxShadow(color: Color(0x0D000000), offset: Offset(0, 1), blurRadius: 2), ], ), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Text( hintText, style: baseStyle.copyWith( fontSize: fontSize, height: lineHeight / fontSize, color: tailwindColors['gray']![400], letterSpacing: 0, ), ), );}<section> <div class="mx-auto max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8"> <header> <h2 class="text-xl font-bold text-gray-900 sm:text-3xl">Product Collection</h2>
<p class="mt-4 max-w-md text-gray-500"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Itaque praesentium cumque iure dicta incidunt est ipsam, officia dolor fugit natus? </p> </header>
<div class="mt-8 block lg:hidden"> <button class="flex cursor-pointer items-center gap-2 border-b border-gray-400 pb-1 text-gray-900 transition hover:border-gray-600" > <span class="text-sm font-medium"> Filters & Sorting </span>
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4 rtl:rotate-180" > <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /> </svg> </button> </div>
<div class="mt-4 lg:mt-8 lg:grid lg:grid-cols-4 lg:items-start lg:gap-8"> <div class="hidden space-y-4 lg:block"> <div> <label for="SortBy" class="block text-xs font-medium text-gray-700"> Sort By </label>
<select id="SortBy" class="mt-1 rounded-sm border-gray-300 text-sm"> <option>Sort By</option> <option value="Title, DESC">Title, DESC</option> <option value="Title, ASC">Title, ASC</option> <option value="Price, DESC">Price, DESC</option> <option value="Price, ASC">Price, ASC</option> </select> </div>
<div> <p class="block text-xs font-medium text-gray-700">Filters</p>
<div class="mt-1 space-y-2"> <details class="overflow-hidden rounded-sm border border-gray-300 [&_summary::-webkit-details-marker]:hidden" > <summary class="flex cursor-pointer items-center justify-between gap-2 p-4 text-gray-900 transition" > <span class="text-sm font-medium"> Availability </span>
<span class="transition group-open:-rotate-180"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" /> </svg> </span> </summary>
<div class="border-t border-gray-200 bg-white"> <header class="flex items-center justify-between p-4"> <span class="text-sm text-gray-700"> 0 Selected </span>
<button type="button" class="text-sm text-gray-900 underline underline-offset-4" > Reset </button> </header>
<ul class="space-y-1 border-t border-gray-200 p-4"> <li> <label for="FilterInStock" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterInStock" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> In Stock (5+) </span> </label> </li>
<li> <label for="FilterPreOrder" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterPreOrder" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Pre Order (3+) </span> </label> </li>
<li> <label for="FilterOutOfStock" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterOutOfStock" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Out of Stock (10+) </span> </label> </li> </ul> </div> </details>
<details class="overflow-hidden rounded-sm border border-gray-300 [&_summary::-webkit-details-marker]:hidden" > <summary class="flex cursor-pointer items-center justify-between gap-2 p-4 text-gray-900 transition" > <span class="text-sm font-medium"> Price </span>
<span class="transition group-open:-rotate-180"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" /> </svg> </span> </summary>
<div class="border-t border-gray-200 bg-white"> <header class="flex items-center justify-between p-4"> <span class="text-sm text-gray-700"> The highest price is $600 </span>
<button type="button" class="text-sm text-gray-900 underline underline-offset-4" > Reset </button> </header>
<div class="border-t border-gray-200 p-4"> <div class="flex justify-between gap-4"> <label for="FilterPriceFrom" class="flex items-center gap-2"> <span class="text-sm text-gray-600">$</span>
<input type="number" id="FilterPriceFrom" placeholder="From" class="w-full rounded-md border-gray-200 shadow-xs sm:text-sm" /> </label>
<label for="FilterPriceTo" class="flex items-center gap-2"> <span class="text-sm text-gray-600">$</span>
<input type="number" id="FilterPriceTo" placeholder="To" class="w-full rounded-md border-gray-200 shadow-xs sm:text-sm" /> </label> </div> </div> </div> </details>
<details class="overflow-hidden rounded-sm border border-gray-300 [&_summary::-webkit-details-marker]:hidden" > <summary class="flex cursor-pointer items-center justify-between gap-2 p-4 text-gray-900 transition" > <span class="text-sm font-medium"> Colors </span>
<span class="transition group-open:-rotate-180"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" /> </svg> </span> </summary>
<div class="border-t border-gray-200 bg-white"> <header class="flex items-center justify-between p-4"> <span class="text-sm text-gray-700"> 0 Selected </span>
<button type="button" class="text-sm text-gray-900 underline underline-offset-4" > Reset </button> </header>
<ul class="space-y-1 border-t border-gray-200 p-4"> <li> <label for="FilterRed" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterRed" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Red </span> </label> </li>
<li> <label for="FilterBlue" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterBlue" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Blue </span> </label> </li>
<li> <label for="FilterGreen" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterGreen" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Green </span> </label> </li>
<li> <label for="FilterOrange" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterOrange" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Orange </span> </label> </li>
<li> <label for="FilterPurple" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterPurple" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Purple </span> </label> </li>
<li> <label for="FilterTeal" class="inline-flex items-center gap-2"> <input type="checkbox" id="FilterTeal" class="size-5 rounded-sm border-gray-300 shadow-sm" />
<span class="text-sm font-medium text-gray-700"> Teal </span> </label> </li> </ul> </div> </details> </div> </div> </div>
<div class="lg:col-span-3"> <ul class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> <li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li>
<li> <a href="#" class="group block overflow-hidden"> <img src="https://images.unsplash.com/photo-1523381210434-271e8be1f52b?auto=format&fit=crop&q=80&w=1160" alt="" class="h-87.5 w-full object-cover transition duration-500 group-hover:scale-105 sm:h-112.5" />
<div class="relative bg-white pt-3"> <h3 class="text-xs text-gray-700 group-hover:underline group-hover:underline-offset-4" > Basic Tee </h3>
<p class="mt-2"> <span class="sr-only"> Regular Price </span>
<span class="tracking-wider text-gray-900"> £24.00 GBP </span> </p> </div> </a> </li> </ul> </div> </div> </div></section>