diff --git a/docs/source/configuration/settings-reference.md b/docs/source/configuration/settings-reference.md
index 0f156cf8a9..b8601cffef 100644
--- a/docs/source/configuration/settings-reference.md
+++ b/docs/source/configuration/settings-reference.md
@@ -464,12 +464,22 @@ querystringSearchGet
Please test this setting properly before enabling in a production site.
cssLayers
- To use CSS layers when styling Volto, you can define and apply them at the very top level of the page, where they appear in the `
` tag.
+ To use CSS layers when styling Volto, you can define and apply them at the very top level of the page, where they appear in the `` tag.
By using this configuration, you can pass the layer list definition as an array:
```js
config.settings.cssLayers = ['reset', 'plone-components', 'layout', 'addons', 'theme'];
```
+
+showRelatedItems
+ If true, the `RelatedItems` component will show items from the `relatedItems` field. Default: false.
+
+ ```{versionadded} 18.5.0
+ ```
+
+
+showTags
+ If true, the `Tags` component will show tags from the `subjects` field. Default: true.
```
## Views settings
diff --git a/packages/types/src/config/Settings.d.ts b/packages/types/src/config/Settings.d.ts
index 61e87a8955..2053fde0f5 100644
--- a/packages/types/src/config/Settings.d.ts
+++ b/packages/types/src/config/Settings.d.ts
@@ -76,6 +76,7 @@ export interface SettingsConfig {
serverConfig: unknown;
storeExtenders: unknown[];
showTags: boolean;
+ showRelatedItems: boolean;
controlpanels: unknown[];
controlPanelsIcons: Record;
filterControlPanels: unknown;
diff --git a/packages/volto/locales/ca/LC_MESSAGES/volto.po b/packages/volto/locales/ca/LC_MESSAGES/volto.po
index f004a71968..3e7b0dfe67 100644
--- a/packages/volto/locales/ca/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/ca/LC_MESSAGES/volto.po
@@ -2872,6 +2872,11 @@ msgstr "Registrar-se"
msgid "Registration form"
msgstr "Formulari d'inscripció"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/de/LC_MESSAGES/volto.po b/packages/volto/locales/de/LC_MESSAGES/volto.po
index 688a7886f2..043109a013 100644
--- a/packages/volto/locales/de/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/de/LC_MESSAGES/volto.po
@@ -2871,6 +2871,11 @@ msgstr "Registrieren"
msgid "Registration form"
msgstr "Registrierungsformular"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/en/LC_MESSAGES/volto.po b/packages/volto/locales/en/LC_MESSAGES/volto.po
index 3ed645594c..9ad7a604aa 100644
--- a/packages/volto/locales/en/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/en/LC_MESSAGES/volto.po
@@ -2866,6 +2866,11 @@ msgstr ""
msgid "Registration form"
msgstr ""
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/es/LC_MESSAGES/volto.po b/packages/volto/locales/es/LC_MESSAGES/volto.po
index 095307a2a0..ff5b8c2299 100644
--- a/packages/volto/locales/es/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/es/LC_MESSAGES/volto.po
@@ -2873,6 +2873,11 @@ msgstr "Registro"
msgid "Registration form"
msgstr "Formulario de registro"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/eu/LC_MESSAGES/volto.po b/packages/volto/locales/eu/LC_MESSAGES/volto.po
index a67988bc0c..aa260e34fa 100644
--- a/packages/volto/locales/eu/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/eu/LC_MESSAGES/volto.po
@@ -2873,6 +2873,11 @@ msgstr "Izena eman"
msgid "Registration form"
msgstr "Erregistro formularioa"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/fi/LC_MESSAGES/volto.po b/packages/volto/locales/fi/LC_MESSAGES/volto.po
index 595f3076a2..99c1f6ff04 100644
--- a/packages/volto/locales/fi/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/fi/LC_MESSAGES/volto.po
@@ -2871,6 +2871,11 @@ msgstr "Rekisteröidy"
msgid "Registration form"
msgstr "Rekisteröitymislomake"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/fr/LC_MESSAGES/volto.po b/packages/volto/locales/fr/LC_MESSAGES/volto.po
index ebc33cfdec..120eda4ebe 100644
--- a/packages/volto/locales/fr/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/fr/LC_MESSAGES/volto.po
@@ -2873,6 +2873,11 @@ msgstr "S'enregistrer"
msgid "Registration form"
msgstr "Formulaire d'enregistrement"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/hi/LC_MESSAGES/volto.po b/packages/volto/locales/hi/LC_MESSAGES/volto.po
index 3a381829f0..0219651642 100644
--- a/packages/volto/locales/hi/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/hi/LC_MESSAGES/volto.po
@@ -2866,6 +2866,11 @@ msgstr "रजिस्टर करें"
msgid "Registration form"
msgstr "रजिस्ट्रेशन फ़ॉर्म"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/it/LC_MESSAGES/volto.po b/packages/volto/locales/it/LC_MESSAGES/volto.po
index d5ae249f68..6cccb3d46b 100644
--- a/packages/volto/locales/it/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/it/LC_MESSAGES/volto.po
@@ -2866,6 +2866,11 @@ msgstr "Registrati"
msgid "Registration form"
msgstr "Form di iscrizione"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/ja/LC_MESSAGES/volto.po b/packages/volto/locales/ja/LC_MESSAGES/volto.po
index 6d51320e2d..e4c74c3188 100644
--- a/packages/volto/locales/ja/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/ja/LC_MESSAGES/volto.po
@@ -2871,6 +2871,11 @@ msgstr "登録"
msgid "Registration form"
msgstr "登録フォーム"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/nl/LC_MESSAGES/volto.po b/packages/volto/locales/nl/LC_MESSAGES/volto.po
index 2b038800b5..281135a55c 100644
--- a/packages/volto/locales/nl/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/nl/LC_MESSAGES/volto.po
@@ -2870,6 +2870,11 @@ msgstr "Registreer"
msgid "Registration form"
msgstr "Registratie formulier"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/pt/LC_MESSAGES/volto.po b/packages/volto/locales/pt/LC_MESSAGES/volto.po
index 61736fb8a3..8f4040495a 100644
--- a/packages/volto/locales/pt/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/pt/LC_MESSAGES/volto.po
@@ -2871,6 +2871,11 @@ msgstr "Registar"
msgid "Registration form"
msgstr "Formulário de registo"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/pt_BR/LC_MESSAGES/volto.po b/packages/volto/locales/pt_BR/LC_MESSAGES/volto.po
index aa504377c5..76a25c310c 100644
--- a/packages/volto/locales/pt_BR/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/pt_BR/LC_MESSAGES/volto.po
@@ -2872,6 +2872,11 @@ msgstr "Cadastro"
msgid "Registration form"
msgstr "Formulário de cadastro"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr "Itens relacionados"
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/ro/LC_MESSAGES/volto.po b/packages/volto/locales/ro/LC_MESSAGES/volto.po
index 58314bb461..9199570724 100644
--- a/packages/volto/locales/ro/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/ro/LC_MESSAGES/volto.po
@@ -2872,6 +2872,11 @@ msgstr "Înregistrare"
msgid "Registration form"
msgstr "Formular de înregistrare"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/volto.pot b/packages/volto/locales/volto.pot
index ba45f0fa1c..18436bc9bf 100644
--- a/packages/volto/locales/volto.pot
+++ b/packages/volto/locales/volto.pot
@@ -2868,6 +2868,11 @@ msgstr ""
msgid "Registration form"
msgstr ""
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/locales/zh_CN/LC_MESSAGES/volto.po b/packages/volto/locales/zh_CN/LC_MESSAGES/volto.po
index 0b08345f61..8b3aa94303 100644
--- a/packages/volto/locales/zh_CN/LC_MESSAGES/volto.po
+++ b/packages/volto/locales/zh_CN/LC_MESSAGES/volto.po
@@ -2872,6 +2872,11 @@ msgstr "注册"
msgid "Registration form"
msgstr "注册表单"
+#. Default: "Related Items"
+#: components/theme/RelatedItems/RelatedItems
+msgid "Related Items"
+msgstr ""
+
#. Default: "Relation"
#: components/manage/Controlpanels/Relations/RelationsMatrix
#: helpers/MessageLabels/MessageLabels
diff --git a/packages/volto/news/3740.feature b/packages/volto/news/3740.feature
new file mode 100644
index 0000000000..ed0c1b9313
--- /dev/null
+++ b/packages/volto/news/3740.feature
@@ -0,0 +1 @@
+Add component to show related items, which can be enabled using the `showRelatedItems` setting. @wesleybl
diff --git a/packages/volto/src/components/theme/RelatedItems/RelatedItems.jsx b/packages/volto/src/components/theme/RelatedItems/RelatedItems.jsx
new file mode 100644
index 0000000000..e0e121c377
--- /dev/null
+++ b/packages/volto/src/components/theme/RelatedItems/RelatedItems.jsx
@@ -0,0 +1,70 @@
+/**
+ * RelatedItems component.
+ * @module components/theme/RelatedItems/RelatedItems
+ */
+
+import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
+import { defineMessages, useIntl } from 'react-intl';
+import PropTypes from 'prop-types';
+import { Container } from 'semantic-ui-react';
+import config from '@plone/volto/registry';
+
+const messages = defineMessages({
+ relatedItems: {
+ id: 'Related Items',
+ defaultMessage: 'Related Items',
+ },
+});
+
+/**
+ * Related Items component.
+ * @function RelatedItems
+ * @param {array} relatedItems Array of related items.
+ * @returns {JSX.Element} Markup of the component.
+ */
+const RelatedItems = ({ content }) => {
+ const intl = useIntl();
+ const relatedItems = content?.relatedItems;
+ if (
+ !config.settings.showRelatedItems ||
+ !relatedItems ||
+ relatedItems.length === 0
+ ) {
+ return null;
+ }
+
+ return (
+
+ {intl.formatMessage(messages.relatedItems)}
+
+ {relatedItems.map((relatedItem) =>
+ relatedItem ? (
+ -
+
+ {relatedItem.title}
+
+
+ ) : null,
+ )}
+
+
+ );
+};
+
+/**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+RelatedItems.propTypes = {
+ content: PropTypes.shape({
+ relatedItems: PropTypes.arrayOf(
+ PropTypes.shape({
+ '@id': PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ }),
+ ),
+ }),
+};
+
+export default RelatedItems;
diff --git a/packages/volto/src/components/theme/RelatedItems/RelatedItems.test.jsx b/packages/volto/src/components/theme/RelatedItems/RelatedItems.test.jsx
new file mode 100644
index 0000000000..42647e24e2
--- /dev/null
+++ b/packages/volto/src/components/theme/RelatedItems/RelatedItems.test.jsx
@@ -0,0 +1,83 @@
+import renderer from 'react-test-renderer';
+import configureStore from 'redux-mock-store';
+import { Provider } from 'react-intl-redux';
+import { MemoryRouter } from 'react-router-dom';
+
+import RelatedItems from './RelatedItems';
+
+const mockStore = configureStore();
+let store;
+
+describe('Related Items', () => {
+ beforeEach(() => {
+ store = mockStore({
+ intl: {
+ locale: 'en',
+ messages: {},
+ },
+ });
+ });
+
+ it('renders without related items', () => {
+ const content = {};
+ const component = renderer.create(
+
+
+
+
+ ,
+ );
+ const json = component.toJSON();
+ expect(json).toMatchSnapshot();
+ });
+
+ it('renders with related items', () => {
+ const content = {
+ relatedItems: [
+ {
+ '@id': '/test-1',
+ title: 'Title 1',
+ description: 'Description 1',
+ },
+ {
+ '@id': '/test-2',
+ title: 'Title 2',
+ description: 'Description 2',
+ },
+ ],
+ };
+
+ const component = renderer.create(
+
+
+
+
+ ,
+ );
+ const json = component.toJSON();
+ expect(json).toMatchSnapshot();
+ });
+
+ it('renders with related items has null', () => {
+ const content = {
+ relatedItems: [
+ {
+ '@id': '/test-1',
+ title: 'Title 1',
+ description: 'Description 1',
+ },
+ null,
+ ],
+ };
+
+ const component = renderer.create(
+
+
+
+
+ ,
+ );
+ const json = component.toJSON();
+ expect(json).toMatchSnapshot();
+ });
+});
diff --git a/packages/volto/src/components/theme/RelatedItems/__snapshots__/RelatedItems.test.jsx.snap b/packages/volto/src/components/theme/RelatedItems/__snapshots__/RelatedItems.test.jsx.snap
new file mode 100644
index 0000000000..1eef151979
--- /dev/null
+++ b/packages/volto/src/components/theme/RelatedItems/__snapshots__/RelatedItems.test.jsx.snap
@@ -0,0 +1,60 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Related Items renders with related items 1`] = `
+
+`;
+
+exports[`Related Items renders with related items has null 1`] = `
+
+`;
+
+exports[`Related Items renders without related items 1`] = `null`;
diff --git a/packages/volto/src/config/index.js b/packages/volto/src/config/index.js
index 48ab6e0159..0c8f57d0b6 100644
--- a/packages/volto/src/config/index.js
+++ b/packages/volto/src/config/index.js
@@ -141,6 +141,7 @@ let config = {
serverConfig,
storeExtenders: [],
showTags: true,
+ showRelatedItems: false,
controlpanels: [],
controlPanelsIcons,
filterControlPanels,
diff --git a/packages/volto/src/config/slots.js b/packages/volto/src/config/slots.js
index 008bada7e2..265b3573ce 100644
--- a/packages/volto/src/config/slots.js
+++ b/packages/volto/src/config/slots.js
@@ -1,3 +1,4 @@
+import RelatedItems from '@plone/volto/components/theme/RelatedItems/RelatedItems';
import Tags from '@plone/volto/components/theme/Tags/Tags';
const slots = {
@@ -6,6 +7,10 @@ const slots = {
name: 'tags',
component: Tags,
},
+ {
+ name: 'relatedItems',
+ component: RelatedItems,
+ },
],
};
diff --git a/packages/volto/test-setup-config.jsx b/packages/volto/test-setup-config.jsx
index 890205193a..4662306123 100644
--- a/packages/volto/test-setup-config.jsx
+++ b/packages/volto/test-setup-config.jsx
@@ -34,6 +34,7 @@ config.set('settings', {
supportedLanguages: ['en'],
defaultPageSize: 25,
showTags: true,
+ showRelatedItems: true,
isMultilingual: false,
nonContentRoutes,
nonContentRoutesPublic,
diff --git a/packages/volto/theme/themes/pastanaga/extras/main.less b/packages/volto/theme/themes/pastanaga/extras/main.less
index 1062b14845..d373cfb3c1 100644
--- a/packages/volto/theme/themes/pastanaga/extras/main.less
+++ b/packages/volto/theme/themes/pastanaga/extras/main.less
@@ -651,6 +651,11 @@ img.responsive {
height: auto;
}
+// Related Items
+.related-items {
+ margin-top: 20px;
+}
+
// Deprecated as per https://github.com/plone/volto/issues/1265
// @import 'utils';
@import (multiple) '../extras/fonts';