From d95a4d300f6ddd386f3e0710ce9cdfde90dfbcff Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Thu, 13 May 2021 18:54:09 -0300 Subject: [PATCH] refactor: Bootstrap to AntD - NavDropdown (#14557) --- .../src/components/EditableTitle/index.tsx | 9 +- .../components/Menu/LanguagePicker.test.tsx | 13 +- .../src/components/Menu/LanguagePicker.tsx | 105 ++++++--- .../src/components/Menu/Menu.test.tsx | 8 +- .../src/components/Menu/Menu.tsx | 6 +- .../src/components/Menu/MenuRight.tsx | 214 +++++++++--------- .../src/components/NavDropdown/index.tsx | 63 ------ .../DashboardBuilder/DashboardBuilder.tsx | 7 +- 8 files changed, 206 insertions(+), 219 deletions(-) delete mode 100644 superset-frontend/src/components/NavDropdown/index.tsx diff --git a/superset-frontend/src/components/EditableTitle/index.tsx b/superset-frontend/src/components/EditableTitle/index.tsx index f1685daca48f..ec2245b05ef8 100644 --- a/superset-frontend/src/components/EditableTitle/index.tsx +++ b/superset-frontend/src/components/EditableTitle/index.tsx @@ -110,12 +110,9 @@ export default function EditableTitle({ } } - // this entire method exists to support using EditableTitle as the title of a - // react-bootstrap Tab, as a workaround for this line in react-bootstrap https://goo.gl/ZVLmv4 - // - // tl;dr when a Tab EditableTitle is being edited, typically the Tab it's within has been - // clicked and is focused/active. for accessibility, when focused the Tab intercepts - // the ' ' key (among others, including all arrows) and onChange() doesn't fire. somehow + // tl;dr when a EditableTitle is being edited, typically the Tab that wraps it has been + // clicked and is focused/active. For accessibility, when the focused tab anchor intercepts + // the ' ' key (among others, including all arrows) the onChange() doesn't fire. Somehow // keydown is still called so we can detect this and manually add a ' ' to the current title function handleKeyDown(event: any) { if (event.key === ' ') { diff --git a/superset-frontend/src/components/Menu/LanguagePicker.test.tsx b/superset-frontend/src/components/Menu/LanguagePicker.test.tsx index ad494d620ca8..c82cd5069827 100644 --- a/superset-frontend/src/components/Menu/LanguagePicker.test.tsx +++ b/superset-frontend/src/components/Menu/LanguagePicker.test.tsx @@ -18,6 +18,7 @@ */ import React from 'react'; import { render, screen } from 'spec/helpers/testing-library'; +import userEvent from '@testing-library/user-event'; import LanguagePicker from './LanguagePicker'; const mockedProps = { @@ -41,14 +42,14 @@ test('should render', () => { expect(container).toBeInTheDocument(); }); -test('should render the button', () => { +test('should render the combobox', () => { render(); - const button = screen.getByRole('button'); - expect(button).toHaveAttribute('href', '#'); + expect(screen.getByRole('combobox')).toBeInTheDocument(); }); -test('should render the menuitem', () => { +test('should render the items', async () => { render(); - const menuitem = screen.getByRole('menuitem'); - expect(menuitem).toHaveTextContent('Italian'); + userEvent.click(screen.getByRole('combobox')); + expect(await screen.findByText('English')).toBeInTheDocument(); + expect(await screen.findByText('Italian')).toBeInTheDocument(); }); diff --git a/superset-frontend/src/components/Menu/LanguagePicker.tsx b/superset-frontend/src/components/Menu/LanguagePicker.tsx index 63f6e6bae1bf..ec271d064a94 100644 --- a/superset-frontend/src/components/Menu/LanguagePicker.tsx +++ b/superset-frontend/src/components/Menu/LanguagePicker.tsx @@ -17,8 +17,9 @@ * under the License. */ import React, { useState } from 'react'; -import { Menu } from 'src/common/components'; -import NavDropdown from 'src/components/NavDropdown'; +import { Select } from 'src/common/components'; +import { styled, useTheme } from '@superset-ui/core'; +import Icons from 'src/components/Icons'; export interface Languages { [key: string]: { @@ -33,43 +34,81 @@ interface LanguagePickerProps { languages: Languages; } +const dropdownWidth = 150; + +const StyledLabel = styled.div` + display: flex; + align-items: center; + + & i { + margin-right: ${({ theme }) => theme.gridUnit}px; + } + + & span { + display: block; + width: ${dropdownWidth}px; + word-wrap: break-word; + white-space: normal; + } +`; + +const StyledFlag = styled.div` + margin-top: 2px; +`; + +const StyledIcon = styled(Icons.TriangleDown)` + ${({ theme }) => ` + margin-top: -${theme.gridUnit}px; + margin-left: -${theme.gridUnit * 2}px; + `} +`; + export default function LanguagePicker({ locale, languages, }: LanguagePickerProps) { - const [dropdownOpen, setDropdownOpen] = useState(false); + const theme = useTheme(); + const [open, setOpen] = useState(false); + + const options = Object.keys(languages).map(langKey => ({ + label: ( + + {' '} + {languages[langKey].name} + + ), + value: langKey, + flag: ( + + + + ), + })); return ( - setDropdownOpen(true)} - onMouseLeave={() => setDropdownOpen(false)} - onToggle={value => setDropdownOpen(value)} - open={dropdownOpen} - id="locale-dropdown" - title={ - - - +