@hashicorp/react-components 0.0.0-nightly.ad81ac2 → 0.0.0-nightly.b154bf4

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 (142) hide show
  1. package/.eslintrc.js +1 -2
  2. package/.stylelintrc.js +1 -1
  3. package/README.md +1 -1
  4. package/package.json +3 -8
  5. package/postcss.config.js +1 -1
  6. package/src/components/nav-panel/components/flight-icon/index.tsx +51 -0
  7. package/src/components/nav-panel/components/flight-icon/style.module.css +3 -0
  8. package/src/components/nav-panel/components/link/index.tsx +127 -0
  9. package/src/components/nav-panel/components/link/style.module.css +64 -0
  10. package/src/components/nav-panel/components/link-list/index.tsx +13 -65
  11. package/src/components/nav-panel/components/link-list/style.module.css +1 -50
  12. package/src/components/nav-panel/components/panel/column/style.module.css +2 -2
  13. package/src/components/nav-panel/components/panel/root/style.module.css +5 -5
  14. package/src/components/nav-panel/components/promo/index.tsx +31 -11
  15. package/src/components/nav-panel/components/promo/style.module.css +26 -12
  16. package/src/components/nav-panel/components/text/index.tsx +34 -0
  17. package/src/components/nav-panel/product-panel/index.tsx +54 -17
  18. package/src/components/nav-panel/product-panel/style.module.css +116 -36
  19. package/src/components/nav-panel/standard-panel/index.tsx +3 -0
  20. package/src/components/nav-panel/standard-panel/style.module.css +2 -2
  21. package/src/lib/get-localized-link-props/index.test.ts +30 -0
  22. package/src/lib/get-localized-link-props/index.ts +45 -0
  23. package/src/lib/parse-url/index.ts +0 -2
  24. package/src/lib/send-posthog-event/index.ts +22 -0
  25. package/src/lib/supported-locales/index.ts +10 -0
  26. package/src/lib/track-nav-click-event/index.ts +4 -4
  27. package/src/components/actions/index.tsx +0 -107
  28. package/src/components/actions/style.module.css +0 -28
  29. package/src/components/actions/types.ts +0 -73
  30. package/src/components/call-to-action/index.tsx +0 -205
  31. package/src/components/call-to-action/styles/variant-centered.module.css +0 -93
  32. package/src/components/call-to-action/styles/variant-compact-grid.module.css +0 -88
  33. package/src/components/call-to-action/styles/variant-compact.module.css +0 -91
  34. package/src/components/call-to-action/styles/variant-links.module.css +0 -85
  35. package/src/components/card/README.md +0 -11
  36. package/src/components/card/card.tsx +0 -45
  37. package/src/components/card/index.test.tsx +0 -69
  38. package/src/components/card/index.tsx +0 -14
  39. package/src/components/card/newsroom-card/index.test.tsx +0 -39
  40. package/src/components/card/newsroom-card/index.tsx +0 -37
  41. package/src/components/card/newsroom-card/style.module.css +0 -12
  42. package/src/components/card/partner-card/index.test.tsx +0 -57
  43. package/src/components/card/partner-card/index.tsx +0 -69
  44. package/src/components/card/partner-card/style.module.css +0 -24
  45. package/src/components/card/person-card/index.test.tsx +0 -71
  46. package/src/components/card/person-card/index.tsx +0 -93
  47. package/src/components/card/person-card/style.module.css +0 -33
  48. package/src/components/card/primitives.tsx +0 -177
  49. package/src/components/card/promo-card/index.tsx +0 -51
  50. package/src/components/card/resource-card/index.test.tsx +0 -48
  51. package/src/components/card/resource-card/index.tsx +0 -40
  52. package/src/components/card/style.module.css +0 -145
  53. package/src/components/card/types.ts +0 -66
  54. package/src/components/card/unified-card/index.spec.tsx +0 -40
  55. package/src/components/card/unified-card/index.tsx +0 -58
  56. package/src/components/intro/index.tsx +0 -82
  57. package/src/components/intro/style.module.css +0 -67
  58. package/src/components/intro/types.ts +0 -44
  59. package/src/components/marketo-form/CHANGELOG.md +0 -122
  60. package/src/components/marketo-form/README.md +0 -1
  61. package/src/components/marketo-form/contexts/FormMetadata.ts +0 -13
  62. package/src/components/marketo-form/docs.mdx +0 -197
  63. package/src/components/marketo-form/fixtures/index.ts +0 -185
  64. package/src/components/marketo-form/form/index.tsx +0 -371
  65. package/src/components/marketo-form/index.test.tsx +0 -320
  66. package/src/components/marketo-form/index.ts +0 -11
  67. package/src/components/marketo-form/package.original.json +0 -30
  68. package/src/components/marketo-form/partials/error-message/index.tsx +0 -12
  69. package/src/components/marketo-form/partials/error-message/style.module.css +0 -13
  70. package/src/components/marketo-form/partials/field/index.tsx +0 -90
  71. package/src/components/marketo-form/partials/field-wrapper/index.tsx +0 -26
  72. package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +0 -32
  73. package/src/components/marketo-form/partials/fields/email-field/index.tsx +0 -35
  74. package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +0 -23
  75. package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +0 -38
  76. package/src/components/marketo-form/partials/fields/htmltext-field/index.tsx +0 -21
  77. package/src/components/marketo-form/partials/fields/htmltext-field/style.module.css +0 -18
  78. package/src/components/marketo-form/partials/fields/name-field/index.tsx +0 -19
  79. package/src/components/marketo-form/partials/fields/name-field/style.module.css +0 -13
  80. package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +0 -48
  81. package/src/components/marketo-form/partials/fields/select-field/index.tsx +0 -39
  82. package/src/components/marketo-form/partials/fields/select-field/style.module.css +0 -5
  83. package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +0 -30
  84. package/src/components/marketo-form/partials/fields/text-field/index.tsx +0 -30
  85. package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +0 -29
  86. package/src/components/marketo-form/partials/label/index.tsx +0 -24
  87. package/src/components/marketo-form/partials/label/style.module.css +0 -12
  88. package/src/components/marketo-form/partials/visibility-rule/index.tsx +0 -84
  89. package/src/components/marketo-form/props.js +0 -66
  90. package/src/components/marketo-form/server/api-routes.ts +0 -109
  91. package/src/components/marketo-form/server/client.ts +0 -98
  92. package/src/components/marketo-form/server/index.ts +0 -8
  93. package/src/components/marketo-form/types.ts +0 -267
  94. package/src/components/marketo-form/utils.test.tsx +0 -103
  95. package/src/components/marketo-form/utils.ts +0 -449
  96. package/src/components/next-steps/index.tsx +0 -138
  97. package/src/components/next-steps/style.module.css +0 -270
  98. package/src/components/next-steps/types.ts +0 -63
  99. package/src/components/product-badge/index.test.tsx +0 -11
  100. package/src/components/product-badge/index.tsx +0 -42
  101. package/src/components/product-badge/style.module.css +0 -76
  102. package/src/components/products-used/index.tsx +0 -84
  103. package/src/components/products-used/style.module.css +0 -87
  104. package/src/components/products-used/types.ts +0 -31
  105. package/src/components/related-content/index.test.tsx +0 -74
  106. package/src/components/related-content/index.tsx +0 -56
  107. package/src/components/related-content/style.module.css +0 -89
  108. package/src/components/related-content/types.ts +0 -21
  109. package/src/components/subnav/helpers/areBasePathsMatching.ts +0 -13
  110. package/src/components/subnav/helpers/traverse/index.ts +0 -42
  111. package/src/components/subnav/helpers/useHeightRef.ts +0 -42
  112. package/src/components/subnav/helpers/useNavRef.ts +0 -30
  113. package/src/components/subnav/helpers/useOverflowRef.ts +0 -85
  114. package/src/components/subnav/helpers/useStuckRef.ts +0 -51
  115. package/src/components/subnav/index.tsx +0 -204
  116. package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.test.ts +0 -26
  117. package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.ts +0 -22
  118. package/src/components/subnav/partials/CtaLinks/github-stars-link/index.tsx +0 -87
  119. package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.test.ts +0 -29
  120. package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.ts +0 -32
  121. package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +0 -81
  122. package/src/components/subnav/partials/CtaLinks/icons/github-logo.js +0 -20
  123. package/src/components/subnav/partials/CtaLinks/icons/github.svg.js +0 -7
  124. package/src/components/subnav/partials/CtaLinks/icons/star.js +0 -20
  125. package/src/components/subnav/partials/CtaLinks/index.tsx +0 -131
  126. package/src/components/subnav/partials/CtaLinks/style.module.css +0 -45
  127. package/src/components/subnav/partials/DropdownTrigger/index.tsx +0 -35
  128. package/src/components/subnav/partials/DropdownTrigger/style.module.css +0 -39
  129. package/src/components/subnav/partials/MenuItemsDefault/index.tsx +0 -158
  130. package/src/components/subnav/partials/MenuItemsDefault/style.module.css +0 -104
  131. package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +0 -143
  132. package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +0 -88
  133. package/src/components/subnav/partials/TitleLink/index.tsx +0 -113
  134. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +0 -10
  135. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +0 -10
  136. package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-dark.ts +0 -23
  137. package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-light.ts +0 -23
  138. package/src/components/subnav/partials/TitleLink/style.module.css +0 -43
  139. package/src/components/subnav/partials/nav-item-text/index.tsx +0 -37
  140. package/src/components/subnav/partials/nav-item-text/style.module.css +0 -13
  141. package/src/components/subnav/style.module.css +0 -66
  142. package/src/components/subnav/subnav-consts.ts +0 -1
