@hashicorp/react-components 0.0.0-nightly.10f9286 → 0.0.0-nightly.1679700

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.
package/.eslintrc.js CHANGED
@@ -1,4 +1,3 @@
1
1
  module.exports = {
2
- root: true,
3
- extends: require.resolve('@hashicorp/platform-cli/config/.eslintrc.js'),
2
+ /* Specify overrides here */
4
3
  }
package/.stylelintrc.js CHANGED
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
- extends: ['@hashicorp/platform-cli/config/stylelint.config']
2
+ extends: ['@hashicorp/platform-cli/config/stylelint.config'],
3
3
  }
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # `@hashicorp/react-components`
2
2
 
3
- This package contains React components that are built using HDS guidelines that don't align with existing HDS components.
3
+ This package contains React components that are built using HDS guidelines that don't align with existing HDS components.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hashicorp/react-components",
3
- "version": "0.0.0-nightly.10f9286",
3
+ "version": "0.0.0-nightly.1679700",
4
4
  "main": "src/index.ts",
5
5
  "scripts": {
6
6
  "lint": "next-hashicorp lint",
package/postcss.config.js CHANGED
@@ -13,7 +13,7 @@ function standardSyntax(plugins) {
13
13
  return _plugins
14
14
  }
15
15
 
16
- const baseConfig = require('@hashicorp/platform-postcss-config')
16
+ const baseConfig = require('@hashicorp/mds-postcss-config')
17
17
 
18
18
  module.exports = {
19
19
  ...baseConfig,
@@ -1,3 +1,3 @@
1
1
  .flight-icon {
2
2
  display: inline-block;
3
- }
3
+ }
@@ -0,0 +1,107 @@
1
+ import Link from 'next/link'
2
+ import classNames from 'classnames'
3
+ import { vercelSplit } from '../../../../lib/v'
4
+ import { getLocalizedLinkProps } from '../../../../lib/get-localized-link-props'
5
+ import FlightIcon from '../flight-icon'
6
+ import * as NavigationMenu from '@radix-ui/react-navigation-menu'
7
+ import s from './style.module.css'
8
+
9
+ interface NavLinkProps {
10
+ title: string
11
+ url: string
12
+ icon?: string
13
+ description?: string
14
+ iconGradient?: string
15
+ iconAppearance?: 'light' | 'dark'
16
+ linkClickHandler?: (title: string, url: string) => void
17
+ locale?: string
18
+ className?: string
19
+ }
20
+
21
+ const GRADIENT_VALUE_MAP = new Map([
22
+ [
23
+ 'ILM',
24
+ {
25
+ iconGradient: {
26
+ light: 'var(--icon-gradient-infrastructure-lifecycle-management)',
27
+ dark: 'var(--icon-gradient-infrastructure-lifecycle-management-dark)',
28
+ },
29
+ },
30
+ ],
31
+ [
32
+ 'SLM',
33
+ {
34
+ iconGradient: {
35
+ light: 'var(--icon-gradient-security-lifecycle-management)',
36
+ dark: 'var(--icon-gradient-security-lifecycle-management-dark)',
37
+ },
38
+ },
39
+ ],
40
+ [
41
+ 'Cloud',
42
+ {
43
+ iconGradient: {
44
+ light: 'var(--icon-gradient-infrastructure-cloud)',
45
+ dark: 'var(--icon-gradient-infrastructure-cloud-dark)',
46
+ },
47
+ },
48
+ ],
49
+ ])
50
+
51
+ export default function NavLink({
52
+ url,
53
+ title,
54
+ description,
55
+ icon,
56
+ iconGradient,
57
+ iconAppearance = 'light',
58
+ linkClickHandler,
59
+ locale,
60
+ className,
61
+ }: NavLinkProps) {
62
+ const style = iconGradient
63
+ ? {
64
+ ['--iconGradient' as string]: GRADIENT_VALUE_MAP.get(
65
+ vercelSplit(iconGradient)
66
+ )?.iconGradient[vercelSplit(iconAppearance)],
67
+ }
68
+ : undefined
69
+
70
+ return (
71
+ <NavigationMenu.Link asChild>
72
+ <Link
73
+ className={classNames(s.link, className)}
74
+ {...getLocalizedLinkProps(url, locale)}
75
+ onClickCapture={() => {
76
+ linkClickHandler && linkClickHandler(title, url)
77
+ }}
78
+ >
79
+ {iconGradient && icon ? (
80
+ <div
81
+ className={s.iconBackground}
82
+ style={style}
83
+ data-theme={iconAppearance}
84
+ >
85
+ <FlightIcon
86
+ name={vercelSplit(icon)}
87
+ color="var(--token-color-foreground-strong)"
88
+ />
89
+ </div>
90
+ ) : (
91
+ icon && (
92
+ <div className={s.iconWrapper}>
93
+ <FlightIcon
94
+ name={vercelSplit(icon)}
95
+ color="var(--token-color-foreground-faint)"
96
+ />
97
+ </div>
98
+ )
99
+ )}
100
+ <div>
101
+ <div className={iconGradient && s.boldTitle}>{title}</div>
102
+ {description && <div className={s.description}>{description}</div>}
103
+ </div>
104
+ </Link>
105
+ </NavigationMenu.Link>
106
+ )
107
+ }
@@ -0,0 +1,64 @@
1
+ .linkList {
2
+ display: flex;
3
+ list-style: none;
4
+ flex-direction: column;
5
+ gap: var(--mds-spacing-03);
6
+ margin: 0;
7
+ padding: 0;
8
+ }
9
+
10
+ .link {
11
+ color: var(--token-color-foreground-primary);
12
+ display: flex;
13
+ gap: var(--mds-spacing-04);
14
+ padding: var(--mds-spacing-03) var(--mds-spacing-05);
15
+ min-width: 190px;
16
+ align-items: flex-start;
17
+ height: 100%;
18
+
19
+ &:hover {
20
+ background-color: var(--token-color-surface-interactive-hover);
21
+ border-radius: var(--mds-spacing-01);
22
+ }
23
+
24
+ &:has(.iconBackground) {
25
+ align-items: flex-start;
26
+ }
27
+
28
+ @media (--large) {
29
+ max-width: 416px;
30
+ }
31
+
32
+ &:focus {
33
+ outline: 2px solid var(--token-color-focus-action-internal);
34
+ outline-style: auto;
35
+ }
36
+ }
37
+
38
+ .description {
39
+ font-size: var(--mds-typography-body-200-font-size);
40
+ font-weight: var(--mds-typography-font-weight-regular);
41
+ margin-top: var(--mds-spacing-02);
42
+ color: var(--token-color-foreground-faint);
43
+ }
44
+
45
+ .iconBackground {
46
+ background: var(--iconGradient);
47
+ height: var(--mds-spacing-08);
48
+ width: var(--mds-spacing-08);
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ border-radius: 3px;
53
+ flex: none;
54
+ margin-top: 3px;
55
+ }
56
+
57
+ .boldTitle {
58
+ font-weight: var(--mds-typography-font-weight-semibold);
59
+ }
60
+
61
+ .iconWrapper {
62
+ margin-top: 3px;
63
+ height: fit-content;
64
+ }
@@ -1,8 +1,4 @@
1
- import Link from 'next/link'
2
- import { vercelSplit } from '../../../../lib/v'
3
- import { getLocalizedLinkProps } from '../../../../lib/get-localized-link-props'
4
- import FlightIcon from '../flight-icon'
5
- import * as NavigationMenu from '@radix-ui/react-navigation-menu'
1
+ import NavLink from '../link'
6
2
  import s from './style.module.css'
7
3
 
8
4
  export interface LinkListProps {
@@ -13,31 +9,11 @@ export interface LinkListProps {
13
9
  icon?: string
14
10
  description?: string
15
11
  iconGradient?: string
12
+ iconAppearance?: 'light' | 'dark'
16
13
  }[]
17
14
  linkClickHandler?: (title: string, url: string) => void
18
15
  }
19
16
 
20
- const GRADIENT_VALUE_MAP = new Map([
21
- [
22
- 'ILM',
23
- {
24
- iconGradient: 'var(--icon-gradient-infrastructure-lifecycle-management)',
25
- },
26
- ],
27
- [
28
- 'SLM',
29
- {
30
- iconGradient: 'var(--icon-gradient-security-lifecycle-management)',
31
- },
32
- ],
33
- [
34
- 'Cloud',
35
- {
36
- iconGradient: 'var(--icon-gradient-infrastructure-cloud)',
37
- },
38
- ],
39
- ])
40
-
41
17
  export default function LinkList({
42
18
  locale,
43
19
  links,
@@ -46,46 +22,13 @@ export default function LinkList({
46
22
  return (
47
23
  <ul className={s.linkList}>
48
24
  {links.map((link) => {
49
- let style
50
- link.iconGradient
51
- ? (style = {
52
- '--iconGradient': GRADIENT_VALUE_MAP.get(
53
- vercelSplit(link.iconGradient)
54
- )?.iconGradient,
55
- } as React.CSSProperties)
56
- : (style = null)
57
25
  return (
58
26
  <li key={link.title}>
59
- <NavigationMenu.Link asChild>
60
- <Link
61
- className={s.link}
62
- {...getLocalizedLinkProps(link.url, locale)}
63
- onClickCapture={() => {
64
- linkClickHandler && linkClickHandler(link.title, link.url)
65
- }}
66
- >
67
- {link.iconGradient && link.icon ? (
68
- <div className={s.iconBackground} style={style}>
69
- <FlightIcon name={vercelSplit(link.icon)} />
70
- </div>
71
- ) : (
72
- link.icon && (
73
- <FlightIcon
74
- name={vercelSplit(link.icon)}
75
- color="var(--token-color-foreground-faint)"
76
- />
77
- )
78
- )}
79
- <div>
80
- <div className={link.iconGradient && s.boldTitle}>
81
- {link.title}
82
- </div>
83
- {link.description && (
84
- <div className={s.description}>{link.description}</div>
85
- )}
86
- </div>
87
- </Link>
88
- </NavigationMenu.Link>
27
+ <NavLink
28
+ {...link}
29
+ linkClickHandler={linkClickHandler}
30
+ locale={locale}
31
+ />
89
32
  </li>
90
33
  )
91
34
  })}
@@ -6,52 +6,3 @@
6
6
  margin: 0;
7
7
  padding: 0;
8
8
  }
9
-
10
- .link {
11
- color: var(--token-color-foreground-primary);
12
- display: flex;
13
- gap: var(--mds-spacing-04);
14
- padding: var(--mds-spacing-03) var(--mds-spacing-04);
15
- min-width: 190px;
16
- align-items: center;
17
-
18
- &:hover {
19
- background-color: var(--token-color-surface-interactive-hover);
20
- border-radius: var(--mds-spacing-01);
21
- }
22
-
23
- &:has(.iconBackground) {
24
- align-items: flex-start;
25
- }
26
-
27
- @media (--large) {
28
- max-width: 416px;
29
- }
30
-
31
- &:focus {
32
- outline: 2px solid var(--token-color-focus-action-internal);
33
- outline-style: auto;
34
- }
35
- }
36
-
37
- .description {
38
- font-size: var(--mds-typography-body-200-font-size);
39
- font-weight: var(--mds-typography-font-weight-regular);
40
- margin-top: var(--mds-spacing-02);
41
- }
42
-
43
- .iconBackground {
44
- background: var(--iconGradient);
45
- height: var(--mds-spacing-08);
46
- width: var(--mds-spacing-08);
47
- display: flex;
48
- align-items: center;
49
- justify-content: center;
50
- border-radius: 3px;
51
- flex: none;
52
- margin-top: 3px;
53
- }
54
-
55
- .boldTitle {
56
- font-weight: var(--mds-typography-font-weight-semibold);
57
- }
@@ -11,6 +11,7 @@ import s from './style.module.css'
11
11
  export interface PromoProps {
12
12
  locale?: string
13
13
  title: string
14
+ titleLinkUrl?: string
14
15
  description: string
15
16
  linkUrl: string
16
17
  linkTitle: string
@@ -24,6 +25,7 @@ export interface PromoProps {
24
25
  export default function Promo({
25
26
  locale,
26
27
  title,
28
+ titleLinkUrl,
27
29
  description,
28
30
  linkUrl,
29
31
  linkTitle,
@@ -65,14 +67,26 @@ export default function Promo({
65
67
  )}
66
68
  <div className={s.rightContent}>
67
69
  <div>
68
- <div
69
- className={classNames(s.title, {
70
- [s.hashidays]: vercelSplit(theme) === 'hashidays',
71
- [s.hashiconf]: vercelSplit(theme) === 'hashiconf',
72
- })}
73
- >
74
- {title}
75
- </div>
70
+ {titleLinkUrl ? (
71
+ <a
72
+ className={classNames(s.title, s.link, {
73
+ [s.hashidays]: vercelSplit(theme) === 'hashidays',
74
+ [s.hashiconf]: vercelSplit(theme) === 'hashiconf',
75
+ })}
76
+ href={titleLinkUrl}
77
+ >
78
+ {title}
79
+ </a>
80
+ ) : (
81
+ <div
82
+ className={classNames(s.title, {
83
+ [s.hashidays]: vercelSplit(theme) === 'hashidays',
84
+ [s.hashiconf]: vercelSplit(theme) === 'hashiconf',
85
+ })}
86
+ >
87
+ {title}
88
+ </div>
89
+ )}
76
90
  <div className={s.description}>{description}</div>
77
91
  </div>
78
92
  <NavigationMenu.Link asChild>
@@ -8,6 +8,8 @@ import FlightIcon from '../components/flight-icon'
8
8
  import { Text } from '../components/text'
9
9
  import { trackNavClickEvent } from '../../../lib/track-nav-click-event'
10
10
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
11
+ import { LinkListProps } from '../components/link-list'
12
+ import NavLink from '../components/link'
11
13
  import s from './style.module.css'
12
14
 
13
15
  const PRODUCT_LOGO_MAP = new Map([
@@ -29,9 +31,15 @@ const PRODUCT_LOGO_EXCEPTION_CLASSNAMES = {
29
31
  'HCP Vault Radar': 'hcpVaultRadar',
30
32
  }
31
33
 
34
+ export type ProductCategoriesProps = Array<{
35
+ title: string
36
+ group?: LinkListProps['links'][0]
37
+ products: NavProductProps[]
38
+ }>
39
+
32
40
  export interface ProductsPanelProps {
33
41
  locale?: string
34
- productCategories: any
42
+ productCategories: ProductCategoriesProps
35
43
  promo?: PromoProps
36
44
  sidePanel?: {
37
45
  label: string
@@ -71,10 +79,19 @@ const ProductPanel = ({
71
79
  ) : null}
72
80
  <NavPanel.Column hasSidePanel={Boolean(sidePanel)}>
73
81
  <ul className={s.productCategories}>
74
- {productCategories.map(({ title, products }) => {
82
+ {productCategories.map(({ group, title, products }) => {
75
83
  return (
76
- <li key={title} className={s.productCategory}>
77
- <Text className={s.eyebrow}>{title}</Text>
84
+ <li
85
+ key={title}
86
+ className={classNames(s.productCategory, {
87
+ [s.productCategoryHasGroup]: group,
88
+ })}
89
+ >
90
+ {group ? (
91
+ <NavLink {...group} className={s.productGroupLink} />
92
+ ) : (
93
+ <Text className={s.eyebrow}>{title}</Text>
94
+ )}
78
95
  <ul className={s.productList}>
79
96
  {products.map((product) => {
80
97
  return (
@@ -354,3 +354,42 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
354
354
  .sidePanelText {
355
355
  font-weight: var(--mds-typography-font-weight-semibold);
356
356
  }
357
+
358
+ .productCategoryHasGroup {
359
+ & .productList {
360
+ padding-left: 0;
361
+ padding-right: 0;
362
+ padding-top: 0;
363
+ }
364
+
365
+ & .productWrapper {
366
+ gap: var(--mds-spacing-04);
367
+
368
+ @media (--small) {
369
+ padding: var(--mds-spacing-03) var(--mds-spacing-05);
370
+ }
371
+ }
372
+
373
+ & .productLogo {
374
+ margin-top: 3px;
375
+ height: 32px;
376
+ width: 32px;
377
+ min-width: 32px;
378
+
379
+ & svg {
380
+ width: 100%;
381
+ height: 100%;
382
+ }
383
+ }
384
+
385
+ & .terraform {
386
+ width: 100%;
387
+ height: 100%;
388
+ }
389
+ }
390
+
391
+ .productGroupLink {
392
+ min-width: 100%;
393
+ max-width: 100%;
394
+ margin-bottom: var(--mds-spacing-03);
395
+ }