@kitconcept/volto-light-theme 8.0.0-alpha.18 → 8.0.0-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/.changelog.draft +8 -7
  2. package/CHANGELOG.md +14 -0
  3. package/package.json +1 -1
  4. package/src/components/Blocks/EventCalendar/Search/components/EventTemplate.tsx +1 -1
  5. package/src/components/Blocks/Listing/DefaultTemplate.jsx +5 -5
  6. package/src/components/Blocks/Listing/GridTemplate.jsx +9 -6
  7. package/src/components/Blocks/Listing/ListingBody.jsx +1 -1
  8. package/src/components/Blocks/Listing/SummaryTemplate.jsx +9 -6
  9. package/src/components/Blocks/Teaser/DefaultBody.tsx +0 -1
  10. package/src/components/Summary/DefaultSummary.tsx +10 -3
  11. package/src/components/Summary/EventSummary.tsx +10 -3
  12. package/src/components/Summary/FileSummary.tsx +10 -3
  13. package/src/components/Summary/NewsItemSummary.tsx +10 -3
  14. package/src/components/Summary/PersonSummary.tsx +10 -3
  15. package/src/components/Summary/Summary.stories.tsx +46 -30
  16. package/src/primitives/Card/Card.stories.tsx +4 -1
  17. package/src/primitives/Card/Card.test.tsx +11 -33
  18. package/src/primitives/Card/Card.tsx +33 -49
  19. package/src/theme/_bgcolor-blocks-layout.scss +27 -41
  20. package/src/theme/_footer.scss +27 -1
  21. package/src/theme/_header.scss +13 -1
  22. package/src/theme/_layout.scss +6 -10
  23. package/src/theme/_typo-custom.scss +4 -5
  24. package/src/theme/_variables.scss +10 -5
  25. package/src/theme/blocks/_accordion.scss +10 -4
  26. package/src/theme/blocks/_grid.scss +0 -78
  27. package/src/theme/blocks/_listing.scss +54 -130
  28. package/src/theme/blocks/_search.scss +3 -4
  29. package/src/theme/blocks/_table.scss +1 -0
  30. package/src/theme/blocks/_teaser.scss +7 -119
  31. package/src/theme/card.scss +107 -70
  32. package/src/theme/person.scss +7 -1
package/.changelog.draft CHANGED
@@ -1,14 +1,15 @@
1
- ## 8.0.0-alpha.18 (2026-03-14)
1
+ ## 8.0.0-alpha.19 (2026-04-17)
2
2
 
3
- ### Feature
3
+ ### Breaking
4
4
 
5
- - Improve layout for full-width blocks when in Edit mode. @danalvrz
5
+ - Improve Card component link handling by using a CSS stretched-link pattern & other minor style fixes for consistency. Breaking: custom `Summary` components must now accept and use the `LinkToItem` prop; category labels changed from heading tags to `<ul>` elements. See the upgrade guide for migration steps. @danalvrz
6
6
 
7
7
  ### Bugfix
8
8
 
