Skip to content

Commit

Permalink
Image rendering (#3337)
Browse files Browse the repository at this point in the history
Co-authored-by: David Glick <david@glicksoftware.com>
Co-authored-by: Steve Piercy <web@stevepiercy.com>
Co-authored-by: Victor Fernandez de Alba <sneridagh@gmail.com>
  • Loading branch information
4 people authored Jul 23, 2023
1 parent 48baf29 commit 262b755
Show file tree
Hide file tree
Showing 69 changed files with 1,209 additions and 535 deletions.
6 changes: 3 additions & 3 deletions cypress/tests/core/basic/objectBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('Object Browser Tests', () => {
// then we should see a image
cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/my-page-1/my-image/@@images/image');
.and('contains', '/my-page-1/my-image/@@images/image');
});

it('As editor I can add the full url in search box in sidebar', () => {
Expand All @@ -74,7 +74,7 @@ describe('Object Browser Tests', () => {
// then we should see a image
cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/my-page-1/my-image/@@images/image');
.and('contains', '/my-page-1/my-image/@@images/image');
});

it('As editor I get focus on search box in sidebar when clicking on lens icon', () => {
Expand Down Expand Up @@ -108,6 +108,6 @@ describe('Object Browser Tests', () => {
// then we should see a image
cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/my-searchable-image/@@images/image');
.and('contains', '/my-searchable-image/@@images/image');
});
});
6 changes: 3 additions & 3 deletions cypress/tests/core/blocks/blocks-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Blocks Tests', () => {
cy.intercept('GET', `/**/*?expand*`).as('content');
cy.intercept('GET', '/**/Document').as('schema');
cy.intercept('POST', '*').as('saveImage');
cy.intercept('GET', '/**/image.png/@@images/image').as('getImage');
cy.intercept('GET', '/**/image.png/@@images/image-*').as('getImage');
// given a logged in editor and a page in edit mode
cy.visit('/');
cy.autologin();
Expand Down Expand Up @@ -117,7 +117,7 @@ describe('Blocks Tests', () => {
// then image src must be equal to image name
cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/my-page/image.png/@@images/image');
.and('contains', '/my-page/image.png/@@images/image-');

cy.get('.block img')
.should('be.visible')
Expand Down Expand Up @@ -146,7 +146,7 @@ describe('Blocks Tests', () => {

cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/image.png/@@images/image');
.and('contains', '/image.png/@@images/image-');

cy.get('.block img')
.should('be.visible')
Expand Down
2 changes: 1 addition & 1 deletion cypress/tests/core/blocks/blocks-listing-templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('Folder Contents Tests', () => {
cy.url().should('eq', Cypress.config().baseUrl + '/my-folder/my-document');
cy.get('.listing-item img')
.should('have.attr', 'src')
.and('contain', '/my-folder/my-document/my-image/@@images/image/preview');
.and('contain', '/my-folder/my-document/my-image/@@images/image-');
cy.get('.listing-item img')
.should('be.visible')
.and(($img) => {
Expand Down
6 changes: 3 additions & 3 deletions cypress/tests/minimal/blocks-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Blocks Tests', () => {
cy.intercept('GET', `/**/*?expand*`).as('content');
cy.intercept('GET', '/**/Document').as('schema');
cy.intercept('POST', '*').as('saveImage');
cy.intercept('GET', '/**/image.png/@@images/image').as('getImage');
cy.intercept('GET', '/**/image.png/@@images/image-*').as('getImage');
// given a logged in editor and a page in edit mode
cy.autologin();
cy.createContent({
Expand Down Expand Up @@ -115,7 +115,7 @@ describe('Blocks Tests', () => {
// then image src must be equal to image name
cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/my-page/image.png/@@images/image');
.and('contains', '/my-page/image.png/@@images/image-');

cy.get('.block img')
.should('be.visible')
Expand Down Expand Up @@ -144,7 +144,7 @@ describe('Blocks Tests', () => {

cy.get('.block img')
.should('have.attr', 'src')
.and('eq', '/image.png/@@images/image');
.and('contains', '/image.png/@@images/image-');

cy.get('.block img')
.should('be.visible')
Expand Down
92 changes: 92 additions & 0 deletions docs/source/recipes/images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
myst:
html_meta:
"description": "Volto code recipe for images"
"property=og:description": "Volto code recipe for images"
"property=og:title": "Volto code recipe for images"
"keywords": "Plone, Volto, code, recipe, images"
---

(images-label)=

# Images

Volto comes with an `Image` component that loads images in an optimal way.

Features of the `Image` component are the following.

- optimized [lazy loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading)
- automatic `srcset` generation, if given a content item or catalog brain
- optional responsive width

The component can accept all the regular HTML `<img>` attributes and a few extra for the above features.
The following example demonstrates how the code with attributes will render to HTML.

```jsx
import config from '@plone/volto/registry';

const Image = config.getComponent({ name: 'Image' }).component;

<Image
src="https://picsum.photos/200/300"
alt="Alt text for accessibility"
className="myClass"
width="200"
height="300"
/>;
```

```html
<img
src="https://picsum.photos/200/300"
alt="Alt text for accessibility"
class="myClass"
width="200"
height="300"
/>
```

Setting the `loading="lazy"` attribute to the `Image` component also adds the `decoding="async"` attribute.
The [`async`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding) attribute decodes the image asynchronously to reduce delay in presenting other content.

To render an image from a content object, you can use the component as shown in the following code snippet.

```jsx
<Image item={content} imageField="image" alt="Alt text for accessibility" />
```

This will generate the `src`, `srcset`, `width`, and `height` attributes automatically for the given image.

To make the image width responsive, you can add the prop `responsive`, and the literal `responsive` will be added to the HTML attribute `class`.

## Serving the right image size

To serve the proper image size for the viewer's device, you should add a `sizes` attribute to the `Image` component while rendering.
This responsibility is left to the developer because it depends on where the image is rendered.

For example, if the image is rendered in a container that is always half as wide as the page, the `sizes` attribute should reflect that to properly inform the browser which image size to request and render.

```jsx
<Image
item={content}
imageField="image"
alt="Alt text for accessibility"
sizes="50vw"
/>
```

If the image is rendered at full viewport width when the viewport is less than `900px` wide, though, you can add a media condition to the `sizes` attribute.

```jsx
<Image
item={content}
imageField="image"
alt="Alt text for accessibility"
sizes="(max-width: 900px) 100vw, 50vw"
/>
```

More information on this subject can be found at the following resources.

- https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
- https://www.builder.io/blog/fast-images
1 change: 1 addition & 0 deletions docs/source/recipes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ environment-variables
customizing-components
customizing-views
creating-views
images
i18n
express
lazyload
Expand Down
12 changes: 12 additions & 0 deletions docs/source/upgrade-guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ If you want to retain the old behavior (and no use `apiExpanders` at all), you n
config.settings.apiExpanders = [];
```

### New Image component

```{versionadded} 17.0.0-alpha.21
A new image component has been added to core to render optimized images.
It requires the latest version of `plone.restapi` (>=8.42.0) installed in the backend to work properly.
```

### Removed Teaser block utils

The `utils.js` file of the Teaser block was removed because it is no longer used.
You can consider removing it if you were shadowing it in your project.

(volto-upgrade-guide-16.x.x)=

## Upgrading to Volto 16.x.x
Expand Down
11 changes: 10 additions & 1 deletion locales/ca/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3330,7 +3330,6 @@ msgid "Sorted"
msgstr ""

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4423,6 +4422,16 @@ msgstr "HTML"
msgid "image"
msgstr "Imatge"

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
11 changes: 10 additions & 1 deletion locales/de/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3327,7 +3327,6 @@ msgid "Sorted"
msgstr "Sortiert"

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4420,6 +4419,16 @@ msgstr "HTML"
msgid "image"
msgstr "Bild"

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
11 changes: 10 additions & 1 deletion locales/en/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3321,7 +3321,6 @@ msgid "Sorted"
msgstr ""

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4414,6 +4413,16 @@ msgstr ""
msgid "image"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
11 changes: 10 additions & 1 deletion locales/es/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3332,7 +3332,6 @@ msgid "Sorted"
msgstr "Ordenado"

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4425,6 +4424,16 @@ msgstr "HTML"
msgid "image"
msgstr "Imagen"

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
11 changes: 10 additions & 1 deletion locales/eu/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3328,7 +3328,6 @@ msgid "Sorted"
msgstr "Ordenatuta"

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4421,6 +4420,16 @@ msgstr "HTML"
msgid "image"
msgstr "Irudia"

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
11 changes: 10 additions & 1 deletion locales/fi/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3332,7 +3332,6 @@ msgid "Sorted"
msgstr "Lajiteltu"

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4425,6 +4424,16 @@ msgstr "HTML"
msgid "image"
msgstr "kuva"

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
11 changes: 10 additions & 1 deletion locales/fr/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -3338,7 +3338,6 @@ msgid "Sorted"
msgstr "Trié"

#: components/manage/Blocks/HTML/Edit
#: components/manage/Blocks/Image/schema
#: components/manage/Controlpanels/Relations/RelationsMatrix
# defaultMessage: Source
msgid "Source"
Expand Down Expand Up @@ -4431,6 +4430,16 @@ msgstr "html"
msgid "image"
msgstr "image"

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Clear image
msgid "image_block_clear"
msgstr ""

#: components/manage/Blocks/Image/ImageSidebar
# defaultMessage: Image preview
msgid "image_block_preview"
msgstr ""

#: helpers/MessageLabels/MessageLabels
# defaultMessage: Input must be integer
msgid "integer"
Expand Down
Loading

0 comments on commit 262b755

Please sign in to comment.