Skip to content

Commit

Permalink
feat(pie-thumbnail): DSW-2615 add the aspect ratio prop (#2184)
Browse files Browse the repository at this point in the history
* feat(pie-thumbnail): DSW-2580 add basic thumbnail functionality

* feat(pie-thumbnail): DSW-2583 add disabled thumbnail prop

* feat(pie-thumbnail): DSW-2583 add hasPadding thumbnail prop

* feat(pie-thumbnail): DSW-2582 add size prop

* feat(pie-thumbnail): DSW-2582 add size prop

* fix(pie-thumbnail): DSW-2582 revert some changes

* fix(pie-thumbnail): DSW-2582 revert some changes

* fix(pie-thumbnail): DSW-2582 add sizes

* feat(pie-thumbnail): DSW-2615 add the aspect ratio prop

* fix(pie-thumbnail): DSW-2615 apply background to the image to respect the asepct ratio

* fix(pie-thumbnail): DSW-2615 rever some changes

* fix(pie-thumbnail): DSW-2615 rever some changes

* fix(pie-thumbnail): DSW-2615 update aspect ratio calcs

* fix(pie-thumbnail): DSW-2615 allow images to be cropped instead of shrinking

* fix(pie-thumbnail): DSW-2615 revert some changes

* fix(pie-thumbnail): DSW-2615 update stories

* fix(pie-thumbnail): DSW-2615 update stories

* fix(pie-thumbnail): DSW-2615 update stories

* fix(pie-thumbnail): DSW-2615 fix tests

* fix(pie-thumbnail): DSW-2615 fix tests

* fix(pie-thumbnail): DSW-2615 update alt messages

* fix(pie-monorepo): DSW-000 revert changes

* fix(pie-thumbnail): DSW-2615 update tests

* fix(pie-thumbnail): DSW-2615 update snapshot tests

---------

Co-authored-by: boris.netsov <[email protected]>
  • Loading branch information
raoufswe and boris.netsov authored Feb 6, 2025
1 parent 95b604f commit 1adeb2e
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .changeset/sharp-spiders-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@justeattakeaway/pie-thumbnail": minor
"pie-storybook": minor
---

[Added] - the aspect ratio prop
Binary file added apps/pie-storybook/static/images/burger-16by9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/pie-storybook/static/images/burger-4by3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions apps/pie-storybook/static/images/pie-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 27 additions & 2 deletions apps/pie-storybook/stories/pie-thumbnail.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
variants,
backgroundColors,
sizes,
aspectRatios,
} from '@justeattakeaway/pie-thumbnail';

import { createStory, type TemplateFunction } from '../utilities';
Expand All @@ -17,8 +18,8 @@ type ThumbnailStoryMeta = Meta<ThumbnailProps>;

