Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions docs/how-to-guides/customize-content-tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
myst:
html_meta:
"description": "How to hide or replace the tags (subjects) shown below content in Plone Aurora"
"property=og:description": "How to hide or replace the tags (subjects) shown below content in Plone Aurora"
"property=og:title": "Customize the content tags"
"keywords": "Plone Aurora, tags, subjects, slot, belowContent"
---

# Customize the content tags

Plone Aurora renders a content item's tags (its `subjects`) below the content as links to the search.
The tags come from a slot component registered for the `belowContent` slot.
This guide shows you how to hide or replace them.

## Hide the tags

Set `showTags` to `false` in your add-on configuration to hide the tags on every page.

```ts
import type { ConfigType } from '@plone/registry';

export default function install(config: ConfigType) {
config.settings.showTags = false;
return config;
}
```

The slot renders the tags whenever an item has `subjects`, unless `showTags` is `false`.

## Replace the tags component

Register your own component for the `belowContent` slot under the same name to override the default.

```ts
import type { ConfigType } from '@plone/registry';
import MyTags from './MyTags';

export default function install(config: ConfigType) {
config.registerSlotComponent({
name: 'Tags',
slot: 'belowContent',
component: MyTags,
});
return config;
}
```

Your component receives the slot props, including `content`, from which you can read `content.subjects`.
To learn how slots work in general, refer to {doc}`register-slots`.
1 change: 1 addition & 0 deletions docs/how-to-guides/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ icons
configure-plate-code-block-languages
bind-metadata-fields-to-plate-text-blocks
custom-content-types
customize-content-tags
```
8 changes: 8 additions & 0 deletions packages/layout/config/slots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import HeaderTools from '../slots/Tools';
import ContentArea from '../slots/ContentArea';
import MainFooter from '../slots/MainFooter/MainFooter';
import Breadcrumbs from '../slots/Breadcrumbs';
import Tags from '../slots/Tags/Tags';
import { NotContentTypeCondition } from '../helpers';

export default function install(config: ConfigType) {
Expand Down Expand Up @@ -70,6 +71,13 @@ export default function install(config: ConfigType) {
component: ContentArea,
});

// Tags (Subjects)
config.registerSlotComponent({
name: 'Tags',
slot: 'belowContent',
component: Tags,
});

// Footer Slot
config.registerSlotComponent({
name: 'Footer',
Expand Down
3 changes: 3 additions & 0 deletions packages/layout/locales/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"toolbar": {
"label": "Werkzeugleiste"
},
"tags": {
"label": "Schlagwörter"
},
"views": {
"link": {
"linkLabel": "Die Linkadresse lautet:",
Expand Down
3 changes: 3 additions & 0 deletions packages/layout/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"toolbar": {
"label": "Toolbar"
},
"tags": {
"label": "Tags"
},
"views": {
"link": {
"linkLabel": "The link address is:",
Expand Down
3 changes: 3 additions & 0 deletions packages/layout/locales/it/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"toolbar": {
"label": "Barra degli strumenti"
},
"tags": {
"label": "Etichette"
},
"views": {
"link": {
"linkLabel": "L'indirizzo del link è:",
Expand Down
1 change: 1 addition & 0 deletions packages/layout/news/63.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a Tags (Subjects) slot that renders a content item's tags below the content as links to the search. @nils-pzr
21 changes: 21 additions & 0 deletions packages/layout/slots/Tags/Tags.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@layer custom {
.tags {
display: flex;
flex-wrap: wrap;
margin-top: 16px;
gap: 8px;
}

.tag {
padding: 4px 12px;
border-radius: 9999px;
background: var(--quanta-azure);
color: var(--quanta-puya);
font-size: 0.875rem;
text-decoration: none;
}

.tag:hover {
opacity: 0.8;
}
}
32 changes: 32 additions & 0 deletions packages/layout/slots/Tags/Tags.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router';
import Tags from './Tags';

const renderTags = (subjects: string[]) =>
render(
<MemoryRouter>
<Tags
content={{ subjects } as never}
location={{ pathname: '/' } as never}
/>
</MemoryRouter>,
);

describe('Tags slot', () => {
it('renders nothing when there are no tags', () => {
const { container } = renderTags([]);
expect(container).toBeEmptyDOMElement();
});

it('renders a search link for each tag', () => {
renderTags(['News', 'Plone & Co']);
expect(screen.getByRole('link', { name: 'News' })).toHaveAttribute(
'href',
'/search?Subject=News',
);
expect(screen.getByRole('link', { name: 'Plone & Co' })).toHaveAttribute(
'href',
'/search?Subject=Plone%20%26%20Co',
);
});
});
33 changes: 33 additions & 0 deletions packages/layout/slots/Tags/Tags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Link } from 'react-router';
import { useTranslation } from 'react-i18next';
import config from '@plone/registry';
import type { SlotComponentProps } from '../SlotRenderer';
import SectionWrapper from '../../components/SectionWrapper/SectionWrapper';
import styles from './Tags.module.css';

const Tags = (props: SlotComponentProps) => {
const { t } = useTranslation();
const tags = (props.content?.subjects ?? []) as string[];

if (config.settings.showTags === false || tags.length === 0) {
return null;
}

return (
<SectionWrapper as="nav" width="layout" aria-label={t('layout.tags.label')}>
<div className={styles.tags}>
{tags.map((tag) => (
<Link
key={tag}
to={`/search?Subject=${encodeURIComponent(tag)}`}
className={styles.tag}
>
{tag}
</Link>
))}
</div>
</SectionWrapper>
);
};

export default Tags;
Loading