From 38c1105af24e41705823b9c09d0e860fe4e646f8 Mon Sep 17 00:00:00 2001 From: Andrew Sikowitz Date: Wed, 26 Feb 2025 15:21:06 -0800 Subject: [PATCH 1/2] refactor(ui/v2): Update icons and search bars on schema tab, glossary search, domain search --- .../components/Button/Button.stories.tsx | 49 +++--- .../components/Button/Button.tsx | 6 +- .../components/Button/types.ts | 16 +- .../components/Button/utils.ts | 42 ++--- .../components/ButtonIcon/IconButton.tsx | 22 +++ .../components/Drawer/Drawer.tsx | 4 +- .../GraphCard/GraphCard.stories.tsx | 2 +- .../components/Icon/constants.ts | 4 +- .../components/Input/Input.stories.tsx | 5 + .../components/Input/Input.tsx | 2 +- .../components/Input/types.ts | 2 +- .../components/SearchBar/SearchBar.tsx | 11 +- .../components/SearchBar/types.ts | 1 + .../components/Select/AutoCompleteSelect.tsx | 8 +- .../components/Select/BasicSelect.tsx | 6 +- .../components/Select/Nested/NestedSelect.tsx | 2 +- .../components/Select/SimpleSelect.tsx | 6 +- .../src/app/domainV2/DomainSearch.tsx | 49 +++--- .../nestedDomains/ManageDomainsPageV2.tsx | 2 +- .../schema/components/SchemaHeader.tsx | 4 +- .../Dataset/Queries/QueriesTabToolbar.tsx | 5 +- .../Dataset/Relationship/RelationshipsTab.tsx | 5 +- .../tabs/Properties/AddPropertyButton.tsx | 2 +- .../shared/tabs/Properties/TabHeader.tsx | 4 +- .../schema/components/SchemaHeader.tsx | 64 +++----- .../schema/components/SchemaSearchInput.tsx | 145 ++++-------------- .../components/search/InlineListSearch.tsx | 4 +- .../shared/components/styled/TabToolbar.tsx | 2 +- .../shared/tabs/Dataset/Schema/SchemaTab.tsx | 4 +- .../shared/tabs/Lineage/CompactLineageTab.tsx | 6 +- .../shared/tabs/Properties/TabHeader.tsx | 4 +- .../shared/versioning/VersionsDrawer.tsx | 2 +- .../glossaryV2/GlossaryContentProvider.tsx | 2 +- .../src/app/glossaryV2/GlossarySearch.tsx | 36 ++--- .../StructuredProperties.tsx | 9 +- .../src/app/lineage/NodeColumnsHeader.tsx | 5 +- .../app/lineageV2/controls/SearchControl.tsx | 21 ++- .../src/app/search/ViewAllSearchItem.tsx | 4 +- .../search/autoComplete/RecommendedOption.tsx | 4 +- .../src/app/searchV2/ViewAllSearchItem.tsx | 4 +- .../autoComplete/RecommendedOption.tsx | 4 +- 41 files changed, 255 insertions(+), 324 deletions(-) create mode 100644 datahub-web-react/src/alchemy-components/components/ButtonIcon/IconButton.tsx diff --git a/datahub-web-react/src/alchemy-components/components/Button/Button.stories.tsx b/datahub-web-react/src/alchemy-components/components/Button/Button.stories.tsx index 22cd810c246bf..124508de36b03 100644 --- a/datahub-web-react/src/alchemy-components/components/Button/Button.stories.tsx +++ b/datahub-web-react/src/alchemy-components/components/Button/Button.stories.tsx @@ -1,3 +1,6 @@ +import { ButtonVariantValues } from '@components/components/Button/types'; +import { MATERIAL_UI_ICONS, PHOSPHOR_ICONS } from '@components/components/Icon/constants'; +import { SizeValues } from '@components/theme/config'; import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; @@ -33,7 +36,7 @@ const meta = { }, variant: { description: 'The variant of the Button.', - options: ['filled', 'outline', 'text'], + options: Object.values(ButtonVariantValues), table: { defaultValue: { summary: buttonDefaults.variant }, }, @@ -43,7 +46,7 @@ const meta = { }, color: { description: 'The color of the Button.', - options: ['violet', 'green', 'red', 'blue', 'gray'], + options: ['violet', 'green', 'red', 'gray'], table: { defaultValue: { summary: buttonDefaults.color }, }, @@ -53,7 +56,7 @@ const meta = { }, size: { description: 'The size of the Button.', - options: ['sm', 'md', 'lg', 'xl'], + options: Object.values(SizeValues), table: { defaultValue: { summary: buttonDefaults.size }, }, @@ -61,23 +64,14 @@ const meta = { type: 'select', }, }, - iconSize: { - description: 'The optional size of the Icon.', - options: ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'], - table: { - defaultValue: { - summary: 'undefined', - detail: 'The size of the Button will be used as the size of the Icon', - }, - }, - control: { - type: 'select', - }, - }, icon: { description: 'The icon to display in the Button.', type: 'string', options: AVAILABLE_ICONS, + mapping: Object.fromEntries([ + ...MATERIAL_UI_ICONS.map((icon) => [icon, { icon, source: 'material', size: '2xl' }]), + ...PHOSPHOR_ICONS.map((icon) => [icon, { icon, source: 'phosphor', size: '2xl' }]), + ]), table: { defaultValue: { summary: 'undefined' }, }, @@ -143,7 +137,7 @@ const meta = { // Define defaults args: { - children: 'Button Content', + children: 'Button', variant: buttonDefaults.variant, color: buttonDefaults.color, size: buttonDefaults.size, @@ -167,7 +161,7 @@ type Story = StoryObj; // Pass props to this so that it can be customized via the UI props panel export const sandbox: Story = { tags: ['dev'], - render: (props) => , + render: (props) => - - - + + + + + ); export const withIcon = () => ( - - + @@ -209,8 +204,8 @@ export const withIcon = () => ( export const circleShape = () => ( - + ); +} diff --git a/datahub-web-react/src/alchemy-components/components/Drawer/Drawer.tsx b/datahub-web-react/src/alchemy-components/components/Drawer/Drawer.tsx index 1067b95700576..d1c55f6e9c804 100644 --- a/datahub-web-react/src/alchemy-components/components/Drawer/Drawer.tsx +++ b/datahub-web-react/src/alchemy-components/components/Drawer/Drawer.tsx @@ -26,7 +26,7 @@ export const Drawer = ({ {onBack && ( [icon, { icon, source: 'material' }]), + ...PHOSPHOR_ICONS.map((icon) => [icon, { icon, source: 'phosphor' }]), + ]), table: { defaultValue: { summary: 'undefined' }, }, diff --git a/datahub-web-react/src/alchemy-components/components/Input/Input.tsx b/datahub-web-react/src/alchemy-components/components/Input/Input.tsx index 75c199610f81e..3db152d7fd216 100644 --- a/datahub-web-react/src/alchemy-components/components/Input/Input.tsx +++ b/datahub-web-react/src/alchemy-components/components/Input/Input.tsx @@ -76,7 +76,7 @@ export const Input = ({ )} - {icon && } + {icon && } setValue?.(e.target.value)} diff --git a/datahub-web-react/src/alchemy-components/components/Input/types.ts b/datahub-web-react/src/alchemy-components/components/Input/types.ts index 8ec3c8ed3e358..28e5429563d0c 100644 --- a/datahub-web-react/src/alchemy-components/components/Input/types.ts +++ b/datahub-web-react/src/alchemy-components/components/Input/types.ts @@ -8,7 +8,7 @@ export interface InputProps extends InputHTMLAttributes { setValue?: React.Dispatch>; label: string; placeholder?: string; - icon?: { name: IconNames; source: IconSource; variant?: MaterialIconVariant }; + icon?: { icon: IconNames; source: IconSource; variant?: MaterialIconVariant }; error?: string; warning?: string; isSuccess?: boolean; diff --git a/datahub-web-react/src/alchemy-components/components/SearchBar/SearchBar.tsx b/datahub-web-react/src/alchemy-components/components/SearchBar/SearchBar.tsx index 8e9eea5eb907c..ec78f6db7021b 100644 --- a/datahub-web-react/src/alchemy-components/components/SearchBar/SearchBar.tsx +++ b/datahub-web-react/src/alchemy-components/components/SearchBar/SearchBar.tsx @@ -1,4 +1,5 @@ -import { SearchOutlined } from '@ant-design/icons'; +import { Icon } from '@src/alchemy-components'; +import { InputProps } from 'antd'; import React from 'react'; import { StyledSearchBar } from './components'; import { SearchBarProps } from './types'; @@ -6,7 +7,7 @@ import { SearchBarProps } from './types'; export const searchBarDefaults: SearchBarProps = { placeholder: 'Search...', value: '', - width: '272px', + width: '100%', allowClear: true, }; @@ -16,15 +17,17 @@ export const SearchBar = ({ width = searchBarDefaults.width, allowClear = searchBarDefaults.allowClear, onChange, -}: SearchBarProps) => { + ...props +}: SearchBarProps & Omit) => { return ( onChange?.(e.target.value)} value={value} - prefix={} + prefix={} allowClear={allowClear} $width={width} + {...props} /> ); }; diff --git a/datahub-web-react/src/alchemy-components/components/SearchBar/types.ts b/datahub-web-react/src/alchemy-components/components/SearchBar/types.ts index 04ac218dc2cc6..74f0eca340519 100644 --- a/datahub-web-react/src/alchemy-components/components/SearchBar/types.ts +++ b/datahub-web-react/src/alchemy-components/components/SearchBar/types.ts @@ -4,4 +4,5 @@ export interface SearchBarProps { width?: string; onChange?: (value: string) => void; allowClear?: boolean; + disabled?: boolean; } diff --git a/datahub-web-react/src/alchemy-components/components/Select/AutoCompleteSelect.tsx b/datahub-web-react/src/alchemy-components/components/Select/AutoCompleteSelect.tsx index ed16e42dbc650..2f7f67df65910 100644 --- a/datahub-web-react/src/alchemy-components/components/Select/AutoCompleteSelect.tsx +++ b/datahub-web-react/src/alchemy-components/components/Select/AutoCompleteSelect.tsx @@ -173,7 +173,7 @@ export default function AutoCompleteSelect({ { @@ -218,7 +218,11 @@ function SelectActionButtons({ return ( {showClear && selectedValues.length > 0 && !isDisabled && !isReadOnly && ( - + )} diff --git a/datahub-web-react/src/alchemy-components/components/Select/BasicSelect.tsx b/datahub-web-react/src/alchemy-components/components/Select/BasicSelect.tsx index c4b6404cc0f54..09cd4a51e8fb2 100644 --- a/datahub-web-react/src/alchemy-components/components/Select/BasicSelect.tsx +++ b/datahub-web-react/src/alchemy-components/components/Select/BasicSelect.tsx @@ -37,7 +37,11 @@ const SelectActionButtons = ({ return ( {showClear && selectedValues.length > 0 && !isDisabled && !isReadOnly && ( - + )} diff --git a/datahub-web-react/src/alchemy-components/components/Select/Nested/NestedSelect.tsx b/datahub-web-react/src/alchemy-components/components/Select/Nested/NestedSelect.tsx index 16312d2cf6e8a..a10b482679956 100644 --- a/datahub-web-react/src/alchemy-components/components/Select/Nested/NestedSelect.tsx +++ b/datahub-web-react/src/alchemy-components/components/Select/Nested/NestedSelect.tsx @@ -99,7 +99,7 @@ const SelectActionButtons = ({ {!showCount && !!selectedOptions.length && !isDisabled && !isReadOnly && ( {showClear && selectedValues.length > 0 && !isDisabled && !isReadOnly && ( - + )} diff --git a/datahub-web-react/src/app/domainV2/DomainSearch.tsx b/datahub-web-react/src/app/domainV2/DomainSearch.tsx index 73552060cb5e8..824043ee9ce96 100644 --- a/datahub-web-react/src/app/domainV2/DomainSearch.tsx +++ b/datahub-web-react/src/app/domainV2/DomainSearch.tsx @@ -1,13 +1,14 @@ -import React, { useRef, useState } from 'react'; +import { SearchBar } from '@components'; +import React, { useState } from 'react'; import { LoadingOutlined, SearchOutlined } from '@ant-design/icons'; +import { useDebounce } from 'react-use'; import styled from 'styled-components/macro'; import { useGetAutoCompleteResultsQuery } from '../../graphql/search.generated'; import { EntityType } from '../../types.generated'; -import { SearchBar } from '../searchV2/SearchBar'; import ClickOutside from '../shared/ClickOutside'; import { useEntityRegistry } from '../useEntityRegistry'; import DomainSearchResultItem from './DomainSearchResultItem'; -import { ANTD_GRAY, REDESIGN_COLORS } from '../entityV2/shared/constants'; +import { REDESIGN_COLORS } from '../entityV2/shared/constants'; const DomainSearchWrapper = styled.div` flex-shrink: 0; @@ -35,6 +36,10 @@ const LoadingWrapper = styled(ResultsWrapper)` font-size: 16px; `; +const InputWrapper = styled.div` + padding: 12px; +`; + const SearchIcon = styled(SearchOutlined)` color: ${REDESIGN_COLORS.TEXT_HEADING_SUB_LINK}; padding: 16px; @@ -48,9 +53,12 @@ type Props = { }; function DomainSearch({ isCollapsed, unhideSidebar }: Props) { + const [searchInput, setSearchInput] = useState(''); const [query, setQuery] = useState(''); const [isSearchBarFocused, setIsSearchBarFocused] = useState(false); const entityRegistry = useEntityRegistry(); + + useDebounce(() => setQuery(searchInput), 200, [searchInput]); const { data, loading } = useGetAutoCompleteResultsQuery({ variables: { input: { @@ -62,14 +70,6 @@ function DomainSearch({ isCollapsed, unhideSidebar }: Props) { }); const entities = data?.autoComplete?.entities || []; - const timerRef = useRef(-1); - - const handleQueryChange = (q: string) => { - window.clearTimeout(timerRef.current); - timerRef.current = window.setTimeout(() => { - setQuery(q); - }, 250); - }; return ( @@ -77,25 +77,14 @@ function DomainSearch({ isCollapsed, unhideSidebar }: Props) { ) : ( setIsSearchBarFocused(false)}> - null} - onQueryChange={(q) => handleQueryChange(q)} - entityRegistry={entityRegistry} - onFocus={() => setIsSearchBarFocused(true)} - /> + + setIsSearchBarFocused(true)} + /> + {loading && isSearchBarFocused && ( diff --git a/datahub-web-react/src/app/domainV2/nestedDomains/ManageDomainsPageV2.tsx b/datahub-web-react/src/app/domainV2/nestedDomains/ManageDomainsPageV2.tsx index 9735136972d12..62a8f9b1154b0 100644 --- a/datahub-web-react/src/app/domainV2/nestedDomains/ManageDomainsPageV2.tsx +++ b/datahub-web-react/src/app/domainV2/nestedDomains/ManageDomainsPageV2.tsx @@ -49,7 +49,7 @@ export default function ManageDomainsPageV2() { id={DOMAINS_CREATE_DOMAIN_ID} onClick={() => setIsCreatingDomain(true)} data-testid="domains-new-domain-button" - icon="Add" + icon={{ icon: 'Add', source: 'material' }} > Create diff --git a/datahub-web-react/src/app/entity/dataset/profile/schema/components/SchemaHeader.tsx b/datahub-web-react/src/app/entity/dataset/profile/schema/components/SchemaHeader.tsx index 2fc8fc11cd1b2..e5a6791557021 100644 --- a/datahub-web-react/src/app/entity/dataset/profile/schema/components/SchemaHeader.tsx +++ b/datahub-web-react/src/app/entity/dataset/profile/schema/components/SchemaHeader.tsx @@ -1,3 +1,4 @@ +import { Icon } from '@components'; import React from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import { Button, Input, Popover, Select, Tooltip, Typography } from 'antd'; @@ -7,7 +8,6 @@ import { CaretDownOutlined, FileTextOutlined, QuestionCircleOutlined, - SearchOutlined, TableOutlined, } from '@ant-design/icons'; import styled from 'styled-components/macro'; @@ -245,7 +245,7 @@ export default function SchemaHeader({ placeholder="Search in schema..." onChange={debouncedSetFilterText} allowClear - prefix={} + prefix={} /> )} diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Queries/QueriesTabToolbar.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Queries/QueriesTabToolbar.tsx index 85fb011bc8e30..7dfe3c2289466 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Queries/QueriesTabToolbar.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Queries/QueriesTabToolbar.tsx @@ -1,5 +1,6 @@ +import { Icon } from '@components'; import { Button, Input, Tooltip } from 'antd'; -import { PlusOutlined, SearchOutlined } from '@ant-design/icons'; +import { PlusOutlined } from '@ant-design/icons'; import styled from 'styled-components'; import React from 'react'; import TabToolbar from '../../../components/styled/TabToolbar'; @@ -31,7 +32,7 @@ export default function QueriesTabToolbar({ addQueryDisabled, onAddQuery, onChan placeholder="Search in queries..." onChange={onChangeSearch} allowClear - prefix={} + prefix={} data-testid="search-query-input" /> diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Relationship/RelationshipsTab.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Relationship/RelationshipsTab.tsx index c44bddc2c30d1..84ed707753e31 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Relationship/RelationshipsTab.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Relationship/RelationshipsTab.tsx @@ -1,7 +1,8 @@ +import { Icon } from '@components'; import { Button, Card, Divider, Empty, Input, Modal, Pagination } from 'antd'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; -import { ExclamationCircleFilled, LoadingOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons'; +import { ExclamationCircleFilled, LoadingOutlined, PlusOutlined } from '@ant-design/icons'; import { useBaseEntity } from '../../../EntityContext'; import './RelationshipsTab.less'; import { EntityType, ErModelRelationship } from '../../../../../../types.generated'; @@ -243,7 +244,7 @@ export const RelationshipsTab = () => { onChange={(e) => setFilterText(e.target.value)} allowClear autoFocus - prefix={} + prefix={} /> )} diff --git a/datahub-web-react/src/app/lineageV2/controls/SearchControl.tsx b/datahub-web-react/src/app/lineageV2/controls/SearchControl.tsx index 5ce3d5b1ffe2e..3af11d043ed9e 100644 --- a/datahub-web-react/src/app/lineageV2/controls/SearchControl.tsx +++ b/datahub-web-react/src/app/lineageV2/controls/SearchControl.tsx @@ -93,9 +93,24 @@ export default function SearchControl() { {matchedNodes.length ? searchIndex + 1 : 0} / {matchedNodes.length} - - ); -} diff --git a/datahub-web-react/src/alchemy-components/components/Input/Input.tsx b/datahub-web-react/src/alchemy-components/components/Input/Input.tsx index 3db152d7fd216..138476f2ad606 100644 --- a/datahub-web-react/src/alchemy-components/components/Input/Input.tsx +++ b/datahub-web-react/src/alchemy-components/components/Input/Input.tsx @@ -76,7 +76,7 @@ export const Input = ({ )} - {icon && } + {icon && } setValue?.(e.target.value)} diff --git a/datahub-web-react/src/alchemy-components/components/Input/types.ts b/datahub-web-react/src/alchemy-components/components/Input/types.ts index 28e5429563d0c..a750ce675637e 100644 --- a/datahub-web-react/src/alchemy-components/components/Input/types.ts +++ b/datahub-web-react/src/alchemy-components/components/Input/types.ts @@ -1,14 +1,12 @@ -import { IconSource } from '@components/components/Icon/types'; +import { IconProps } from '@components/components/Icon/types'; import React, { InputHTMLAttributes } from 'react'; -import { IconNames, MaterialIconVariant } from '../Icon'; - export interface InputProps extends InputHTMLAttributes { value?: string | number | readonly string[] | undefined; setValue?: React.Dispatch>; label: string; placeholder?: string; - icon?: { icon: IconNames; source: IconSource; variant?: MaterialIconVariant }; + icon?: IconProps; error?: string; warning?: string; isSuccess?: boolean;