@@ -1,177 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import * as React from 'react'
7
- import classNames from 'classnames'
8
- import Image from 'next/image'
9
- import Link from 'next/link'
10
- import HDSCard from '@hashicorp/react-hds/src/components/card'
11
- import { TextPlus } from '@hashicorp/react-hds/src/components/text'
12
- import { IconArrowRight24 } from '@hashicorp/flight-icons/svg-react/arrow-right-24'
13
- import ProductBadge from '../product-badge'
14
- import type {
15
- CardPrimitiveProps,
16
- ThumbnailProps,
17
- MetaProps,
18
- ContentProps,
19
- HeadingProps,
20
- ProductBadgesProps,
21
- DescriptionProps,
22
- } from './types'
23
- import s from './style.module.css'
24
-
25
- const Card = React.forwardRef<HTMLAnchorElement, CardPrimitiveProps>(
26
- (props, ref) => {
27
- const {
28
- withArrow = true,
29
- heading,
30
- link,
31
- clickHandler,
32
- isExternal,
33
- hasBorder = true,
34
- children,
35
- className,
36
- 'aria-label': ariaLabel,
37
- } = props
38
-
39
- const linkProps = isExternal
40
- ? { target: '_blank', rel: 'noopener noreferrer' }
41
- : {}
42
-
43
- return (
44
- <HDSCard
45
- level="mid"
46
- levelHover="high"
47
- className={classNames(s.card, className)}
48
- overflow="hidden"
49
- hasBorder={hasBorder}
50
- >
51
- <div className={s.contentContainer}>
52
- {children}
53
-
54
- <div className={s.cta} data-testid="wpl-card-cta">
55
- {withArrow ? <IconArrowRight24 /> : null}
56
- </div>
57
-
58
- <Link
59
- href={link}
60
- ref={ref}
61
- className={s.link}
62
- aria-label={ariaLabel ?? heading}
63
- onClickCapture={clickHandler}
64
- {...linkProps}
65
- />
66
- </div>
67
- </HDSCard>
68
- )
69
- }
70
- )
71
-
72
- function Thumbnail({ src, alt }: ThumbnailProps) {
73
- return (
74
- <div className={s.thumbnail} data-testid="wpl-card-thumbnail">
75
- <div className={s.image}>
76
- <Image src={src} alt={alt} width={800} height={450} />
77
- </div>
78
- </div>
79
- )
80
- }
81
-
82
- function PersonThumbnail({ src, alt }: ThumbnailProps) {
83
- return (
84
- <div className={s.personThumbnail} data-testid="wpl-card-thumbnail">
85
- <div className={s.image}>
86
- <Image src={src} alt={alt} width={800} height={450} />
87
- </div>
88
- </div>
89
- )
90
- }
91
-
92
- function LogoThumbnail({ src, alt }: ThumbnailProps) {
93
- return (
94
- <div className={s.logoThumbnail} data-testid="wpl-card-logo-thumbnail">
95
- <div className={s.image}>
96
- <Image src={src} alt={alt} width={800} height={450} />
97
- </div>
98
- </div>
99
- )
100
- }
101
-
102
- function Meta({ items }: MetaProps) {
103
- return (
104
- <div className={s.meta} data-testid="wpl-card-meta">
105
- <TextPlus.Label>
106
- {items.map((item, stableIdx) => {
107
- const isLastItem = stableIdx === items.length - 1
108
- return (
109
- <>
110
- {item}
111
- {!isLastItem ? (
112
- <span className={s.metaSeparator} aria-hidden={true}>
113
- |
114
- </span>
115
- ) : null}
116
- </>
117
- )
118
- })}
119
- </TextPlus.Label>
120
- </div>
121
- )
122
- }
123
-
124
- function Content({ children }: ContentProps) {
125
- return (
126
- <div className={s.content} data-testid="wpl-card-content">
127
- {children}
128
- </div>
129
- )
130
- }
131
-
132
- function Heading({ as = 'h2', children }: HeadingProps) {
133
- return (
134
- <TextPlus.DisplayExpressive tag={as} size="200" className={s.heading}>
135
- {children}
136
- </TextPlus.DisplayExpressive>
137
- )
138
- }
139
-
140
- function ProductBadges({ badges, children }: ProductBadgesProps) {
141
- return (
142
- <div className={s.productBadges} data-testid="wpl-card-badges">
143
- {badges.map((badge, stableIdx) => {
144
- return (
145
- <ProductBadge
146
- // eslint-disable-next-line react/no-array-index-key
147
- key={`product-badge-${stableIdx}`}
148
- productName={badge}
149
- hasDot={true}
150
- />
151
- )
152
- })}
153
- {children}
154
- </div>
155
- )
156
- }
157
-
158
- function Description({ children }: DescriptionProps) {
159
- return (
160
- <TextPlus.Body tag="p" size="200" className={s.description}>
161
- {children}
162
- </TextPlus.Body>
163
- )
164
- }
165
-
166
- Card.displayName = 'Card'
167
- export {
168
- Card,
169
- Thumbnail,
170
- PersonThumbnail,
171
- LogoThumbnail,
172
- Meta,
173
- Content,
174
- Heading,
175
- Description,
176
- ProductBadges,
177
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import * as CardPrimitives from '../primitives'
7
- import type { ThumbnailProps } from '../types'
8
-
9
- export interface PromoCardProps {
10
- heading: string
11
- description?: string
12
- eyebrow?: string
13
- link: string
14
- clickHandler?: () => void
15
- thumbnail?: ThumbnailProps
16
- withArrow?: boolean
17
- isExternal?: boolean
18
- className?: string
19
- }
20
-
21
- export function PromoCard({
22
- heading,
23
- description,
24
- eyebrow,
25
- link,
26
- clickHandler,
27
- thumbnail,
28
- withArrow = false,
29
- isExternal = false,
30
- className,
31
- }: PromoCardProps) {
32
- return (
33
- <CardPrimitives.Card
34
- heading={heading}
35
- link={link}
36
- withArrow={withArrow}
37
- isExternal={isExternal}
38
- className={className}
39
- clickHandler={clickHandler}
40
- >
41
- {thumbnail ? <CardPrimitives.Thumbnail {...thumbnail} /> : null}
42
- <CardPrimitives.Content>
43
- {eyebrow ? <CardPrimitives.Meta items={[eyebrow]} /> : null}
44
- <CardPrimitives.Heading>{heading}</CardPrimitives.Heading>
45
- {description ? (
46
- <CardPrimitives.Description>{description}</CardPrimitives.Description>
47
- ) : null}
48
- </CardPrimitives.Content>
49
- </CardPrimitives.Card>
50
- )
51
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import { render, screen } from '@testing-library/react'
7
- import { ResourceCard } from '.'
8
-
9
- const defaultProps = {
10
- link: 'https://hashicorp.com',
11
- heading: 'Example heading',
12
- date: 'August 15, 2022',
13
- category: 'Category',
14
- thumbnail: {
15
- src: 'https://www.datocms-assets.com/19447/1648680074-screenshot-2022-03-31-at-00-40-47.png',
16
- alt: 'HashiConf Europe 2022 Recap',
17
- },
18
- }
19
-
20
- describe('<ResourceCard />', () => {
21
- it('should render the provided date and category with separator', () => {
22
- const expectedMeta = [defaultProps.date, defaultProps.category]
23
-
24
- render(<ResourceCard {...defaultProps} />)
25
-
26
- const metaElement = screen.getByTestId('wpl-card-meta')
27
-
28
- expectedMeta.forEach((item) => {
29
- expect(metaElement).toHaveTextContent(item)
30
- })
31
-
32
- expect(metaElement).toContainElement(screen.getByText('|'))
33
- })
34
-
35
- it('should not render the date if no date is provided', () => {
36
- const defaultPropsWithoutDate = { ...defaultProps, date: '' }
37
-
38
- render(<ResourceCard {...defaultPropsWithoutDate} />)
39
-
40
- const metaElement = screen.getByTestId('wpl-card-meta')
41
-
42
- expect(metaElement).toContainElement(
43
- screen.getByText(defaultProps.category)
44
- )
45
-
46
- expect(metaElement).not.toContainElement(screen.queryByText('|'))
47
- })
48
- })
@@ -1,40 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import type { CardProps, ThumbnailProps } from '../types'
7
- import { UnifiedCard } from '../unified-card'
8
-
9
- export interface ResourceCardProps {
10
- heading: string
11
- date?: string
12
- category: string
13
- link: string
14
- productBadges?: CardProps['productBadges']
15
- thumbnail: ThumbnailProps
16
- isExternal?: CardProps['isExternal']
17
- }
18
-
19
- export function ResourceCard({
20
- heading,
21
- date,
22
- category,
23
- link,
24
- productBadges,
25
- thumbnail,
26
- isExternal,
27
- }: ResourceCardProps) {
28
- const meta: string[] = date ? [date, category] : [category]
29
-
30
- return (
31
- <UnifiedCard
32
- heading={heading}
33
- link={link}
34
- meta={meta}
35
- productBadges={productBadges}
36
- thumbnail={thumbnail}
37
- isExternal={isExternal}
38
- />
39
- )
40
- }
@@ -1,145 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- .card {
7
- display: flex;
8
- flex-direction: column;
9
- flex-grow: 1;
10
- transition: 0.2s ease;
11
- transition-property: transform, box-shadow, border-color, background-color;
12
-
13
- &:hover {
14
- transform: translateY(-2px);
15
-
16
- & .cta svg {
17
- transform: translateX(2px);
18
- }
19
- }
20
-
21
- &.dark {
22
- & .thumbnail {
23
- border-bottom: 0;
24
- }
25
- }
26
-
27
- &:focus-within {
28
- outline-color: var(--token-color-focus-action-external);
29
- outline-width: 2px;
30
- outline-style: solid;
31
- outline-offset: 0;
32
- }
33
- }
34
-
35
- .contentContainer {
36
- display: flex;
37
- flex-direction: column;
38
- flex-grow: 1;
39
- overflow: hidden;
40
- position: relative;
41
- }
42
-
43
- .link {
44
- position: absolute;
45
- inset: 0;
46
- outline: none;
47
- }
48
-
49
- .thumbnail {
50
- & .image {
51
- position: relative;
52
- display: grid;
53
- aspect-ratio: 16 / 9;
54
- overflow: hidden;
55
-
56
- & img {
57
- object-fit: cover;
58
- object-position: center;
59
- width: 100%;
60
- height: 100%;
61
- }
62
- }
63
- }
64
-
65
- .personThumbnail {
66
- composes: thumbnail;
67
- & .image {
68
- aspect-ratio: 4 / 3;
69
- }
70
- }
71
-
72
- .logoThumbnail {
73
- composes: thumbnail;
74
- padding: var(--hdsplus-spacing-07);
75
-
76
- & .image {
77
- aspect-ratio: none;
78
-
79
- & img {
80
- aspect-ratio: 16 / 9;
81
- object-fit: contain;
82
- }
83
- }
84
- }
85
-
86
- .meta {
87
- color: var(--token-color-foreground-faint);
88
- text-transform: uppercase;
89
- margin: 0;
90
- display: flex;
91
- flex-wrap: wrap;
92
- list-style: none;
93
- padding: 0;
94
- }
95
-
96
- .metaSeparator {
97
- --padding-x: 12px;
98
-
99
- padding-left: var(--padding-x);
100
- padding-right: var(--padding-x);
101
- }
102
-
103
- .content {
104
- display: flex;
105
- flex-direction: column;
106
- flex-grow: 1;
107
- row-gap: 16px;
108
- padding: 20px 20px 0 20px;
109
- }
110
-
111
- .heading {
112
- font-weight: var(--token-typography-font-weight-bold);
113
- color: var(--token-color-foreground-strong);
114
- margin: 0;
115
- }
116
-
117
- .description {
118
- color: var(--token-color-foreground-primary);
119
- margin: 0;
120
- }
121
-
122
- .productBadges {
123
- margin-top: auto;
124
- display: flex;
125
- flex-wrap: wrap;
126
- gap: 8px;
127
- }
128
-
129
- .cta {
130
- display: flex;
131
- align-items: center;
132
- justify-content: flex-end;
133
- color: var(--token-color-foreground-primary);
134
- padding: 8px 20px 20px 20px;
135
- margin-top: auto;
136
- transition: color 0.25s ease;
137
-
138
- & svg {
139
- transition: transform 0.25s ease;
140
- }
141
-
142
- &:empty {
143
- padding-top: 0;
144
- }
145
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import type { ReactNode } from 'react'
7
- import type { ProductBadgeProps } from '../product-badge'
8
- import type { NewsroomCardProps } from './newsroom-card'
9
- import type { PersonCardProps } from './person-card'
10
- import type { ResourceCardProps } from './resource-card'
11
- import type { UnifiedCardProps } from './unified-card'
12
-
13
- export interface BaseCardProps
14
- extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
15
- withArrow?: boolean
16
- heading: string
17
- link: string
18
- clickHandler?: () => void
19
- isExternal?: boolean
20
- hasBorder?: boolean
21
- }
22
-
23
- export interface CardPrimitiveProps extends BaseCardProps {
24
- children: ReactNode
25
- }
26
-
27
- export interface ThumbnailProps {
28
- src: string
29
- alt: string
30
- }
31
-
32
- export interface MetaProps {
33
- items: Array<string | ReactNode>
34
- }
35
-
36
- export interface ContentProps {
37
- children: ReactNode
38
- }
39
-
40
- export interface HeadingProps {
41
- as?: 'h2' | 'h3' | 'h4'
42
- children: string
43
- }
44
-
45
- export interface ProductBadgesProps {
46
- badges: Array<ProductBadgeProps['productName']>
47
- children?: ReactNode
48
- }
49
-
50
- export interface DescriptionProps {
51
- children: string
52
- }
53
-
54
- export interface CardProps extends BaseCardProps {
55
- thumbnail?: ThumbnailProps
56
- meta?: MetaProps['items']
57
- description?: DescriptionProps['children']
58
- productBadges?: ProductBadgesProps['badges']
59
- }
60
-
61
- export {
62
- NewsroomCardProps,
63
- PersonCardProps,
64
- ResourceCardProps,
65
- UnifiedCardProps,
66
- }
@@ -1,40 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import { render, screen } from '@testing-library/react'
7
- import { UnifiedCard, UnifiedCardProps } from '.'
8
-
9
- const defaultProps: UnifiedCardProps = {
10
- link: 'https://hashicorp.com',
11
- heading: 'Example heading',
12
- thumbnail: {
13
- src: 'https://www.datocms-assets.com/19447/1648680074-screenshot-2022-03-31-at-00-40-47.png',
14
- alt: 'HashiConf Europe 2022 Recap',
15
- },
16
- } as const
17
-
18
- describe(`<UnifiedCard />`, () => {
19
- it('should render the provided meta with a separator if n > 1', () => {
20
- const expectedMeta = ['Category', 'Hello']
21
- render(<UnifiedCard {...defaultProps} meta={expectedMeta} />)
22
-
23
- const metaElement = screen.getByTestId('wpl-card-meta')
24
-
25
- expectedMeta.forEach((item) => {
26
- expect(metaElement).toHaveTextContent(item)
27
- })
28
-
29
- expect(metaElement).toContainElement(screen.getByText('|'))
30
- })
31
-
32
- it('it should not render a separator if n === 1', () => {
33
- render(<UnifiedCard {...defaultProps} meta={['Category']} />)
34
- const metaElement = screen.getByTestId('wpl-card-meta')
35
-
36
- expect(metaElement).toContainElement(screen.getByText('Category'))
37
-
38
- expect(metaElement).not.toContainElement(screen.queryByText('|'))
39
- })
40
- })
@@ -1,58 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import type { ReactNode } from 'react'
7
- import Badge from '@hashicorp/react-hds/src/components/badge'
8
- import * as CardPrimitives from '../primitives'
9
- import type { CardProps } from '../types'
10
-
11
- export interface UnifiedCardProps extends CardProps {
12
- badges?: (string | [ReactNode, string])[]
13
- }
14
-
15
- export function UnifiedCard({
16
- heading,
17
- meta,
18
- link,
19
- productBadges,
20
- badges,
21
- thumbnail,
22
- withArrow = false,
23
- isExternal = false,
24
- className,
25
- 'aria-label': ariaLabel,
26
- }: UnifiedCardProps) {
27
- return (
28
- <CardPrimitives.Card
29
- heading={heading}
30
- link={link}
31
- withArrow={withArrow}
32
- isExternal={isExternal}
33
- className={className}
34
- aria-label={ariaLabel ?? heading}
35
- >
36
- {thumbnail ? <CardPrimitives.Thumbnail {...thumbnail} /> : null}
37
- <CardPrimitives.Content>
38
- {meta && meta.length > 0 ? <CardPrimitives.Meta items={meta} /> : null}
39
- <CardPrimitives.Heading>{heading}</CardPrimitives.Heading>
40
- {productBadges && productBadges?.length > 0 ? (
41
- <CardPrimitives.ProductBadges badges={productBadges}>
42
- {badges && badges.length > 0
43
- ? badges.map((badge, stableIdx) => {
44
- if (Array.isArray(badge)) {
45
- return (
46
- <Badge key={stableIdx} icon={badge[0]} text={badge[1]} />
47
- )
48
- }
49
-
50
- return <Badge key={stableIdx} text={badge} />
51
- })
52
- : null}
53
- </CardPrimitives.ProductBadges>
54
- ) : null}
55
- </CardPrimitives.Content>
56
- </CardPrimitives.Card>
57
- )
58
- }
@@ -1,82 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- import classNames from 'classnames'
7
- import type { IntroProps } from './types'
8
- import Actions from '../actions'
9
- import s from './style.module.css'
10
-
11
- export default function Intro({
12
- appearance = 'light',
13
- textAlignment = 'left',
14
- eyebrow,
15
- heading,
16
- headingElement: HeadingElement = 'h2',
17
- headingSize = 2,
18
- description,
19
- actions,
20
- }: IntroProps) {
21
- const headingSizeClassname = `g-type-display-${headingSize}`
22
- const descriptionSizeClassname =
23
- headingSize === 1 ? 'g-type-body-large' : 'g-type-body'
24
- const descriptionClassName = classNames(
25
- s.description,
26
- descriptionSizeClassname
27
- )
28
- return (
29
- <div
30
- className={classNames(s.intro, s[appearance], s[textAlignment])}
31
- data-testid="intro"
32
- >
33
- {eyebrow ? <p className={s.eyebrow}>{eyebrow}</p> : null}
34
- <HeadingElement className={classNames(s.heading, headingSizeClassname)}>
35
- {heading}
36
- </HeadingElement>
37
- <Description className={descriptionClassName}>{description}</Description>
38
- {actions && actions.ctas && actions.ctas.length > 0 ? (
39
- <div className={s.actions}>
40
- <Actions
41
- appearance={appearance}
42
- layout={actions.layout}
43
- alignment={textAlignment}
44
- theme={actions.theme}
45
- size={actions.size}
46
- ctas={actions.ctas}
47
- />
48
- </div>
49
- ) : null}
50
- </div>
51
- )
52
- }
53
-
54
- const containsHTML = (str: string) => /<[a-z][\s\S]*>/i.test(str)
55
-
56
- function Description({
57
- className,
58
- children,
59
- }: {
60
- className: string
61
- children: IntroProps['description']
62
- }) {
63
- // ReactNode
64
- if (typeof children === 'object') {
65
- return <div className={className}>{children}</div>
66
- }
67
-
68
- // HTML String
69
- if (typeof children === 'string' && containsHTML(children)) {
70
- return (
71
- <div
72
- dangerouslySetInnerHTML={{
73
- __html: children,
74
- }}
75
- className={className}
76
- />
77
- )
78
- }
79
-
80
- // String
81
- return <p className={className}>{children}</p>
82
- }