const defaultArgs: ThumbnailProps = {
...defaultProps,
src: 'https://www.pie.design/assets/img/jet-logo-narrow.svg',
alt: 'JET logo',
src: './static/images/pie-logo.svg',
alt: 'The PIE design system logo',
placeholder: {
src: 'https://www.pie.design/assets/img/404_narrow.png',
alt: 'Thumbnail placeholder image',
Expand Down Expand Up @@ -81,6 +82,14 @@ const thumbnailStoryMeta: ThumbnailStoryMeta = {
summary: defaultProps.backgroundColor,
},
},
aspectRatio: {
description: 'Sets the aspect-ratio of the thumbnail image.',
control: 'select',
options: aspectRatios,
defaultValue: {
summary: defaultProps.aspectRatio,
},
},
placeholder: {
description: 'If an image fails to load, the placeholder prop can be used to ensure there is always something visible to users.',
control: 'object',
Expand Down Expand Up @@ -109,10 +118,12 @@ const Template: TemplateFunction<ThumbnailProps> = ({
hasPadding,
backgroundColor,
placeholder,
aspectRatio,
}) => html`
<pie-thumbnail
variant="${ifDefined(variant)}"
size="${ifDefined(size)}"
aspectRatio="${ifDefined(aspectRatio)}"
src="${ifDefined(src)}"
alt="${ifDefined(alt)}"
backgroundColor="${ifDefined(backgroundColor)}"
Expand All @@ -128,3 +139,17 @@ export const Default = createThumbnailStory({}, {});
export const Outline = createThumbnailStory({
variant: 'outline',
}, {});

export const AspectRatio4By3 = createThumbnailStory({
size: 120,
src: './static/images/burger-4by3.png',
alt: 'Burger King meal with a cheeseburger, fries, onion rings, and Coca-Cola.',
aspectRatio: '4by3',
}, {});

export const AspectRatio16By9 = createThumbnailStory({
size: 128,
src: './static/images/burger-16by9.png',
alt: 'Chef assembling a burger in a kitchen.',
aspectRatio: '16by9',
}, {});
37 changes: 32 additions & 5 deletions apps/pie-storybook/stories/testing/pie-thumbnail.test.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
variants,
backgroundColors,
sizes,
aspectRatios,
} from '@justeattakeaway/pie-thumbnail';

import { type Meta } from '@storybook/web-components';
Expand All @@ -17,8 +18,8 @@ type ThumbnailStoryMeta = Meta<ThumbnailProps>;

const defaultArgs: ThumbnailProps = {
...defaultProps,
src: 'https://www.pie.design/assets/img/jet-logo-narrow.svg',
alt: 'JET logo',
src: './static/images/pie-logo.svg',
alt: 'The PIE design system logo',
placeholder: {
src: 'https://www.pie.design/assets/img/404_narrow.png',
alt: 'Thumbnail placeholder image',
Expand Down Expand Up @@ -81,6 +82,14 @@ const thumbnailStoryMeta: ThumbnailStoryMeta = {
summary: defaultProps.backgroundColor,
},
},
aspectRatio: {
description: 'Sets the aspect-ratio of the thumbnail image.',
control: 'select',
options: aspectRatios,
defaultValue: {
summary: defaultProps.aspectRatio,
},
},
placeholder: {
description: 'If an image fails to load, the placeholder prop can be used to ensure there is always something visible to users.',
control: 'object',
Expand All @@ -96,6 +105,7 @@ export default thumbnailStoryMeta;

const Template: TemplateFunction<ThumbnailProps> = ({
variant,
aspectRatio,
size,
src,
alt,
Expand All @@ -110,6 +120,7 @@ const Template: TemplateFunction<ThumbnailProps> = ({
src="${ifDefined(src)}"
alt="${ifDefined(alt)}"
backgroundColor="${ifDefined(backgroundColor)}"
aspectRatio="${ifDefined(aspectRatio)}"
?disabled="${disabled}"
?hasPadding="${hasPadding}"
.placeholder="${placeholder}">
Expand All @@ -119,11 +130,12 @@ const Template: TemplateFunction<ThumbnailProps> = ({
const sharedPropOptions = {
src: [defaultArgs.src],
alt: [defaultArgs.alt],
size: sizes,
size: [...sizes],
disabled: [true, false],
hasPadding: [true, false],
backgroundColor: [defaultArgs.backgroundColor],
placeholder: [defaultArgs.placeholder],
aspectRatio: [defaultArgs.aspectRatio],
};

const defaultPropOptions = {
Expand All @@ -142,6 +154,18 @@ const backgroundPropOptions = {
src: ['https://www.pie.design/assets/img/404_narrow.png'],
};

const aspectRatio4by3PropOptions = {
...sharedPropOptions,
aspectRatio: ['4by3'],
src: ['./static/images/burger-4by3.png'],
};

const aspectRatio16by9PropOptions = {
...sharedPropOptions,
aspectRatio: ['16by9'],
src: ['./static/images/burger-16by9.png'],
};

export const Default = createStory<ThumbnailProps>(Template, defaultArgs)();

export const InvalidSrc = createStory<ThumbnailProps>(Template, {
Expand All @@ -158,10 +182,13 @@ export const ValidSrcWithPlaceholder = createStory<ThumbnailProps>(Template, {
src: 'https://www.pie.design/assets/img/404_narrow.png',
alt: 'Placeholder Alt',
},
src: 'https://www.pie.design/assets/img/jet-logo-narrow.svg',
alt: 'JET Logo',
src: defaultArgs.src,
alt: defaultArgs.alt,
})();

export const DefaultPropVariations = createVariantStory<ThumbnailProps>(Template, defaultPropOptions);
export const OutlinePropVariations = createVariantStory<ThumbnailProps>(Template, outlinePropOptions);
export const BackgroundPropVariations = createVariantStory<ThumbnailProps>(Template, backgroundPropOptions);
export const aspectRatio4by3PropVariations = createVariantStory<ThumbnailProps>(Template, aspectRatio4by3PropOptions);
export const aspectRatio16by9PropVariations = createVariantStory<ThumbnailProps>(Template, aspectRatio16by9PropOptions);

7 changes: 7 additions & 0 deletions packages/components/pie-thumbnail/src/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export const backgroundColorClassNames: Record<typeof backgroundColors[number],
'inverse-alternative': 'c-thumbnail--backgroundInverseAlternative',
};

export const aspectRatios = ['1by1', '4by3', '16by9'] as const;

const SIZE_INCREMENT_BY = 8;
const SIZE_MIN = 24;
const SIZE_MAX = 128;
Expand Down Expand Up @@ -64,6 +66,10 @@ export interface ThumbnailProps {
* What placeholder should be used when the image fails to load.
*/
placeholder?: PlaceholderProps;
/**
* Sets the aspect-ratio of the thumbnail image.
*/
aspectRatio?: typeof aspectRatios[number];
}

export type DefaultProps = ComponentDefaultProps<ThumbnailProps>;
Expand All @@ -76,6 +82,7 @@ export const defaultProps: DefaultProps = {
disabled: false,
hasPadding: false,
backgroundColor: 'default',
aspectRatio: '1by1',
placeholder: {
src: '',
alt: '',
Expand Down
11 changes: 11 additions & 0 deletions packages/components/pie-thumbnail/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
backgroundColors,
backgroundColorClassNames,
sizes,
aspectRatios,
} from './defs';
import styles from './thumbnail.scss?inline';

Expand All @@ -33,6 +34,10 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
@validPropertyValues(componentSelector, sizes, defaultProps.size)
public size = defaultProps.size;

@property({ type: String })
@validPropertyValues(componentSelector, aspectRatios, defaultProps.aspectRatio)
public aspectRatio = defaultProps.aspectRatio;

@property({ type: String })
public src = defaultProps.src;

Expand All @@ -55,6 +60,10 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
@query('img')
private img!: HTMLImageElement;

/**
* Assigns the thumbnail size and border radius CSS variables
* based on the size prop.
*/
private _generateSizeStyles (): string {
const { size } = this;
let borderRadius = '--dt-radius-rounded-c';
Expand Down Expand Up @@ -103,11 +112,13 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
disabled,
hasPadding,
backgroundColor,
aspectRatio,
} = this;

const wrapperClasses = {
'c-thumbnail': true,
[`c-thumbnail--${variant}`]: true,
[`c-thumbnail--${aspectRatio}`]: true,
[backgroundColorClassNames[backgroundColor]]: true,
'c-thumbnail--disabled': disabled,
'c-thumbnail--padding': hasPadding,
Expand Down
18 changes: 14 additions & 4 deletions packages/components/pie-thumbnail/src/thumbnail.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
--thumbnail-size: 48px;
--thumbnail-border-radius: var(--dt-radius-rounded-b);
--thumbnail-bg-color: var(--dt-color-container-default);
--thumbnail-border-color: transparent;
--thumbnail-padding: calc(var(--dt-spacing-a) / 2);
--thumbnail-img-border-radius: unset;

display: flex;
justify-content: center;
Expand All @@ -13,11 +13,10 @@
width: var(--thumbnail-size);
height: var(--thumbnail-size);
border-radius: var(--thumbnail-border-radius);
border: 1px solid var(--thumbnail-border-color);
background-color: var(--thumbnail-bg-color);

&.c-thumbnail--outline {
--thumbnail-border-color: var(--dt-color-border-default);
border: 1px solid var(--dt-color-border-default);
}

&.c-thumbnail--disabled {
Expand Down Expand Up @@ -45,11 +44,22 @@
}

&.c-thumbnail--padding {
--thumbnail-img-border-radius: calc(var(--thumbnail-border-radius) - var(--thumbnail-padding));
padding: var(--thumbnail-padding);
}

&.c-thumbnail--4by3 {
height: calc(var(--thumbnail-size) * 3 / 4)
}

&.c-thumbnail--16by9 {
height: calc(var(--thumbnail-size) * 9 / 16)
}

.c-thumbnail-img {
width: 100%;
height: auto;
height: 100%;
border-radius: var(--thumbnail-img-border-radius);
object-fit: cover;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ test.describe('PieThumbnail - Component tests', () => {
test('should NOT set placeholder values if a placeholder is provided when an image load does not throw an error', async ({ page }) => {
// Arrange
const expectedValues = {
src: 'https://www.pie.design/assets/img/jet-logo-narrow.svg',
alt: 'JET Logo',
src: './static/images/pie-logo.svg',
alt: 'The PIE design system logo',
};

const pieThumbnailPage = new BasePage(page, 'thumbnail--valid-src-with-placeholder');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,23 @@ test('should render all prop variants for background variants', async ({ page })

await percySnapshot(page, 'PIE Thumbnail - backgroundColor variants', { widths: [1280] });
});

test('should render all prop variations for the 4by3 aspect ratio', async ({ page }) => {
const basePage = new BasePage(page, 'thumbnail--aspect-ratio-4-by-3-prop-variations');
await basePage.load();

const thumbnailComponent = page.getByTestId(thumbnail.selectors.container.dataTestId).first();
await expect.soft(thumbnailComponent).toBeVisible();

await percySnapshot(page, 'PIE Thumbnail - aspectRatio: 4by3', { widths: [1280] });
});

test('should render all prop variations for the 16by9 aspect ratio', async ({ page }) => {
const basePage = new BasePage(page, 'thumbnail--aspect-ratio-16-by-9-prop-variations');
await basePage.load();

const thumbnailComponent = page.getByTestId(thumbnail.selectors.container.dataTestId).first();
await expect.soft(thumbnailComponent).toBeVisible();

await percySnapshot(page, 'PIE Thumbnail - aspectRatio: 16by9', { widths: [1280] });
});

0 comments on commit 1adeb2e

Please sign in to comment.