feat(carousel): enhance product list layout with adaptive grid and simple vertical options
This commit is contained in:
@@ -53,6 +53,8 @@
|
||||
class="product-list"
|
||||
[class.product-list--row]="effectiveLayout() === 'row'"
|
||||
[class.product-list--column]="effectiveLayout() !== 'row'"
|
||||
[class.product-list--adaptive]="groupLayout() !== 'simple_vertical'"
|
||||
[class.product-list--simple-vertical]="groupLayout() === 'simple_vertical'"
|
||||
>
|
||||
@for (item of itemData(); track item.id; let index = $index) {
|
||||
<ng-container
|
||||
|
||||
@@ -4,39 +4,34 @@
|
||||
}
|
||||
|
||||
.product-list {
|
||||
--product-list-item-min-width: 16rem;
|
||||
|
||||
display: grid;
|
||||
width: 100%;
|
||||
gap: 1.5rem;
|
||||
|
||||
&--row {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
|
||||
.product-list__item {
|
||||
width: 100%;
|
||||
}
|
||||
--product-list-item-min-width: 32rem;
|
||||
}
|
||||
|
||||
&--column {
|
||||
container-name: product-list;
|
||||
container-type: inline-size;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
&--adaptive {
|
||||
grid-template-columns: repeat(
|
||||
auto-fit,
|
||||
minmax(min(100%, var(--product-list-item-min-width)), 1fr)
|
||||
);
|
||||
}
|
||||
|
||||
.product-list__item {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
&--simple-vertical {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
&__item {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
|
||||
&--carousel {
|
||||
width: 100%;
|
||||
min-width: clamp(15rem, 30vw, 18rem);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&--carousel-row {
|
||||
@@ -45,27 +40,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@container product-list (min-width: 544px) {
|
||||
.product-list--column .product-list__item {
|
||||
flex-basis: calc((100% - 1.5rem) / 2);
|
||||
max-width: calc((100% - 1.5rem) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@container product-list (min-width: 828px) {
|
||||
.product-list--column .product-list__item {
|
||||
flex-basis: calc((100% - 3rem) / 3);
|
||||
max-width: calc((100% - 3rem) / 3);
|
||||
}
|
||||
}
|
||||
|
||||
@container product-list (min-width: 1112px) {
|
||||
.product-list--column .product-list__item {
|
||||
flex-basis: calc((100% - 4.5rem) / 4);
|
||||
max-width: calc((100% - 4.5rem) / 4);
|
||||
}
|
||||
}
|
||||
|
||||
.product-list__paginator {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
@@ -79,11 +79,12 @@ describe('ProductListComponent', () => {
|
||||
};
|
||||
}
|
||||
|
||||
it('renders every row product at full available width', async () => {
|
||||
it('renders row products in the adaptive grid', async () => {
|
||||
const fixture = await render('row');
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
expect(element.querySelector('.product-list--row')).not.toBeNull();
|
||||
expect(element.querySelector('.product-list--adaptive')).not.toBeNull();
|
||||
expect(element.querySelectorAll('app-product-row-card')).toHaveLength(2);
|
||||
expect(element.querySelector('app-product-column-with-image')).toBeNull();
|
||||
});
|
||||
@@ -143,9 +144,19 @@ describe('ProductListComponent', () => {
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
expect(element.querySelectorAll('app-product-row-card')).toHaveLength(2);
|
||||
expect(element.querySelector('.product-list--adaptive')).not.toBeNull();
|
||||
expect(element.querySelector('app-paginator')).toBeNull();
|
||||
});
|
||||
|
||||
it('keeps simple vertical groups to one full-width item per row', async () => {
|
||||
const fixture = await render('column_with_image', items, 'simple_vertical');
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
expect(element.querySelector('.product-list--simple-vertical')).not.toBeNull();
|
||||
expect(element.querySelector('.product-list--adaptive')).toBeNull();
|
||||
expect(element.querySelectorAll('app-product-column-with-image')).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('renders carousel groups with the reusable carousel', async () => {
|
||||
const fixture = await render('column_with_image', items, 'carousel');
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
Reference in New Issue
Block a user