diff --git a/docs-website/docusaurus.config.js b/docs-website/docusaurus.config.js index 350521ea8ee64..fb2f418e37c04 100644 --- a/docs-website/docusaurus.config.js +++ b/docs-website/docusaurus.config.js @@ -336,6 +336,7 @@ module.exports = { require.resolve("./src/styles/sphinx.scss"), require.resolve("./src/styles/config-table.scss"), require.resolve("./src/components/SecondNavbar/styles.module.scss"), + require.resolve("./src/components/SolutionsDropdown/styles.module.css"), ], }, pages: { diff --git a/docs-website/src/components/CardDropdown/CardDropdown.tsx b/docs-website/src/components/CardDropdown/CardDropdown.tsx new file mode 100644 index 0000000000000..5f896e1ecd8c0 --- /dev/null +++ b/docs-website/src/components/CardDropdown/CardDropdown.tsx @@ -0,0 +1,183 @@ +import React, {useState, useRef, useEffect} from 'react'; +import clsx from 'clsx'; +import { + isRegexpStringMatch, + useCollapsible, + Collapsible, +} from '@docusaurus/theme-common'; +import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal'; +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; +import NavbarItem, {type LinkLikeNavbarItemProps} from '@theme/NavbarItem'; +import type { + DesktopOrMobileNavBarItemProps, + Props, +} from '@theme/NavbarItem/DropdownNavbarItem'; +import styles from './styles.module.scss'; +import Link from '@docusaurus/Link'; + +function isItemActive( + item: LinkLikeNavbarItemProps, + localPathname: string, +): boolean { + if (isSamePath(item.to, localPathname)) { + return true; + } + if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) { + return true; + } + if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) { + return true; + } + return false; +} + +function containsActiveItems( + items: readonly LinkLikeNavbarItemProps[], + localPathname: string, +): boolean { + return items.some((item) => isItemActive(item, localPathname)); +} + +function DropdownNavbarItemDesktop({ + label, + items, + position, + className, + onClick, + ...props +}: DesktopOrMobileNavBarItemProps) { + const dropdownRef = useRef(null); + const [showDropdown, setShowDropdown] = useState(false); + + useEffect(() => { + const handleClickOutside = ( + event: MouseEvent | TouchEvent | FocusEvent, + ) => { + if ( + !dropdownRef.current || + dropdownRef.current.contains(event.target as Node) + ) { + return; + } + setShowDropdown(false); + }; + + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('touchstart', handleClickOutside); + document.addEventListener('focusin', handleClickOutside); + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('touchstart', handleClickOutside); + document.removeEventListener('focusin', handleClickOutside); + }; + }, [dropdownRef]); + + return ( +
+ tag focusable in case no link target + // See https://github.com/facebook/docusaurus/pull/6003 + // There's probably a better solution though... + href={props.to ? undefined : '#'} + className={clsx('navbar__link', className)} + {...props} + onClick={props.to ? undefined : (e) => e.preventDefault()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + setShowDropdown(!showDropdown); + } + }}> + {props.children ?? props.label} + + +
+ ); +} + +function DropdownNavbarItemMobile({ + items, + className, + position, // Need to destructure position from props so that it doesn't get passed on. + onClick, + ...props +}: DesktopOrMobileNavBarItemProps) { + const localPathname = useLocalPathname(); + const containsActive = containsActiveItems(items, localPathname); + + const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({ + initialState: () => !containsActive, + }); + + // Expand/collapse if any item active after a navigation + useEffect(() => { + if (containsActive) { + setCollapsed(!containsActive); + } + }, [localPathname, containsActive, setCollapsed]); + + return ( +
  • + { + e.preventDefault(); + toggleCollapsed(); + }}> + {props.children ?? props.label} + + + <> + +
  • + ); +} + +export default function DropdownNavbarItem({ + mobile = false, + ...props +}: Props): JSX.Element { + const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop; + return ; +} \ No newline at end of file diff --git a/docs-website/src/components/CardDropdown/styles.module.scss b/docs-website/src/components/CardDropdown/styles.module.scss new file mode 100644 index 0000000000000..9b5fff816e575 --- /dev/null +++ b/docs-website/src/components/CardDropdown/styles.module.scss @@ -0,0 +1,67 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.dropdownNavbarItemMobile { + cursor: pointer; +} + +.dropdown__menu { + display: flex; + width: 13.875rem; + padding: 0.875rem 1.63694rem; + justify-content: center; + align-items: flex-start; + gap: 0.98219rem; + border-radius: var(--number-scales-2s-20, 1.25rem); + background: #FFF; + box-shadow: 0px 16px 16px 0px rgba(0, 0, 0, 0.25); +} + + +.wrapper { + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.card { + display: flex; + align-items: center; + padding: 1rem 0.8rem; + text-align: left; + gap: 0.5rem; + border-radius: 0.72681rem; + background: #F7F7F7; + width: 12rem; + transition: transform 0.2s, box-shadow 0.2s; + + &:hover { + transform: translateY(-5px); + box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); + text-decoration: none; + color: inherit; + } +} + +.icon { + flex-shrink: 0; + width: 1.3rem; + height: 1.3rem; + display: flex; + justify-content: center; + align-items: center; +} + +.title { + flex-grow: 1; + color: #1E1E1E; + font-family: Manrope, sans-serif; + font-size: 0.9rem; + font-weight: 600; + line-height: 1.5rem; + letter-spacing: -0.011rem; +} diff --git a/docs-website/src/components/SolutionsDropdown/SolutionsDropdown.tsx b/docs-website/src/components/SolutionsDropdown/SolutionsDropdown.tsx new file mode 100644 index 0000000000000..bbb38355ec059 --- /dev/null +++ b/docs-website/src/components/SolutionsDropdown/SolutionsDropdown.tsx @@ -0,0 +1,178 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, {useState, useRef, useEffect} from 'react'; +import clsx from 'clsx'; +import { + isRegexpStringMatch, + useCollapsible, + Collapsible, +} from '@docusaurus/theme-common'; +import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal'; +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; +import NavbarItem, {type LinkLikeNavbarItemProps} from '@theme/NavbarItem'; +import type { + DesktopOrMobileNavBarItemProps, + Props, +} from '@theme/NavbarItem/DropdownNavbarItem'; +import styles from './styles.module.css'; +import SolutionsDropdownContent from './SolutionsDropdownContent'; + +function isItemActive( + item: LinkLikeNavbarItemProps, + localPathname: string, +): boolean { + if (isSamePath(item.to, localPathname)) { + return true; + } + if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) { + return true; + } + if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) { + return true; + } + return false; +} + +function containsActiveItems( + items: readonly LinkLikeNavbarItemProps[], + localPathname: string, +): boolean { + return items.some((item) => isItemActive(item, localPathname)); +} + +function DropdownNavbarItemDesktop({ + items, + position, + className, + onClick, + ...props +}: DesktopOrMobileNavBarItemProps) { + const dropdownRef = useRef(null); + const [showDropdown, setShowDropdown] = useState(false); + + useEffect(() => { + const handleClickOutside = ( + event: MouseEvent | TouchEvent | FocusEvent, + ) => { + if ( + !dropdownRef.current || + dropdownRef.current.contains(event.target as Node) + ) { + return; + } + setShowDropdown(false); + }; + + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('touchstart', handleClickOutside); + document.addEventListener('focusin', handleClickOutside); + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('touchstart', handleClickOutside); + document.removeEventListener('focusin', handleClickOutside); + }; + }, [dropdownRef]); + + return ( +
    + tag focusable in case no link target + // See https://github.com/facebook/docusaurus/pull/6003 + // There's probably a better solution though... + href={props.to ? undefined : '#'} + className={clsx('navbar__link', className)} + {...props} + onClick={props.to ? undefined : (e) => e.preventDefault()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + setShowDropdown(!showDropdown); + } + }}> + {props.children ?? props.label} + +
      + <> + {/* {items.map((childItemProps, i) => ( + + ))} */} + +
    +
    + ); +} + +function DropdownNavbarItemMobile({ + items, + className, + position, // Need to destructure position from props so that it doesn't get passed on. + onClick, + ...props +}: DesktopOrMobileNavBarItemProps) { + const localPathname = useLocalPathname(); + const containsActive = containsActiveItems(items, localPathname); + + const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({ + initialState: () => !containsActive, + }); + + // Expand/collapse if any item active after a navigation + useEffect(() => { + if (containsActive) { + setCollapsed(!containsActive); + } + }, [localPathname, containsActive, setCollapsed]); + + return ( +
  • + { + e.preventDefault(); + toggleCollapsed(); + }}> + {props.children ?? props.label} + + + <> + +
  • + ); +} + +export default function DropdownNavbarItem({ + mobile = false, + ...props +}: Props): JSX.Element { + const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop; + return ; +} \ No newline at end of file diff --git a/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/index.js b/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/index.js new file mode 100644 index 0000000000000..79481c52f279e --- /dev/null +++ b/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/index.js @@ -0,0 +1,67 @@ +import React from 'react'; +import styles from './styles.module.scss'; +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import solutionsDropdownContent from './solutionsDropdownContent'; + +function SolutionsDropdownContent() { + const { fullSizeCards, halfSizeCards } = solutionsDropdownContent; + + return ( +
    +
    + {/* Full-size cards */} + {fullSizeCards.map((item, index) => ( +
    + +
    +
    + {item.title} +
    +
    {item.title}
    +
    +
    {item.description}
    +
    +
    + +
    + ))} + + {/* Half-size cards */} +
    + {halfSizeCards.map((item, index) => ( +
    + +
    +
    +
    + {item.title} +
    {item.title}
    +
    +
    {item.description}
    +
    +
    + +
    + ))} +
    +
    +
    + ); +} + +export default SolutionsDropdownContent; diff --git a/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/solutionsDropdownContent.js b/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/solutionsDropdownContent.js new file mode 100644 index 0000000000000..abede0f11735d --- /dev/null +++ b/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/solutionsDropdownContent.js @@ -0,0 +1,38 @@ +const solutionsDropdownContent = { + fullSizeCards: [ + { + title: "Data Discovery", + description: "Search, Browse, Lineage, and more.", + iconImage: "/img/solutions/icon-dropdown-discovery.png", + href: "/solutions/discovery", + }, + { + title: "Data Observability", + description: "Detect and Resolve Data Quality issues", + iconImage: "/img/solutions/icon-dropdown-observe.png", + href: "/solutions/observability", + }, + { + title: "Data Governance", + description: "Automate Classifying and Governing data.", + iconImage: "/img/solutions/icon-dropdown-governance.png", + href: "/solutions/governance", + }, + ], + halfSizeCards: [ + { + title: "DataHub Core", + description: "Get started with the Open Source platform.", + iconImage: "/img/solutions/icon-dropdown-core.png", + href: "/", + }, + { + title: "Cloud vs Core", + description: "Understand the differences.", + iconImage: "/img/solutions/icon-dropdown-cloud.png", + href: "/cloud", + }, + ], +}; + +export default solutionsDropdownContent \ No newline at end of file diff --git a/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/styles.module.scss b/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/styles.module.scss new file mode 100644 index 0000000000000..b156c3342f24a --- /dev/null +++ b/docs-website/src/components/SolutionsDropdown/SolutionsDropdownContent/styles.module.scss @@ -0,0 +1,137 @@ +.container { + display: flex; + } + + .row { + display: flex; + gap: 1rem; + } + + .card { + display: flex; + width: 12.4375rem; + height: 12.5rem; + padding: 0; + flex-direction: column; + justify-content: center; + align-items: center; + flex-shrink: 0; + border-radius: 0.72681rem; + background: #F7F7F7; + text-align: left; + text-decoration: none; + transition: transform 0.3s ease, box-shadow 0.3s ease; + } + + .header { + display: inline-flex; + } + + .title { + color: #1E1E1E; + font-family: Manrope; + font-style: normal; + font-weight: 600; + } + + .description { + color: #757575; + font-family: Manrope; + font-style: normal; + font-weight: 300; + } + + .fullSizeCard { + background-repeat: no-repeat; + background-size: contain; + background-position: bottom right; + height: 100%; + padding: 1.4rem; + + .icon { + width: 1.7rem; + height: 1.7rem; + display: block; + } + + .title { + font-size: 1.1rem; + font-weight: 600; + line-height: 150%; /* 1.6875rem */ + letter-spacing: -0.01238rem; + margin-top: 0.5rem; + } + + .description { + font-size: 0.95rem; + line-height: 150%; /* 1.5rem */ + letter-spacing: -0.011rem; + }; + } + + .halfSizeWrapper { + display: flex; + flex-direction: column; + gap: 0.98rem; + } + + .halfSizeCard { + display: flex; + height: 5.75rem; + padding: 1.4rem; + flex-direction: column; + align-items: center; + flex-shrink: 0; + align-self: stretch; + + .icon { + display: flex; + width: 1.26806rem; + height: 1.26806rem; + padding: 0.13206rem 0.13725rem 0.13213rem 0.13213rem; + justify-content: center; + align-items: center; + flex-shrink: 0; + margin-right: 0.65rem; + } + + .title { + color: #1E1E1E; + font-family: Manrope; + font-size: 0.95rem; + font-style: normal; + font-weight: 600; + line-height: 150%; /* 1.5rem */ + letter-spacing: -0.011rem; + } + + .description { + font-size: 0.75rem; + line-height: 150%; /* 1.125rem */ + letter-spacing: -0.00825rem; + margin-left: 2rem; + } + } + + .card:hover { + transform: translateY(-5px); + box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); + text-decoration: none; + color: inherit; + } + + + @media (max-width: 768px) { + .col { + flex: 1 1 48%; + max-width: 48%; + } + } + + @media (max-width: 480px) { + .col { + flex: 1 1 100%; + max-width: 100%; + } + } + \ No newline at end of file diff --git a/docs-website/src/components/SolutionsDropdown/styles.module.css b/docs-website/src/components/SolutionsDropdown/styles.module.css new file mode 100644 index 0000000000000..09c71edf0b185 --- /dev/null +++ b/docs-website/src/components/SolutionsDropdown/styles.module.css @@ -0,0 +1,22 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + .dropdownNavbarItemMobile { + cursor: pointer; +} + +.dropdown__menu { + width: fit-content; + height: fit-content; + padding: 1rem; + justify-content: center; + align-items: flex-start; + gap: 0.98219rem; + border-radius: var(--number-scales-2s-20, 1.25rem); + background: #FFF; + box-shadow: 0px 16px 16px 0px rgba(0, 0, 0, 0.25); +} \ No newline at end of file diff --git a/docs-website/src/theme/Navbar/Content/index.tsx b/docs-website/src/theme/Navbar/Content/index.tsx new file mode 100644 index 0000000000000..934ea023dd593 --- /dev/null +++ b/docs-website/src/theme/Navbar/Content/index.tsx @@ -0,0 +1,119 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, {type ReactNode} from 'react'; +import {useThemeConfig, ErrorCauseBoundary} from '@docusaurus/theme-common'; +import { + splitNavbarItems, + useNavbarMobileSidebar, +} from '@docusaurus/theme-common/internal'; +import NavbarItem, {type Props as NavbarItemConfig} from '@theme/NavbarItem'; +import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle'; +import SearchBar from '@theme/SearchBar'; +import NavbarMobileSidebarToggle from '@theme/Navbar/MobileSidebar/Toggle'; +import NavbarLogo from '@theme/Navbar/Logo'; +import NavbarSearch from '@theme/Navbar/Search'; +import SolutionsDropdown from '../../../components/SolutionsDropdown/SolutionsDropdown'; +import CardDropdown from '../../../components/CardDropdown/CardDropdown'; +import learnCardDropdownContent from '../learnCardDropdownContent'; +import communityCardDropdownContent from '../communityCardDropdownContent'; + +import styles from './styles.module.css'; + +function useNavbarItems() { + // TODO temporary casting until ThemeConfig type is improved + return useThemeConfig().navbar.items as NavbarItemConfig[]; +} + +function NavbarItems({items}: {items: NavbarItemConfig[]}): JSX.Element { + return ( + <> + {items.map((item, i) => ( + + new Error( + `A theme navbar item failed to render. +Please double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config: +${JSON.stringify(item, null, 2)}`, + {cause: error}, + ) + }> + + + ))} + + ); +} + +function NavbarContentLayout({ + left, + right, +}: { + left: ReactNode; + right: ReactNode; +}) { + return ( +
    +
    {left}
    +
    {right}
    +
    + ); +} + +export default function NavbarContent(): JSX.Element { + const mobileSidebar = useNavbarMobileSidebar(); + + const items = useNavbarItems(); + const [leftItems, rightItems] = splitNavbarItems(items); + + // among the right items, pick items except "Solution", "Learn", "Community" + const rightItemsDropdown = rightItems.filter( + (item) => + item.label == 'Cloud' || + item.label == 'Docs' || + item.label == 'Integrations' + ); + + // pick items without labels + const rightItemsCTA = rightItems.filter( + (item) => + item.label == undefined + ); + + const searchBarItem = items.find((item) => item.type === 'search'); + + return ( + + {!mobileSidebar.disabled && } + + + + } + right={ + // TODO stop hardcoding items? + // Ask the user to add the respective navbar items => more flexible + <> + + + + + + + {!searchBarItem && ( + + + + )} + + } + /> + ); +} \ No newline at end of file diff --git a/docs-website/src/theme/Navbar/Content/styles.module.css b/docs-website/src/theme/Navbar/Content/styles.module.css new file mode 100644 index 0000000000000..e5d6fde1107ca --- /dev/null +++ b/docs-website/src/theme/Navbar/Content/styles.module.css @@ -0,0 +1,8 @@ +/* +Hide color mode toggle in small viewports + */ + @media (max-width: 996px) { + .colorModeToggle { + display: none; + } + } \ No newline at end of file diff --git a/docs-website/src/theme/Navbar/communityCardDropdownContent.js b/docs-website/src/theme/Navbar/communityCardDropdownContent.js new file mode 100644 index 0000000000000..a2d0496959ca7 --- /dev/null +++ b/docs-website/src/theme/Navbar/communityCardDropdownContent.js @@ -0,0 +1,29 @@ +const learCardDropdownContent = [ + { + title: "Join Slack", + iconImage: "/img/icon-join-slack.png", + href: "/slack", + }, + { + title: "Forum", + iconImage: "/img/icon-forum.png", + href: "https://forum.datahubproject.io/", + }, + { + title: "Events", + iconImage: "/img/icon-events.png", + href: "/events", + }, + { + title: "Champions", + iconImage: "/img/icon-champions.png", + href: "/champions", + }, + { + title: "Share Your Journey", + iconImage: "/img/icon-share-your-journey.png", + href: "/customer-stories-survey", + } + ] + +export default learCardDropdownContent \ No newline at end of file diff --git a/docs-website/src/theme/Navbar/learnCardDropdownContent.js b/docs-website/src/theme/Navbar/learnCardDropdownContent.js new file mode 100644 index 0000000000000..cf60e21c5530f --- /dev/null +++ b/docs-website/src/theme/Navbar/learnCardDropdownContent.js @@ -0,0 +1,29 @@ +const learCardDropdownContent = [ + { + title: "Weekly Demo", + iconImage: "/img/icon-join-slack.png", + href: "https://www.acryldata.io/webinars/weekly-live-demo", + }, + { + title: "Use Cases", + iconImage: "/img/icon-forum.png", + href: "/learn", + }, + { + title: "Adoption Stories", + iconImage: "/img/icon-events.png", + href: "/adoption-stories", + }, + { + title: "Blog", + iconImage: "/img/icon-champions.png", + href: "https://blog.datahubproject.io/", + }, + { + title: "Youtube", + iconImage: "/img/icon-share-your-journey.png", + href: "https://www.youtube.com/channel/UC3qFQC5IiwR5fvWEqi_tJ5w", + } + ] + +export default learCardDropdownContent \ No newline at end of file diff --git a/docs-website/static/img/icon-champions.png b/docs-website/static/img/icon-champions.png new file mode 100644 index 0000000000000..4ac2cd895db71 Binary files /dev/null and b/docs-website/static/img/icon-champions.png differ diff --git a/docs-website/static/img/icon-events.png b/docs-website/static/img/icon-events.png new file mode 100644 index 0000000000000..d40d939800e54 Binary files /dev/null and b/docs-website/static/img/icon-events.png differ diff --git a/docs-website/static/img/icon-forum.png b/docs-website/static/img/icon-forum.png new file mode 100644 index 0000000000000..d405b9224cd08 Binary files /dev/null and b/docs-website/static/img/icon-forum.png differ diff --git a/docs-website/static/img/icon-join-slack.png b/docs-website/static/img/icon-join-slack.png new file mode 100644 index 0000000000000..ed4eac95fd316 Binary files /dev/null and b/docs-website/static/img/icon-join-slack.png differ diff --git a/docs-website/static/img/icon-share-your-journey.png b/docs-website/static/img/icon-share-your-journey.png new file mode 100644 index 0000000000000..80d61e50d96d7 Binary files /dev/null and b/docs-website/static/img/icon-share-your-journey.png differ diff --git a/docs-website/static/img/solutions/icon-dropdown-cloud.png b/docs-website/static/img/solutions/icon-dropdown-cloud.png new file mode 100644 index 0000000000000..fe2f25fc6b6a0 Binary files /dev/null and b/docs-website/static/img/solutions/icon-dropdown-cloud.png differ diff --git a/docs-website/static/img/solutions/icon-dropdown-core.png b/docs-website/static/img/solutions/icon-dropdown-core.png new file mode 100644 index 0000000000000..d87017ab6833f Binary files /dev/null and b/docs-website/static/img/solutions/icon-dropdown-core.png differ diff --git a/docs-website/static/img/solutions/icon-dropdown-discovery.png b/docs-website/static/img/solutions/icon-dropdown-discovery.png new file mode 100644 index 0000000000000..5eaff83ea3a3e Binary files /dev/null and b/docs-website/static/img/solutions/icon-dropdown-discovery.png differ diff --git a/docs-website/static/img/solutions/icon-dropdown-governance.png b/docs-website/static/img/solutions/icon-dropdown-governance.png new file mode 100644 index 0000000000000..e31d518450d49 Binary files /dev/null and b/docs-website/static/img/solutions/icon-dropdown-governance.png differ diff --git a/docs-website/static/img/solutions/icon-dropdown-observe.png b/docs-website/static/img/solutions/icon-dropdown-observe.png new file mode 100644 index 0000000000000..e5ca916240ddb Binary files /dev/null and b/docs-website/static/img/solutions/icon-dropdown-observe.png differ