From 8218e3c9aaedc4645561185c6bb823df4a816ef0 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 18 Oct 2023 20:40:20 -0700 Subject: [PATCH 1/9] [misc cleanup] remove unnecessary functions in favor of memoized JSX --- .../guide_page/guide_page_header.tsx | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index 09ac1a87491..2e0ebca1ac6 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useMemo } from 'react'; import { EuiBadge, @@ -32,15 +32,15 @@ export const GuidePageHeader: React.FunctionComponent = ({ }) => { const isMobileSize = useIsWithinBreakpoints(['xs', 's']); - function renderLogo() { + const logo = useMemo(() => { return ( Elastic UI ); - } + }, []); - function renderVersion() { + const version = useMemo(() => { const isLocalDev = window.location.host.includes('803'); return ( @@ -52,9 +52,9 @@ export const GuidePageHeader: React.FunctionComponent = ({ {isLocalDev ? 'Local' : `v${pkg.version}`} ); - } + }, []); - function renderGithub() { + const github = useMemo(() => { const href = 'https://github.com/elastic/eui'; const label = 'EUI GitHub repo'; return isMobileSize ? ( @@ -68,9 +68,9 @@ export const GuidePageHeader: React.FunctionComponent = ({ ); - } + }, [isMobileSize]); - function renderCodeSandbox() { + const codesandbox = useMemo(() => { const label = 'Codesandbox'; return isMobileSize ? ( @@ -87,11 +87,11 @@ export const GuidePageHeader: React.FunctionComponent = ({ ); - } + }, [isMobileSize]); const [mobilePopoverIsOpen, setMobilePopoverIsOpen] = useState(false); - function renderMobileMenu() { + const mobileMenu = useMemo(() => { const button = ( = ({ gutterSize="none" responsive={false} > - {renderGithub()} + {github} - {renderCodeSandbox()} + {codesandbox} ); - } + }, [mobilePopoverIsOpen, codesandbox, github]); const rightSideItems = isMobileSize ? [ @@ -129,16 +129,16 @@ export const GuidePageHeader: React.FunctionComponent = ({ onToggleLocale={onToggleLocale} selectedLocale={selectedLocale} />, - renderMobileMenu(), + mobileMenu, ] : [ , - renderGithub(), + github, , - renderCodeSandbox(), + codesandbox, ]; return ( @@ -147,7 +147,7 @@ export const GuidePageHeader: React.FunctionComponent = ({ position="fixed" theme="dark" sections={[ - { items: [renderLogo(), renderVersion()] }, + { items: [logo, version] }, { items: rightSideItems }, ]} /> From 318add1058f9221b92f7b5864eeaa6bd89008937 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 18 Oct 2023 20:47:29 -0700 Subject: [PATCH 2/9] Add popover to version badge with list of versions and links --- .../guide_page/guide_page_header.tsx | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index 2e0ebca1ac6..ca2a17c6f0f 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -9,6 +9,8 @@ import { EuiHeaderLogo, EuiHeaderSectionItemButton, EuiIcon, + EuiListGroup, + EuiListGroupItem, EuiPopover, EuiToolTip, } from '../../../../src/components'; @@ -20,6 +22,7 @@ import logoEUI from '../../images/logo-eui.svg'; import { GuideThemeSelector, GuideFigmaLink } from '../guide_theme_selector'; const pkg = require('../../../../package.json'); +const euiVersions = ['TODO']; // Generate an array of versions with valid deploy URLs that gets updated every time the release script runs export type GuidePageHeaderProps = { onToggleLocale: () => {}; @@ -40,19 +43,56 @@ export const GuidePageHeader: React.FunctionComponent = ({ ); }, []); - const version = useMemo(() => { + const [isVersionPopoverOpen, setIsVersionPopoverOpen] = useState(false); + const versionBadge = useMemo(() => { const isLocalDev = window.location.host.includes('803'); - return ( setIsVersionPopoverOpen((isOpen) => !isOpen)} + onClickAriaLabel={`Version ${pkg.version}. Click to switch versions`} color={isLocalDev ? 'accent' : 'default'} > {isLocalDev ? 'Local' : `v${pkg.version}`} ); }, []); + const versionSwitcher = useMemo(() => { + return ( + setIsVersionPopoverOpen(false)} + button={versionBadge} + repositionOnScroll + panelPaddingSize="xs" + > + + {euiVersions.map((version: string) => ( + + ))} + + + ); + }, [isVersionPopoverOpen, versionBadge]); const github = useMemo(() => { const href = 'https://github.com/elastic/eui'; @@ -147,7 +187,7 @@ export const GuidePageHeader: React.FunctionComponent = ({ position="fixed" theme="dark" sections={[ - { items: [logo, version] }, + { items: [logo, versionSwitcher] }, { items: rightSideItems }, ]} /> From 200992433faeade2e30b31e4dd7044dd27aced22 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 18 Oct 2023 20:49:18 -0700 Subject: [PATCH 3/9] Set up file with all deployed versions & release script automation --- scripts/release.js | 4 + scripts/tests/update-versions-log.test.js | 64 ++++++ scripts/update-versions-log.js | 40 ++++ .../guide_page/guide_page_header.tsx | 2 +- .../src/components/guide_page/versions.json | 192 ++++++++++++++++++ 5 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 scripts/tests/update-versions-log.test.js create mode 100644 scripts/update-versions-log.js create mode 100644 src-docs/src/components/guide_page/versions.json diff --git a/scripts/release.js b/scripts/release.js index 49fc4f5a014..82cfdcee00c 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -11,6 +11,7 @@ const { collateChangelogFiles, updateChangelog, } = require('./update-changelog'); +const updateDocsVersionSwitcher = require('./update-versions-log'); const TYPE_MAJOR = 0; const TYPE_MINOR = 1; @@ -73,6 +74,9 @@ if (args.dry_run) { // Update CHANGELOG.md updateChangelog(changelog, versionTarget); + // Update version switcher data + updateDocsVersionSwitcher(versionTarget); + // update package.json & package-lock.json version, git commit, git tag execSync(`npm version ${versionTarget}`, execOptions); } diff --git a/scripts/tests/update-versions-log.test.js b/scripts/tests/update-versions-log.test.js new file mode 100644 index 00000000000..d32978e6091 --- /dev/null +++ b/scripts/tests/update-versions-log.test.js @@ -0,0 +1,64 @@ +import updateDocsVersionSwitcher from '../update-versions-log'; + +// Mock files +jest.mock('fs', () => ({ + readFileSync: jest.fn(() => ''), + writeFileSync: jest.fn(), +})); +const fs = require('fs'); +jest.mock('child_process', () => ({ + execSync: jest.fn(), +})); +const { execSync } = require('child_process'); + +describe('updateDocsVersionSwitcher', () => { + const mockInput = `{ + "euiVersions": [ + "3.0.0", + "2.0.0", + "1.0.0" + ] +}`; + const expectedOutput = `{ + "euiVersions": [ + "4.0.0", + "3.0.0", + "2.0.0", + "1.0.0" + ] +}`; + + beforeEach(() => jest.clearAllMocks()); + + it('appends a new version to the top of the array list', () => { + fs.readFileSync.mockReturnValue(mockInput); + + updateDocsVersionSwitcher('4.0.0'); + + expect(fs.writeFileSync).toHaveBeenCalledWith( + expect.stringContaining('versions.json'), + expectedOutput + ); + expect(execSync).toHaveBeenCalledWith( + expect.stringMatching(/^git add .+versions\.json$/) + ); + }); + + it('throws an error if the version is missing', () => { + expect(() => updateDocsVersionSwitcher('')).toThrow('Missing version'); + }); + + it('throws an error the version is already at the start of the versions array', () => { + fs.readFileSync.mockReturnValue(mockInput); + expect(() => updateDocsVersionSwitcher('3.0.0')).toThrow( + 'Current version has already been logged' + ); + }); + + it('throws an error if the JSON data is somehow malformed', () => { + fs.readFileSync.mockReturnValue('{}'); + expect(() => updateDocsVersionSwitcher('4.0.0')).toThrow( + 'Invalid JSON data' + ); + }); +}); diff --git a/scripts/update-versions-log.js b/scripts/update-versions-log.js new file mode 100644 index 00000000000..13f9a213a6d --- /dev/null +++ b/scripts/update-versions-log.js @@ -0,0 +1,40 @@ +const path = require('path'); +const fs = require('fs'); +const { execSync } = require('child_process'); + +const versionsLogFile = path.resolve( + __dirname, + '../src-docs/src/components/guide_page/versions.json' +); + +/** + * Writes to the above `versions.json` file (which is what the docs version switcher + * uses to generate its list of versions) with the latest release + * + * To test locally, run `node -e "require('./scripts/update-versions-log')('vX.Y.Z')"` + */ +const updateDocsVersionSwitcher = (versionToAdd, file = versionsLogFile) => { + if (!versionToAdd) { + throw new Error('Missing version'); + } + + let fileString = fs.readFileSync(file).toString(); + const split = `"euiVersions": [`; + const array = fileString.split(split); + + if (array.length <= 1) { + throw new Error(`Invalid JSON data - missing ${split}`); + } + if (array[1].trimStart().startsWith(`"${versionToAdd}`)) { + throw new Error('Current version has already been logged'); + } + + // Prepend the new version and re-form the file string + array[1] = `\n "${versionToAdd}",` + array[1]; + const updatedFileString = array.join(split); + + fs.writeFileSync(file, updatedFileString); + execSync(`git add ${file}`); +}; + +module.exports = updateDocsVersionSwitcher; diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index ca2a17c6f0f..6c166b65d63 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -22,7 +22,7 @@ import logoEUI from '../../images/logo-eui.svg'; import { GuideThemeSelector, GuideFigmaLink } from '../guide_theme_selector'; const pkg = require('../../../../package.json'); -const euiVersions = ['TODO']; // Generate an array of versions with valid deploy URLs that gets updated every time the release script runs +const { euiVersions } = require('./versions.json'); export type GuidePageHeaderProps = { onToggleLocale: () => {}; diff --git a/src-docs/src/components/guide_page/versions.json b/src-docs/src/components/guide_page/versions.json new file mode 100644 index 00000000000..b9ae343e267 --- /dev/null +++ b/src-docs/src/components/guide_page/versions.json @@ -0,0 +1,192 @@ +{ + "euiVersions": [ + "89.1.0", + "89.0.0", + "88.5.4", + "88.5.3", + "88.5.2", + "88.5.1", + "88.5.0", + "88.4.0", + "88.3.0", + "88.2.0", + "88.1.0", + "88.0.0", + "87.2.0", + "87.1.0", + "87.0.0", + "86.0.0", + "85.1.0", + "85.0.0", + "84.0.0", + "83.1.0", + "83.0.0", + "82.2.0", + "82.1.0", + "82.0.0", + "81.3.0", + "81.2.0", + "81.1.0", + "81.0.0", + "80.0.0", + "79.0.1", + "79.0.0", + "78.0.0", + "77.2.0", + "77.0.0", + "76.4.0", + "76.3.0", + "76.2.0", + "76.1.0", + "76.0.1", + "76.0.0", + "75.1.1", + "75.1.0", + "75.0.0", + "74.1.0", + "74.0.0", + "73.0.0", + "72.2.0", + "72.1.0", + "72.0.0", + "71.1.0", + "71.0.0", + "70.4.0", + "70.3.0", + "70.2.0", + "70.1.0", + "70.0.0", + "69.0.0", + "68.0.0", + "67.1.1", + "67.1.0", + "67.0.0", + "66.0.0", + "65.0.2", + "65.0.1", + "65.0.0", + "64.0.1", + "64.0.0", + "63.0.0", + "62.2.0", + "62.1.0", + "62.0.1", + "62.0.0", + "61.0.0", + "60.3.0", + "60.2.0", + "60.1.2", + "60.1.1", + "60.1.0", + "60.0.0", + "59.1.0", + "59.0.1", + "59.0.0", + "58.1.1", + "58.1.0", + "58.0.0", + "57.0.0", + "56.0.0", + "55.1.0", + "55.0.1", + "55.0.0", + "54.1.0", + "54.0.0", + "53.0.1", + "53.0.0", + "52.2.0", + "52.1.0", + "52.0.0", + "51.1.0", + "51.0.0", + "49.0.0", + "48.1.0", + "47.0.0", + "46.2.0", + "46.1.0", + "46.0.0", + "45.0.0", + "43.0.0", + "42.1.0", + "42.0.0", + "41.4.0", + "41.3.0", + "41.2.0", + "41.2.0", + "41.1.0", + "41.0.0", + "40.1.0", + "40.0.0", + "39.1.0", + "39.0.0", + "38.2.0", + "38.1.0", + "38.0.0", + "37.7.0", + "37.6.2", + "37.6.0", + "37.5.0", + "37.4.0", + "37.3.1", + "37.3.0", + "37.2.0", + "37.1.0", + "37.0.0", + "36.1.0", + "36.0.0", + "35.1.0", + "35.0.0", + "34.6.0", + "34.5.2", + "34.5.1", + "34.5.0", + "34.4.0", + "34.3.0", + "34.2.0", + "34.1.0", + "34.0.0", + "33.0.0", + "32.2.0", + "32.1.0", + "32.0.4", + "32.0.3", + "32.0.2", + "32.0.1", + "32.0.0", + "31.12.0", + "31.11.0", + "31.10.0", + "31.9.0", + "31.8.0", + "31.7.0", + "31.6.0", + "31.5.0", + "31.4.0", + "31.3.0", + "31.2.0", + "31.1.0", + "31.0.0", + "30.6.0", + "30.5.0", + "30.4.0", + "30.3.0", + "30.2.0", + "30.1.0", + "29.4.0", + "27.0.0", + "26.3.0", + "26.2.0", + "26.1.0", + "26.0.0", + "25.0.0", + "24.1.0", + "24.0.0", + "23.2.0", + "23.1.0", + "23.0.0", + "22.6.0", + "21.0.0", + "20.0.0", + "19.0.0" + ] +} From 07460c4f90fccd1bee298537032d5e1ce41d94ba Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 18 Oct 2023 20:57:52 -0700 Subject: [PATCH 4/9] Virtualize version switcher list - popover is incredibly slow to load otherwise :') - this requires passing the top level `style` prop to the `
  • ` element (was previously going to the inner content) --- .../guide_page/guide_page_header.tsx | 54 ++++++++++--------- .../list_group_item.test.tsx.snap | 2 +- .../list_group/list_group_item.test.tsx | 9 +--- src/components/list_group/list_group_item.tsx | 5 +- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index 6c166b65d63..a5934335a9a 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -1,4 +1,5 @@ import React, { useState, useMemo } from 'react'; +import { FixedSizeList } from 'react-window'; import { EuiBadge, @@ -9,7 +10,6 @@ import { EuiHeaderLogo, EuiHeaderSectionItemButton, EuiIcon, - EuiListGroup, EuiListGroupItem, EuiPopover, EuiToolTip, @@ -65,31 +65,37 @@ export const GuidePageHeader: React.FunctionComponent = ({ repositionOnScroll panelPaddingSize="xs" > - - {euiVersions.map((version: string) => ( - - ))} - + {({ index, style }) => { + const version = euiVersions[index]; + return ( + + ); + }} + ); }, [isVersionPopoverOpen, versionBadge]); diff --git a/src/components/list_group/__snapshots__/list_group_item.test.tsx.snap b/src/components/list_group/__snapshots__/list_group_item.test.tsx.snap index 8c9b127f0a2..9be40de8636 100644 --- a/src/components/list_group/__snapshots__/list_group_item.test.tsx.snap +++ b/src/components/list_group/__snapshots__/list_group_item.test.tsx.snap @@ -339,10 +339,10 @@ exports[`EuiListGroupItem props size xs is rendered 1`] = ` exports[`EuiListGroupItem props style is rendered 1`] = `
  • { - shouldRenderCustomStyles(, { - skip: { style: true }, - }); - // the styles end up on the inner child - shouldRenderCustomStyles(, { - targetSelector: '.euiListGroupItem__text', - skip: { className: true, css: true }, - }); + shouldRenderCustomStyles(); shouldRenderCustomStyles( = ({ rel, className, css: customCss, + style, iconType, icon, iconProps, @@ -343,7 +344,7 @@ export const EuiListGroupItem: FunctionComponent = ({ }; itemContent = ( -
  • +
  • = ({ ); } else { itemContent = ( -
  • +
  • {itemContent} {extraActionNode}
  • From 0a212ac8ac0ab9186b6c5596c11aa77d13bbba61 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 18 Oct 2023 21:11:41 -0700 Subject: [PATCH 5/9] [EuiListGroupItem][opinionated] remove hover/focus transform on extra action button --- .../list_group/list_group_item_extra_action.styles.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/list_group/list_group_item_extra_action.styles.ts b/src/components/list_group/list_group_item_extra_action.styles.ts index ead41d82ee6..e4493b0941b 100644 --- a/src/components/list_group/list_group_item_extra_action.styles.ts +++ b/src/components/list_group/list_group_item_extra_action.styles.ts @@ -21,6 +21,12 @@ export const euiListGroupItemExtraActionStyles = ({ ${euiCanAnimate} { transition: opacity ${euiTheme.animation.fast}; + + /* Unset default EuiButtonIcon animation - extra & used for specificy override */ + &&:hover, + &&:focus { + transform: translateY(0); + } } `, hoverStyles: css` From 6a523849df309d204a70b19506bff5612f718701 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 18 Oct 2023 21:31:45 -0700 Subject: [PATCH 6/9] Fix text truncation/available width on webkit browsers - for some reason they're rendering a full scrollbar and cutting into the item width when FF doesn't --- src-docs/src/components/guide_page/guide_page_header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index a5934335a9a..70cfddecc25 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -70,7 +70,7 @@ export const GuidePageHeader: React.FunctionComponent = ({ itemCount={euiVersions.length} itemSize={24} height={200} - width="100%" + width={120} innerElementType="ul" > {({ index, style }) => { From 4cb0fba599e76509a39a7274c6411bc5aa2d5df9 Mon Sep 17 00:00:00 2001 From: Cee Chen <549407+cee-chen@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:17:48 -0700 Subject: [PATCH 7/9] [PR feedback] SR UX Co-authored-by: Trevor Pierce <1Copenut@users.noreply.github.com> --- src-docs/src/components/guide_page/guide_page_header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index 70cfddecc25..bff3e76f78c 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -82,7 +82,7 @@ export const GuidePageHeader: React.FunctionComponent = ({ label={`v${version}`} href={`https://eui.elastic.co/v${version}/`} extraAction={{ - 'aria-label': 'View release', + 'aria-label': `View release notes for ${version}`, title: 'View release', iconType: 'package', iconSize: 's', From b9bb7718ed89d92c8013e76314813be6d005922e Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Thu, 19 Oct 2023 10:42:04 -0700 Subject: [PATCH 8/9] [PR feedback] Improve SR UX for versions + improve variable names --- .../guide_page/guide_page_header.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src-docs/src/components/guide_page/guide_page_header.tsx b/src-docs/src/components/guide_page/guide_page_header.tsx index bff3e76f78c..5db702daf22 100644 --- a/src-docs/src/components/guide_page/guide_page_header.tsx +++ b/src-docs/src/components/guide_page/guide_page_header.tsx @@ -21,8 +21,11 @@ import { CodeSandboxLink } from '../../components/codesandbox/link'; import logoEUI from '../../images/logo-eui.svg'; import { GuideThemeSelector, GuideFigmaLink } from '../guide_theme_selector'; -const pkg = require('../../../../package.json'); const { euiVersions } = require('./versions.json'); +const currentVersion = require('../../../../package.json').version; +const pronounceVersion = (version: string) => { + return `version ${version.replaceAll('.', ' point ')}`; // NVDA pronounciation issue +}; export type GuidePageHeaderProps = { onToggleLocale: () => {}; @@ -49,10 +52,12 @@ export const GuidePageHeader: React.FunctionComponent = ({ return ( setIsVersionPopoverOpen((isOpen) => !isOpen)} - onClickAriaLabel={`Version ${pkg.version}. Click to switch versions`} + onClickAriaLabel={`${ + isLocalDev ? 'Local' : pronounceVersion(currentVersion) + }. Click to switch versions`} color={isLocalDev ? 'accent' : 'default'} > - {isLocalDev ? 'Local' : `v${pkg.version}`} + {isLocalDev ? 'Local' : `v${currentVersion}`} ); }, []); @@ -75,14 +80,16 @@ export const GuidePageHeader: React.FunctionComponent = ({ > {({ index, style }) => { const version = euiVersions[index]; + const screenReaderVersion = pronounceVersion(version); return ( = ({ href: `https://github.com/elastic/eui/releases/tag/v${version}`, target: '_blank', }} - isActive={version === pkg.version} - color={version === pkg.version ? 'primary' : 'text'} + isActive={version === currentVersion} + color={version === currentVersion ? 'primary' : 'text'} /> ); }} From 4202455453bcdf22966b19d8a7f25c8027f4483e Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Thu, 19 Oct 2023 18:29:22 -0700 Subject: [PATCH 9/9] Changelog for `EuiListGroupItem` changes --- upcoming_changelogs/7298.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 upcoming_changelogs/7298.md diff --git a/upcoming_changelogs/7298.md b/upcoming_changelogs/7298.md new file mode 100644 index 00000000000..b97adc0aa57 --- /dev/null +++ b/upcoming_changelogs/7298.md @@ -0,0 +1,4 @@ +**Bug fixes** + +- Fixed `EuiListGroupItem` to pass `style` props to the wrapping `
  • ` element alongside `className` and `css`. All other props will be passed to the underlying content. +- Fixed `EuiListGroupItem`'s non-transitioned transform on hover/focus