diff --git a/.gitignore b/.gitignore index d26b669..cec4f54 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,8 @@ build pnpm-lock.yaml #Playwright -/playwright/playwright/.cache -/playwright-report +.cache* +playwright-report* /test-results # other files diff --git a/package.json b/package.json index 012b3e9..a7d8791 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "playwright:install": "playwright install --with-deps", "playwright": "playwright test --config=playwright/playwright.config.ts", "playwright:update": "npm run playwright -- -u", + "playwright:clear-cache": "rm -rf ./playwright/.cache", "playwright:docker": "./scripts/playwright-docker.sh 'npm run playwright'", "playwright:docker:update": "./scripts/playwright-docker.sh 'npm run playwright:update'", "playwright:docker:clear-cache": "./scripts/playwright-docker.sh clear-cache" diff --git a/playwright/README.md b/playwright/README.md index 6e76a76..0ed4c26 100644 --- a/playwright/README.md +++ b/playwright/README.md @@ -118,6 +118,7 @@ - `npm run playwright:install` - install playwright browsers and dependencies - `npm run playwright` - run tests - `npm run playwright:update` - update screenshots +- `npm run playwright:clear-cache` - clear cache vite - `npm run playwright:docker` - run tests using docker - `npm run playwright:docker:update` - update screenshots using docker -- `npm run playwright:docker:clear-cache` - clear node_modules cache for docker container +- `npm run playwright:docker:clear-cache` - clear node_modules cache for docker container and clear cache vite diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts index 424f9b5..92125e4 100644 --- a/playwright/playwright.config.ts +++ b/playwright/playwright.config.ts @@ -17,7 +17,10 @@ reporter.push( 'html', { open: process.env.CI ? 'never' : 'on-failure', - outputFolder: resolve(process.cwd(), 'playwright-report'), + outputFolder: resolve( + process.cwd(), + process.env.IS_DOCKER ? 'playwright-report-docker' : 'playwright-report', + ), }, ], ); @@ -53,6 +56,7 @@ const config: PlaywrightTestConfig = { /* Port to use for Playwright component endpoint. */ screenshot: 'only-on-failure', timezoneId: 'UTC', + ctCacheDir: process.env.IS_DOCKER ? '.cache-docker' : '.cache', ctViteConfig: { //@ts-ignore plugins: [ diff --git a/scripts/playwright-docker.sh b/scripts/playwright-docker.sh index 7674751..acc8ffd 100755 --- a/scripts/playwright-docker.sh +++ b/scripts/playwright-docker.sh @@ -15,6 +15,7 @@ run_command() { $CONTAINER_TOOL run --rm --network host -it -w /work \ -v $(pwd):/work \ -v "$NODE_MODULES_CACHE_DIR:/work/node_modules" \ + -e IS_DOCKER=1 \ "$IMAGE_NAME:$IMAGE_TAG" \ /bin/bash -c "$1" } @@ -30,6 +31,7 @@ fi if [[ "$1" = "clear-cache" ]]; then rm -rf "$NODE_MODULES_CACHE_DIR" + rm -rf "./playwright/.cache-docker" exit 0 fi diff --git a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss index 85596f4..9753187 100644 --- a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss +++ b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.scss @@ -1,6 +1,9 @@ @use '../../variables'; +@use '../../../../styles/mixins'; .#{variables.$ns}all-pages-list-item { + @include mixins.accessibility-button; + display: flex; align-items: center; @@ -11,6 +14,7 @@ &__text { flex: 1; + text-align: initial; } &__icon { diff --git a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx index dfa6bcb..1cf76b1 100644 --- a/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx +++ b/src/components/AllPagesPanel/AllPagesListItem/AllPagesListItem.tsx @@ -27,14 +27,17 @@ export const AllPagesListItem: React.FC = (props) => { [onToggle], ); - const onItemClick = (e: MouseEvent) => { + const onItemClick = (e: MouseEvent) => { if (editMode) { e.stopPropagation(); e.preventDefault(); } }; + + const [Tag, tagProps] = item.link ? ['a' as const, {href: item.link}] : ['button' as const, {}]; + return ( -
+ {item.icon ? ( ) : null} @@ -47,6 +50,6 @@ export const AllPagesListItem: React.FC = (props) => { {item.hidden ? : } )} -
+ ); }; diff --git a/src/components/AsideHeader/AsideHeader.scss b/src/components/AsideHeader/AsideHeader.scss index da11730..b24daa7 100644 --- a/src/components/AsideHeader/AsideHeader.scss +++ b/src/components/AsideHeader/AsideHeader.scss @@ -182,20 +182,14 @@ $block: '.#{variables.$ns}aside-header'; } } - &__logo-button-wrapper { + &__logo-button &__logo-icon-place { + height: var( + --gn-aside-header-item-icon-background-size, + var(--_--item-icon-background-size) + ); width: var(--gn-aside-header-min-width); } - &__logo-button[class] { - &, - .g-button__icon { - height: var( - --gn-aside-header-item-icon-background-size, - var(--_--item-icon-background-size) - ); - } - } - &__menu-items { flex-grow: 1; } diff --git a/src/components/AsideHeader/AsideHeaderContext.ts b/src/components/AsideHeader/AsideHeaderContext.ts index 37a8a33..b59ea82 100644 --- a/src/components/AsideHeader/AsideHeaderContext.ts +++ b/src/components/AsideHeader/AsideHeaderContext.ts @@ -10,7 +10,7 @@ export interface AsideHeaderInnerContextType extends AsideHeaderInnerProps { onItemClick: ( item: MenuItem, collapsed: boolean, - event: React.MouseEvent, + event: React.MouseEvent, ) => void; } diff --git a/src/components/AsideHeader/components/Header.tsx b/src/components/AsideHeader/components/Header.tsx index 66c9b6c..5ed6881 100644 --- a/src/components/AsideHeader/components/Header.tsx +++ b/src/components/AsideHeader/components/Header.tsx @@ -33,8 +33,8 @@ export const Header = () => { {...logo} onClick={onLogoClick} compact={compact} - buttonWrapperClassName={b('logo-button-wrapper')} buttonClassName={b('logo-button')} + iconPlaceClassName={b('logo-icon-place')} /> )} diff --git a/src/components/AsideHeader/useAsideHeaderInnerContextValue.tsx b/src/components/AsideHeader/useAsideHeaderInnerContextValue.tsx index 4c1cc2e..a6791c5 100644 --- a/src/components/AsideHeader/useAsideHeaderInnerContextValue.tsx +++ b/src/components/AsideHeader/useAsideHeaderInnerContextValue.tsx @@ -33,11 +33,7 @@ export const useAsideHeaderInnerContextValue = ( }, [onClosePanel]); const onItemClick = useCallback( - ( - item: MenuItem, - collapsed: boolean, - event: React.MouseEvent, - ) => { + (item: MenuItem, collapsed: boolean, event: React.MouseEvent) => { if (item.id === ALL_PAGES_MENU_ITEM.id) { onClosePanel?.(); setInnerVisiblePanel((prev) => diff --git a/src/components/CompositeBar/CompositeBar.tsx b/src/components/CompositeBar/CompositeBar.tsx index 3124fa7..0c28a0f 100644 --- a/src/components/CompositeBar/CompositeBar.tsx +++ b/src/components/CompositeBar/CompositeBar.tsx @@ -35,7 +35,7 @@ export type CompositeBarProps = CompositeBarItems & { onItemClick?: ( item: MenuItem, collapsed: boolean, - event: React.MouseEvent, + event: React.MouseEvent, ) => void; multipleTooltip?: boolean; menuMoreTitle?: string; diff --git a/src/components/CompositeBar/HighlightedItem/HighlightedItem.tsx b/src/components/CompositeBar/HighlightedItem/HighlightedItem.tsx index 8c7bfe3..fefb77e 100644 --- a/src/components/CompositeBar/HighlightedItem/HighlightedItem.tsx +++ b/src/components/CompositeBar/HighlightedItem/HighlightedItem.tsx @@ -13,7 +13,7 @@ const b = block('composite-bar-highlighted-item'); interface ItemInnerProps { iconRef: React.RefObject; iconNode: React.ReactNode; - onClick?: (event: React.MouseEvent) => void; + onClick?: (event: React.MouseEvent) => void; onClickCapture?: (event: React.SyntheticEvent) => void; } diff --git a/src/components/CompositeBar/Item/Item.scss b/src/components/CompositeBar/Item/Item.scss index 8defac9..89c0862 100644 --- a/src/components/CompositeBar/Item/Item.scss +++ b/src/components/CompositeBar/Item/Item.scss @@ -1,8 +1,11 @@ @use '../../variables'; +@use '../../../../styles/mixins'; $block: '.#{variables.$ns}composite-bar-item'; #{$block} { + @include mixins.accessibility-button; + $class: &; --gn-composite-bar-item-action-size: 36px; @@ -24,6 +27,7 @@ $block: '.#{variables.$ns}composite-bar-item'; height: 100%; align-items: center; cursor: pointer; + padding: 0; &__icon { color: var(--gn-aside-header-item-icon-color, var(--_--item-icon-color)); @@ -94,6 +98,8 @@ $block: '.#{variables.$ns}composite-bar-item'; } &__collapse-item { + @include mixins.accessibility-button; + --_--item-icon-color: var(--g-color-text-misc); display: flex; diff --git a/src/components/CompositeBar/Item/Item.tsx b/src/components/CompositeBar/Item/Item.tsx index 830d0c6..094dd2a 100644 --- a/src/components/CompositeBar/Item/Item.tsx +++ b/src/components/CompositeBar/Item/Item.tsx @@ -36,7 +36,7 @@ export interface ItemProps extends ItemPopup { onItemClick?: ( item: MenuItem, collapsed: boolean, - event: React.MouseEvent, + event: React.MouseEvent, ) => void; onItemClickCapture?: (event: React.SyntheticEvent) => void; bringForward?: boolean; @@ -92,7 +92,7 @@ export const Item: React.FC = (props) => { const [open, toggleOpen] = React.useState(false); - const ref = React.useRef(null); + const ref = React.useRef(null); const anchorRef = popupAnchor || ref; const highlightedRef = React.useRef(null); @@ -158,13 +158,18 @@ export const Item: React.FC = (props) => { }; const makeNode = ({icon: iconEl, title: titleEl}: MakeItemParams) => { + const [Tag, tagProps] = item.link + ? ['a' as const, {href: item.link}] + : ['button' as const, {}]; + const createdNode = ( -
) => { + onClick={(event: React.MouseEvent) => { if (collapsedItem) { /** * If we call onItemClick for collapsedItem then: @@ -198,7 +203,7 @@ export const Item: React.FC = (props) => { > {titleEl}
- + {renderPopupContent && Boolean(anchorRef?.current) && ( = (props) => {
); - return item.link ? ( - - {createdNode} - - ) : ( - createdNode - ); + return createdNode; }; const iconNode = icon ? ( @@ -255,7 +254,7 @@ export const Item: React.FC = (props) => { ) => + onClick={(event: React.MouseEvent) => onItemClick?.(item, false, event) } onClickCapture={onItemClickCapture} @@ -301,26 +300,21 @@ function CollapsedPopup({ title: titleEl, icon: iconEl, }: MakeItemParams) => { - const res = ( -
, - ) => { + onClick={(event: React.MouseEvent) => { onItemClick?.(collapseItem, true, event); }} > {iconEl} {titleEl} -
- ); - - return collapseItem.link ? ( - - {res} - - ) : ( - res + ); }; diff --git a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-dark-webkit-linux.png b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-dark-webkit-linux.png index e124f96..854b612 100644 Binary files a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-dark-webkit-linux.png and b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-dark-webkit-linux.png differ diff --git a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-light-webkit-linux.png b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-light-webkit-linux.png index f01b595..3bceef8 100644 Binary files a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-light-webkit-linux.png and b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-ManyItems-light-webkit-linux.png differ diff --git a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-dark-webkit-linux.png b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-dark-webkit-linux.png index e278fa9..53fbedd 100644 Binary files a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-dark-webkit-linux.png and b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-dark-webkit-linux.png differ diff --git a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-light-webkit-linux.png b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-light-webkit-linux.png index 28b4a51..9184da0 100644 Binary files a/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-light-webkit-linux.png and b/src/components/Footer/desktop/__snapshots__/Footer.visual.test.tsx-snapshots/Footer-render-story-Showcase-light-webkit-linux.png differ diff --git a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-dark-webkit-linux.png b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-dark-webkit-linux.png index be90ed5..f30114d 100644 Binary files a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-dark-webkit-linux.png and b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-dark-webkit-linux.png differ diff --git a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-light-webkit-linux.png b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-light-webkit-linux.png index 29c7685..c39e4f1 100644 Binary files a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-light-webkit-linux.png and b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-ManyItems-light-webkit-linux.png differ diff --git a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-dark-webkit-linux.png b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-dark-webkit-linux.png index 3070363..3e93101 100644 Binary files a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-dark-webkit-linux.png and b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-dark-webkit-linux.png differ diff --git a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-light-webkit-linux.png b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-light-webkit-linux.png index d26de28..44f9dbe 100644 Binary files a/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-light-webkit-linux.png and b/src/components/Footer/mobile/__snapshots__/MobileFooter.visual.test.tsx-snapshots/MobileFooter-render-story-Showcase-light-webkit-linux.png differ diff --git a/src/components/Logo/Logo.scss b/src/components/Logo/Logo.scss index aca66b9..27a302a 100644 --- a/src/components/Logo/Logo.scss +++ b/src/components/Logo/Logo.scss @@ -7,28 +7,14 @@ $block: '.#{variables.$ns}logo'; #{$block} { display: flex; align-items: center; - flex-shrink: 0; height: 40px; - &__logo-btn-place { - flex-shrink: 0; + &__btn-logo { display: flex; align-items: center; + flex-shrink: 0; justify-content: center; - cursor: pointer; - - & .g-button::before { - background-color: transparent; - } - } - - &__logo { - @include text-body-2; - vertical-align: middle; - cursor: pointer; - } - &__logo-link { &, &:hover, &:active, @@ -38,9 +24,17 @@ $block: '.#{variables.$ns}logo'; outline: none; color: inherit; } + &:focus-visible { + outline: solid var(--g-color-line-misc); + outline-offset: -2px; + } } - .g-root &__btn-logo.button2_theme_flat.button2_hovered_yes::before { - background-color: transparent; + &__logo-icon-place { + width: 36px; + + display: flex; + align-items: center; + justify-content: center; } } diff --git a/src/components/Logo/Logo.tsx b/src/components/Logo/Logo.tsx index 30924a8..abc4ab6 100644 --- a/src/components/Logo/Logo.tsx +++ b/src/components/Logo/Logo.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import {Button, Icon} from '@gravity-ui/uikit'; +import {Icon} from '@gravity-ui/uikit'; import {LogoProps} from '../types'; import {block} from '../utils/cn'; @@ -10,12 +10,13 @@ import './Logo.scss'; const b = block('logo'); export const Logo: React.FC< - LogoProps & {compact?: boolean; buttonClassName?: string; buttonWrapperClassName?: string} + LogoProps & {compact?: boolean; buttonClassName?: string; iconPlaceClassName?: string} > = ({ text, icon, iconSrc, iconClassName, + iconPlaceClassName, iconSize = 24, textSize = 15, href, @@ -24,7 +25,6 @@ export const Logo: React.FC< onClick, compact, className, - buttonWrapperClassName, buttonClassName, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, @@ -35,33 +35,14 @@ export const Logo: React.FC< if (iconSrc) { buttonIcon = ( - + logo icon - + ); } else if (icon) { buttonIcon = ; } - const button = ( - - ); - let logo: React.ReactNode; if (typeof text === 'function') { @@ -74,25 +55,24 @@ export const Logo: React.FC< ); } + const button = ( + + {buttonIcon} + {!compact && logo} + + ); + return (
-
- {hasWrapper ? wrapper(button, Boolean(compact)) : button} -
- {!compact && - (hasWrapper ? ( -
{wrapper(logo, Boolean(compact))}
- ) : ( - - {logo} - - ))} + {hasWrapper ? wrapper(button, Boolean(compact)) : button}
); }; diff --git a/src/components/types.ts b/src/components/types.ts index 6a333eb..30c7a79 100644 --- a/src/components/types.ts +++ b/src/components/types.ts @@ -26,7 +26,7 @@ export interface MenuItem extends QAProps { onItemClick?: ( item: MenuItem, collapsed: boolean, - event: React.MouseEvent, + event: React.MouseEvent, ) => void; onItemClickCapture?: (event: React.SyntheticEvent) => void; itemWrapper?: ( diff --git a/styles/mixins.scss b/styles/mixins.scss index e9d06f1..e2c54d8 100644 --- a/styles/mixins.scss +++ b/styles/mixins.scss @@ -9,3 +9,17 @@ background-color: var(--g-color-base-selection-hover); } } + +@mixin accessibility-button() { + background: none; + color: inherit; + border: none; + font: inherit; + outline: inherit; + text-decoration: inherit; + + &:focus-visible { + outline: solid var(--g-color-line-misc); + outline-offset: -2px; + } +}