9
- - Fix font size for control panel view headers. @danalvrz [#fixControlPanelFontSize](https://github.com/kitconcept/volto-light-theme/pull/fixControlPanelFontSize)
10
- - Fix css of External link icon indicator for teaser and grid-teaser @iRohitSingh [#797](https://github.com/kitconcept/volto-light-theme/pull/797)
11
- - Fix undefined error when pressing enter in footer site colophon input. @iFlameing
12
- - Improve styles for Export Import control panel & several color fixes. @danalvrz
9
+ - Fixed the font-color in the table block with h2 or h3 font-size. @TimoBroeskamp [#820](https://github.com/kitconcept/volto-light-theme/pull/820)
10
+ - + display footer links with an underline, remove gap between seperate lines in footer colophon text and fixed richtext-editor combinations to work together. @TimoBroeskamp
11
+ - Fix navigation text color not loading on hard reload. @iFlameing
12
+ - Fix spacings for navigation items when using the Intranet header. @danlavrz
13
+ - Fix styles for text in colophon. @danalvrz
13
14
 
14
15
 
package/CHANGELOG.md CHANGED
@@ -8,6 +8,20 @@
8
8
 
9
9
  <!-- towncrier release notes start -->
10
10
 
11
+ ## 8.0.0-alpha.19 (2026-04-17)
12
+
13
+ ### Breaking
14
+
15
+ - Improve Card component link handling by using a CSS stretched-link pattern & other minor style fixes for consistency. Breaking: custom `Summary` components must now accept and use the `LinkToItem` prop; category labels changed from heading tags to `<ul>` elements. See the upgrade guide for migration steps. @danalvrz
16
+
17
+ ### Bugfix
18
+
19
+ - Fixed the font-color in the table block with h2 or h3 font-size. @TimoBroeskamp [#820](https://github.com/kitconcept/volto-light-theme/pull/820)
20
+ - + display footer links with an underline, remove gap between seperate lines in footer colophon text and fixed richtext-editor combinations to work together. @TimoBroeskamp
21
+ - Fix navigation text color not loading on hard reload. @iFlameing
22
+ - Fix spacings for navigation items when using the Intranet header. @danlavrz
23
+ - Fix styles for text in colophon. @danalvrz
24
+
11
25
  ## 8.0.0-alpha.18 (2026-03-14)
12
26
 
13
27
  ### Feature
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitconcept/volto-light-theme",
3
- "version": "8.0.0-alpha.18",
3
+ "version": "8.0.0-alpha.19",
4
4
  "description": "Volto Light Theme by kitconcept",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -49,7 +49,7 @@ const EventItem = ({ item, lang, isEditMode }) => {
49
49
  <span className="event-title">{item.head_title}</span>
50
50
  )}
51
51
  </div>
52
- <DefaultSummary item={item} HeadingTag="h2" />
52
+ <DefaultSummary item={item} />
53
53
  </Card.Summary>
54
54
  </Card>
55
55
  </div>
@@ -27,7 +27,7 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
27
27
 
28
28
  return (
29
29
  <>
30
- <div className="items">
30
+ <ul className="items">
31
31
  {items.map((item) => {
32
32
  const Summary =
33
33
  config.getComponent({
@@ -39,7 +39,7 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
39
39
  showLink = !hideProfileLinks && !isEditMode;
40
40
  }
41
41
  return (
42
- <div
42
+ <li
43
43
  className={cx('listing-item', {
44
44
  [`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
45
45
  })}
@@ -47,13 +47,13 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
47
47
  >
48
48
  <Card item={showLink ? item : null}>
49
49
  <Card.Summary>
50
- <Summary item={item} HeadingTag="h2" />
50
+ <Summary item={item} />
51
51
  </Card.Summary>
52
52
  </Card>
53
- </div>
53
+ </li>
54
54
  );
55
55
  })}
56
- </div>
56
+ </ul>
57
57
 
58
58
  {link && <div className="footer">{link}</div>}
59
59
  </>
@@ -27,7 +27,7 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
27
27
 
28
28
  return (
29
29
  <>
30
- <div className="items">
30
+ <ul className="items">
31
31
  {items.map((item) => {
32
32
  const CustomItemBodyTemplate = config.getComponent({
33
33
  name: 'GridListingItemTemplate',
@@ -55,14 +55,17 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
55
55
  imageComponent={PreviewImageComponent}
56
56
  />
57
57
  )}
58
- <Card.Summary a11yLabelId={props.a11yLabelId}>
59
- <Summary item={item} HeadingTag="h2" />
58
+ <Card.Summary
59
+ a11yLabelId={props.a11yLabelId}
60
+ LinkToItem={props.LinkToItem}
61
+ >
62
+ <Summary item={item} />
60
63
  </Card.Summary>
61
64
  </>
62
65
  );
63
66
 
64
67
  return (
65
- <div
68
+ <li
66
69
  className={cx('listing-item', {
67
70
  [`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
68
71
  })}
@@ -71,10 +74,10 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
71
74
  <Card item={showLink ? item : null}>
72
75
  <ItemBodyTemplate item={item} />
73
76
  </Card>
74
- </div>
77
+ </li>
75
78
  );
76
79
  })}
77
- </div>
80
+ </ul>
78
81
 
79
82
  {link && <div className="footer">{link}</div>}
80
83
  </>
@@ -39,7 +39,7 @@ const Headline = ({
39
39
  mode={!isEditMode && 'view'}
40
40
  children={data.headline}
41
41
  attributes={attr}
42
- className={cx('headline', {
42
+ className={cx('headline block-title', {
43
43
  emptyListing: !listingItems?.length > 0,
44
44
  })}
45
45
  style={style}
@@ -26,7 +26,7 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
26
26
 
27
27
  return (
28
28
  <>
29
- <div className="items">
29
+ <ul className="items">
30
30
  {items.map((item) => {
31
31
  const CustomItemBodyTemplate = config.getComponent({
32
32
  name: 'SummaryListingItemTemplate',
@@ -51,13 +51,16 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
51
51
  showPlaceholderImage={true}
52
52
  imageComponent={PreviewImageComponent}
53
53
  />
54
- <Card.Summary a11yLabelId={props.a11yLabelId}>
55
- <Summary item={item} HeadingTag="h3" />
54
+ <Card.Summary
55
+ a11yLabelId={props.a11yLabelId}
56
+ LinkToItem={props.LinkToItem}
57
+ >
58
+ <Summary item={item} />
56
59
  </Card.Summary>
57
60
  </>
58
61
  );
59
62
  return (
60
- <div
63
+ <li
61
64
  className={cx('listing-item has--align--left', {
62
65
  [`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
63
66
  })}
@@ -66,10 +69,10 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
66
69
  <Card item={showLink ? item : null}>
67
70
  <ItemBodyTemplate item={item} />
68
71
  </Card>
69
- </div>
72
+ </li>
70
73
  );
71
74
  })}
72
- </div>
75
+ </ul>
73
76
 
74
77
  {link && <div className="footer">{link}</div>}
75
78
  </>
@@ -54,7 +54,6 @@ const TeaserDefaultTemplate = (props) => {
54
54
  <Card.Summary>
55
55
  <Summary
56
56
  item={!data.overwrite ? href : { ...href, ...localOverrides }}
57
- HeadingTag="h2"
58
57
  hide_description={props.data?.hide_description}
59
58
  />
60
59
  </Card.Summary>
@@ -4,6 +4,7 @@ import { smartTextRenderer } from '../../helpers/smartText';
4
4
 
5
5
  export type DefaultSummaryProps = {
6
6
  item: Partial<ObjectBrowserItem>;
7
+ LinkToItem?: React.ElementType;
7
8
  HeadingTag?: React.ElementType;
8
9
  a11yLabelId?: string;
9
10
  hide_description?: boolean;
@@ -14,14 +15,20 @@ export type SummaryComponentType = React.ComponentType<DefaultSummaryProps> & {
14
15
  };
15
16
 
16
17
  const DefaultSummary = (props: DefaultSummaryProps) => {
17
- const { item, HeadingTag = 'h3', a11yLabelId, hide_description } = props;
18
+ const {
19
+ item,
20
+ LinkToItem = React.Fragment,
21
+ HeadingTag = 'div',
22
+ a11yLabelId,
23
+ hide_description,
24
+ } = props;
18
25
  return (
19
26
  <>
20
27
  {item?.head_title && <div className="headline">{item.head_title}</div>}
21
28
  <HeadingTag className="title" id={a11yLabelId}>
22
- {item.title ? item.title : item.id}
29
+ <LinkToItem>{item.title ? item.title : item.id}</LinkToItem>
23
30
  </HeadingTag>
24
- {!hide_description && (
31
+ {!hide_description && item?.description !== '' && (
25
32
  <p className="description">{smartTextRenderer(item.description)}</p>
26
33
  )}
27
34
  </>
@@ -1,3 +1,4 @@
1
+ import * as React from 'react';
1
2
  import {
2
3
  parseDateFromCatalog,
3
4
  formatDateRange,
@@ -7,7 +8,13 @@ import type { DefaultSummaryProps } from './DefaultSummary';
7
8
  import { smartTextRenderer } from '../../helpers/smartText';
8
9
 
9
10
  const EventSummary = (props: DefaultSummaryProps) => {
10
- const { item, HeadingTag = 'h3', a11yLabelId, hide_description } = props;
11
+ const {
12
+ item,
13
+ LinkToItem = React.Fragment,
14
+ HeadingTag = 'div',
15
+ a11yLabelId,
16
+ hide_description,
17
+ } = props;
11
18
  const start = parseDateFromCatalog(item.start);
12
19
  const end = parseDateFromCatalog(item.end);
13
20
  const headline = [
@@ -29,9 +36,9 @@ const EventSummary = (props: DefaultSummaryProps) => {
29
36
  <>
30
37
  {headline.length ? <div className="headline">{headline}</div> : null}
31
38
  <HeadingTag className="title" id={a11yLabelId}>
32
- {item.title ? item.title : item.id}
39
+ <LinkToItem>{item.title ? item.title : item.id}</LinkToItem>
33
40
  </HeadingTag>
34
- {!hide_description && (
41
+ {!hide_description && item?.description !== '' && (
35
42
  <p className="description">{smartTextRenderer(item.description)}</p>
36
43
  )}
37
44
  </>
@@ -1,3 +1,4 @@
1
+ import * as React from 'react';
1
2
  import FileType from '@kitconcept/volto-light-theme/helpers/Filetype';
2
3
  import type { DefaultSummaryProps } from './DefaultSummary';
3
4
  import { smartTextRenderer } from '../../helpers/smartText';
@@ -21,15 +22,21 @@ const FileHeadline = (props: { item: any }) => {
21
22
  };
22
23
 
23
24
  const FileSummary = (props: DefaultSummaryProps) => {
24
- const { item, HeadingTag = 'h3', a11yLabelId, hide_description } = props;
25
+ const {
26
+ item,
27
+ LinkToItem = React.Fragment,
28
+ HeadingTag = 'div',
29
+ a11yLabelId,
30
+ hide_description,
31
+ } = props;
25
32
 
26
33
  return (
27
34
  <>
28
35
  <FileHeadline item={item} />
29
36
  <HeadingTag className="title" id={a11yLabelId}>
30
- {item.title ? item.title : item.id}
37
+ <LinkToItem>{item.title ? item.title : item.id}</LinkToItem>
31
38
  </HeadingTag>
32
- {!hide_description && (
39
+ {!hide_description && item?.description !== '' && (
33
40
  <p className="description">{smartTextRenderer(item.description)}</p>
34
41
  )}
35
42
  </>
@@ -1,10 +1,17 @@
1
+ import * as React from 'react';
1
2
  import { parseDateFromCatalog } from '@kitconcept/volto-light-theme/helpers/dates';
2
3
  import FormattedDate from '@plone/volto/components/theme/FormattedDate/FormattedDate';
3
4
  import type { DefaultSummaryProps } from './DefaultSummary';
4
5
  import { smartTextRenderer } from '../../helpers/smartText';
5
6
 
6
7
  const NewsItemSummary = (props: DefaultSummaryProps) => {
7
- const { item, HeadingTag = 'h3', a11yLabelId, hide_description } = props;
8
+ const {
9
+ item,
10
+ LinkToItem = React.Fragment,
11
+ HeadingTag = 'div',
12
+ a11yLabelId,
13
+ hide_description,
14
+ } = props;
8
15
 
9
16
  const effective = parseDateFromCatalog(item.effective);
10
17
  const headline = [
@@ -31,9 +38,9 @@ const NewsItemSummary = (props: DefaultSummaryProps) => {
31
38
  <>
32
39
  {headline.length ? <div className="headline">{headline}</div> : null}
33
40
  <HeadingTag className="title" id={a11yLabelId}>
34
- {item.title ? item.title : item.id}
41
+ <LinkToItem>{item.title ? item.title : item.id}</LinkToItem>
35
42
  </HeadingTag>
36
- {!hide_description && (
43
+ {!hide_description && item?.description !== '' && (
37
44
  <p className="description">{smartTextRenderer(item.description)}</p>
38
45
  )}
39
46
  </>
@@ -1,3 +1,4 @@
1
+ import * as React from 'react';
1
2
  import Icon from '@plone/volto/components/theme/Icon/Icon';
2
3
  import mailSVG from '@plone/volto/icons/email.svg';
3
4
  import locationSVG from '@plone/volto/icons/map.svg';
@@ -22,16 +23,22 @@ const messages = defineMessages({
22
23
  });
23
24
 
24
25
  const PersonSummary = (props: DefaultSummaryProps) => {
25
- const { item, HeadingTag = 'h3', a11yLabelId, hide_description } = props;
26
+ const {
27
+ item,
28
+ LinkToItem = React.Fragment,
29
+ HeadingTag = 'div',
30
+ a11yLabelId,
31
+ hide_description,
32
+ } = props;
26
33
  const intl = useIntl();
27
34
 
28
35
  return (
29
36
  <>
30
37
  {item?.head_title && <div className="headline">{item.head_title}</div>}
31
38
  <HeadingTag className="title" id={a11yLabelId}>
32
- {item.title ? item.title : item.id}
39
+ <LinkToItem>{item.title ? item.title : item.id}</LinkToItem>
33
40
  </HeadingTag>
34
- {!hide_description && (
41
+ {!hide_description && item?.description !== '' && (
35
42
  <p className="description">{smartTextRenderer(item.description)}</p>
36
43
  )}
37
44
 
@@ -22,15 +22,17 @@ type Story = StoryObj<typeof meta>;
22
22
 
23
23
  export const Summary: Story = {
24
24
  render: (args) => (
25
- <div style={{ width: '300px' }}>
26
- <Wrapper>
27
- <DefaultSummary {...args} />
28
- </Wrapper>
25
+ <div className="card" style={{ width: '300px' }}>
26
+ <div className="card-summary">
27
+ <Wrapper>
28
+ <DefaultSummary {...args} />
29
+ </Wrapper>
30
+ </div>
29
31
  </div>
30
32
  ),
31
33
  args: {
32
34
  item: {
33
- title: 'Simple Card with strings',
35
+ title: 'Summary',
34
36
  description:
35
37
  'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea.',
36
38
  head_title: 'Simple Card',
@@ -40,15 +42,17 @@ export const Summary: Story = {
40
42
 
41
43
  export const SummaryWithLink: Story = {
42
44
  render: (args) => (
43
- <div style={{ width: '300px' }}>
44
- <Wrapper>
45
- <DefaultSummary {...args} />
46
- </Wrapper>
45
+ <div className="card" style={{ width: '300px' }}>
46
+ <div className="card-summary">
47
+ <Wrapper>
48
+ <DefaultSummary {...args} />
49
+ </Wrapper>
50
+ </div>
47
51
  </div>
48
52
  ),
49
53
  args: {
50
54
  item: {
51
- title: 'Simple Card with strings',
55
+ title: 'Summary',
52
56
  description:
53
57
  '[Lorem ipsum](https://example.com) dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea.',
54
58
  head_title: 'Simple Card',
@@ -58,15 +62,17 @@ export const SummaryWithLink: Story = {
58
62
 
59
63
  export const SummaryHideDescription: Story = {
60
64
  render: (args) => (
61
- <div style={{ width: '300px' }}>
62
- <Wrapper>
63
- <DefaultSummary {...args} />
64
- </Wrapper>
65
+ <div className="card" style={{ width: '300px' }}>
66
+ <div className="card-summary">
67
+ <Wrapper>
68
+ <DefaultSummary {...args} />
69
+ </Wrapper>
70
+ </div>
65
71
  </div>
66
72
  ),
67
73
  args: {
68
74
  item: {
69
- title: 'Simple Card with strings',
75
+ title: 'Summary',
70
76
  description:
71
77
  'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea.',
72
78
  head_title: 'Simple Card',
@@ -77,15 +83,17 @@ export const SummaryHideDescription: Story = {
77
83
 
78
84
  export const NewsItemSummary: Story = {
79
85
  render: (args) => (
80
- <div style={{ width: '300px' }}>
81
- <Wrapper>
82
- <NewsItemSummaryComponent {...args} />
83
- </Wrapper>
86
+ <div className="card" style={{ width: '300px' }}>
87
+ <div className="card-summary">
88
+ <Wrapper>
89
+ <NewsItemSummaryComponent {...args} />
90
+ </Wrapper>
91
+ </div>
84
92
  </div>
85
93
  ),
86
94
  args: {
87
95
  item: {
88
- title: 'Simple Card with strings',
96
+ title: 'Summary',
89
97
  description:
90
98
  'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea.',
91
99
  head_title: 'Simple Card',
@@ -98,15 +106,17 @@ export const NewsItemSummary: Story = {
98
106
 
99
107
  export const EventSummary: Story = {
100
108
  render: (args) => (
101
- <div style={{ width: '300px' }}>
102
- <Wrapper>
103
- <EventSummaryComponent {...args} />
104
- </Wrapper>
109
+ <div className="card" style={{ width: '300px' }}>
110
+ <div className="card-summary">
111
+ <Wrapper>
112
+ <EventSummaryComponent {...args} />
113
+ </Wrapper>
114
+ </div>
105
115
  </div>
106
116
  ),
107
117
  args: {
108
118
  item: {
109
- title: 'Simple Card with strings',
119
+ title: 'Summary',
110
120
  description:
111
121
  'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea.',
112
122
  head_title: 'Simple Card',
@@ -119,17 +129,23 @@ export const EventSummary: Story = {
119
129
 
120
130
  export const FileSummary: Story = {
121
131
  render: (args) => (
122
- <div style={{ width: '300px' }}>
123
- <Wrapper>
124
- <FileSummaryComponent {...args} />
125
- </Wrapper>
132
+ <div className="card" style={{ width: '300px' }}>
133
+ <div className="card-summary">
134
+ <Wrapper>
135
+ <div className="file-teaser">
136
+ <FileSummaryComponent {...args} />
137
+ </div>
138
+ </Wrapper>
139
+ </div>
126
140
  </div>
127
141
  ),
128
142
  args: {
129
143
  item: {
130
- title: 'Simple Card with strings',
144
+ title: 'Summary',
131
145
  description:
132
146
  'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea.',
147
+ getObjSize: '72.7 KB',
148
+ mime_type: 'application/pdf',
133
149
  head_title: 'Simple Card',
134
150
  start: '2023-01-01T11:00:00+00:00',
135
151
  end: '2023-12-31T12:00:00+00:00',
@@ -165,7 +165,10 @@ export const CustomImage: Story = {
165
165
  render: (args) => (
166
166
  <div
167
167
  className="card-listing"
168
- style={{ width: 'var(--default-container-width)' }}
168
+ style={{
169
+ width: 'var(--default-container-width)',
170
+ '--theme-high-contrast-color': '#ecebeb',
171
+ }}
169
172
  >
170
173
  <Card href={args.href}>
171
174
  <Card.Image>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { describe, it, expect, vi } from 'vitest';
3
- import { render, fireEvent } from '@testing-library/react';
3
+ import { render } from '@testing-library/react';
4
4
  import Card from './Card';
5
5
 
6
6
  vi.mock(
@@ -43,10 +43,16 @@ vi.mock(
43
43
 
44
44
  type SummaryProps = {
45
45
  a11yLabelId?: string;
46
+ LinkToItem?: React.ElementType;
46
47
  };
47
48
 
48
- const SummaryContent = ({ a11yLabelId }: SummaryProps) => (
49
- <h3 id={a11yLabelId}>Card title</h3>
49
+ const SummaryContent = ({
50
+ a11yLabelId,
51
+ LinkToItem = React.Fragment,
52
+ }: SummaryProps) => (
53
+ <h3 id={a11yLabelId}>
54
+ <LinkToItem>Card title</LinkToItem>
55
+ </h3>
50
56
  );
51
57
 
52
58
  const BodyContent = () => <div>Body content</div>;
@@ -64,26 +70,20 @@ describe('Card', () => {
64
70
 
65
71
  it('is interactive when an href is provided', () => {
66
72
  const { container } = renderCard({ href: '/target', className: 'custom' });
67
- const card = container.querySelector('.card') as HTMLElement;
68
-
69
- expect(card).toHaveAttribute('role', 'link');
70
- expect(card).toHaveAttribute('tabindex', '0');
71
73
 
72
74
  const anchor = container.querySelector('a');
73
75
  expect(anchor).not.toBeNull();
74
76
  expect(anchor).toHaveAttribute('href', '/target');
77
+ expect(anchor).toHaveClass('card-primary-link');
75
78
  });
76
79
 
77
80
  it('is interactive when an item is provided', () => {
78
81
  const { container } = renderCard({ item: { '@id': '/item-target' } });
79
- const card = container.querySelector('.card') as HTMLElement;
80
-
81
- expect(card).toHaveAttribute('role', 'link');
82
- expect(card).toHaveAttribute('tabindex', '0');
83
82
 
84
83
  const anchor = container.querySelector('a');
85
84
  expect(anchor).not.toBeNull();
86
85
  expect(anchor).toHaveAttribute('href', '/item-target');
86
+ expect(anchor).toHaveClass('card-primary-link');
87
87
  });
88
88
 
89
89
  it('is not interactive when neither href nor item is provided', () => {
@@ -112,26 +112,4 @@ describe('Card', () => {
112
112
  expect(card).not.toHaveAttribute('tabindex');
113
113
  expect(container.querySelector('a')).toBeNull();
114
114
  });
115
-
116
- it('triggers navigation handlers when interactive', () => {
117
- const clickSpy = vi
118
- .spyOn(HTMLAnchorElement.prototype, 'click')
119
- .mockImplementation(() => {});
120
- const selectionSpy = vi
121
- .spyOn(window, 'getSelection')
122
- .mockReturnValue({ toString: () => '' } as unknown as Selection);
123
-
124
- const { container } = renderCard({ href: '/target' });
125
- const card = container.querySelector('.card') as HTMLElement;
126
-
127
- fireEvent.click(card);
128
- fireEvent.keyDown(card, { key: 'Enter' });
129
- fireEvent.keyDown(card, { key: ' ' });
130
- fireEvent.keyDown(card, { key: 'Escape' });
131
-
132
- expect(clickSpy).toHaveBeenCalledTimes(3);
133
-
134
- clickSpy.mockRestore();
135
- selectionSpy.mockRestore();
136
- });
137
115
  });