diff options
author | David Cho-Lerat <david.cho-lerat@sonarsource.com> | 2023-05-30 16:00:31 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-06-09 20:03:09 +0000 |
commit | 40e061b25b152d7704a989240c12191317a81f3f (patch) | |
tree | d4281cec8e1ce5597d1a5504b62e2a48d1850e36 /server/sonar-web/design-system/src/components | |
parent | 319b9ad6352943fcf6265a589d7dba6ce659fa0a (diff) | |
download | sonarqube-40e061b25b152d7704a989240c12191317a81f3f.tar.gz sonarqube-40e061b25b152d7704a989240c12191317a81f3f.zip |
SONAR-19345 Issues page - list view: new facets using MIUI elements
Diffstat (limited to 'server/sonar-web/design-system/src/components')
16 files changed, 213 insertions, 185 deletions
diff --git a/server/sonar-web/design-system/src/components/BarChart.tsx b/server/sonar-web/design-system/src/components/BarChart.tsx index 9b460674e69..91a01174c97 100644 --- a/server/sonar-web/design-system/src/components/BarChart.tsx +++ b/server/sonar-web/design-system/src/components/BarChart.tsx @@ -24,7 +24,7 @@ import { themeColor } from '../helpers'; interface DataPoint { description: string; - tooltip?: string; + tooltip?: string | JSX.Element; x: number; y: number; } diff --git a/server/sonar-web/design-system/src/components/DatePicker.tsx b/server/sonar-web/design-system/src/components/DatePicker.tsx index e80795cbad2..0bb34725c2d 100644 --- a/server/sonar-web/design-system/src/components/DatePicker.tsx +++ b/server/sonar-web/design-system/src/components/DatePicker.tsx @@ -17,8 +17,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import styled from '@emotion/styled'; +import styled from '@emotion/styled'; import classNames from 'classnames'; import { format, @@ -76,7 +76,7 @@ interface Props { showClearButton?: boolean; size?: InputSizeKeys; value?: Date; - valueFormatter: (date?: Date) => string; + valueFormatter?: (date?: Date) => string; } interface State { @@ -142,6 +142,7 @@ export class DatePicker extends React.PureComponent<Props, State> { id, placeholder, showClearButton = true, + valueFormatter = (date?: Date) => (date ? format(date, 'MMM d, yyyy') : ''), size, } = this.props; const { lastHovered, currentMonth, open } = this.state; @@ -153,10 +154,12 @@ export class DatePicker extends React.PureComponent<Props, State> { const selectedDays = selectedDay ? [selectedDay] : []; let highlighted: Matcher = false; const lastHoveredOrValue = lastHovered ?? selectedDay; + if (highlightFrom && lastHoveredOrValue) { highlighted = { from: highlightFrom, to: lastHoveredOrValue }; selectedDays.push(highlightFrom); } + if (highlightTo && lastHoveredOrValue) { highlighted = { from: lastHoveredOrValue, to: highlightTo }; selectedDays.push(highlightTo); @@ -221,11 +224,13 @@ export class DatePicker extends React.PureComponent<Props, State> { readOnly ref={inputRef} size={size} - title={this.props.valueFormatter(selectedDay)} + title={valueFormatter(selectedDay)} type="text" - value={this.props.valueFormatter(selectedDay)} + value={valueFormatter(selectedDay)} /> + <StyledCalendarIcon fill="datePickerIcon" /> + {selectedDay !== undefined && showClearButton && ( <StyledInteractiveIcon Icon={CloseIcon} @@ -327,16 +332,21 @@ function getCustomCalendarNavigation({ const { goToMonth, nextMonth, previousMonth } = useCalendarNavigation(); const baseDate = startOfMonth(displayMonth); // reference date + const months = range(MONTHS_IN_A_YEAR).map((month) => { const monthValue = setMonth(baseDate, month); + return { label: format(monthValue, 'MMM'), value: monthValue, }; }); + const startYear = fromYear ?? getYear(Date.now()) - YEARS_TO_DISPLAY; + const years = range(startYear, toYear ? toYear + 1 : undefined).map((year) => { const yearValue = setYear(baseDate, year); + return { label: String(year), value: yearValue, @@ -349,37 +359,53 @@ function getCustomCalendarNavigation({ Icon={ChevronLeftIcon} aria-label={ariaPreviousMonthLabel} className="sw-mr-2" - onClick={() => previousMonth && goToMonth(previousMonth)} - size="small" - /> - <InputSelect - isClearable={false} - onChange={(value) => { - if (value) { - goToMonth(value.value); - } - }} - options={months} - size="full" - value={months.find((m) => isSameMonth(m.value, displayMonth))} - /> - <InputSelect - className="sw-ml-1" - isClearable={false} - onChange={(value) => { - if (value) { - goToMonth(value.value); + onClick={() => { + if (previousMonth) { + goToMonth(previousMonth); } }} - options={years} - size="full" - value={years.find((y) => isSameYear(y.value, displayMonth))} + size="small" /> + + <span data-testid="month-select"> + <InputSelect + isClearable={false} + onChange={(value) => { + if (value) { + goToMonth(value.value); + } + }} + options={months} + size="full" + value={months.find((m) => isSameMonth(m.value, displayMonth))} + /> + </span> + + <span data-testid="year-select"> + <InputSelect + className="sw-ml-1" + data-testid="year-select" + isClearable={false} + onChange={(value) => { + if (value) { + goToMonth(value.value); + } + }} + options={years} + size="full" + value={years.find((y) => isSameYear(y.value, displayMonth))} + /> + </span> + <InteractiveIcon Icon={ChevronRightIcon} aria-label={ariaNextMonthLabel} className="sw-ml-2" - onClick={() => nextMonth && goToMonth(nextMonth)} + onClick={() => { + if (nextMonth) { + goToMonth(nextMonth); + } + }} size="small" /> </nav> diff --git a/server/sonar-web/design-system/src/components/DateRangePicker.tsx b/server/sonar-web/design-system/src/components/DateRangePicker.tsx index 132deafcd04..01e73b17baf 100644 --- a/server/sonar-web/design-system/src/components/DateRangePicker.tsx +++ b/server/sonar-web/design-system/src/components/DateRangePicker.tsx @@ -41,7 +41,7 @@ interface Props { separatorText?: string; toLabel: string; value?: DateRange; - valueFormatter: (date?: Date) => string; + valueFormatter?: (date?: Date) => string; } export class DateRangePicker extends React.PureComponent<Props> { diff --git a/server/sonar-web/design-system/src/components/FacetBox.tsx b/server/sonar-web/design-system/src/components/FacetBox.tsx index 2e100268542..0366e6fe69e 100644 --- a/server/sonar-web/design-system/src/components/FacetBox.tsx +++ b/server/sonar-web/design-system/src/components/FacetBox.tsx @@ -26,7 +26,7 @@ import tw from 'twin.macro'; import { themeColor } from '../helpers'; import { Badge } from './Badge'; import { DeferredSpinner } from './DeferredSpinner'; -import { InteractiveIcon } from './InteractiveIcon'; +import { DestructiveIcon } from './InteractiveIcon'; import Tooltip from './Tooltip'; import { BareButton } from './buttons'; import { OpenCloseIndicator } from './icons'; @@ -39,7 +39,9 @@ export interface FacetBoxProps { clearIconLabel?: string; count?: number; countLabel?: string; + 'data-property'?: string; disabled?: boolean; + hasEmbeddedFacets?: boolean; id?: string; inner?: boolean; loading?: boolean; @@ -57,7 +59,9 @@ export function FacetBox(props: FacetBoxProps) { clearIconLabel, count, countLabel, + 'data-property': dataProperty, disabled = false, + hasEmbeddedFacets = false, id: idProp, inner = false, loading = false, @@ -73,7 +77,13 @@ export function FacetBox(props: FacetBoxProps) { const id = React.useMemo(() => idProp ?? uniqueId('filter-facet-'), [idProp]); return ( - <Accordion className={classNames(className, { open })} inner={inner} role="listitem"> + <Accordion + className={classNames(className, { open })} + data-property={dataProperty} + hasEmbeddedFacets={hasEmbeddedFacets} + inner={inner} + role="listitem" + > <Header> <ChevronAndTitle aria-controls={`${id}-panel`} @@ -106,6 +116,7 @@ export function FacetBox(props: FacetBoxProps) { <ClearIcon Icon={CloseIcon} aria-label={clearIconLabel ?? ''} + data-testid={`clear-${name}`} onClick={onClear} size="small" /> @@ -116,7 +127,7 @@ export function FacetBox(props: FacetBoxProps) { </Header> {open && ( - <div aria-labelledby={`${id}-header`} id={`${id}-panel`} role="region"> + <div aria-labelledby={`${id}-header`} id={`${id}-panel`} role="list"> {children} </div> )} @@ -124,14 +135,19 @@ export function FacetBox(props: FacetBoxProps) { ); } +FacetBox.displayName = 'FacetBox'; // so that tests don't see the obfuscated production name + const Accordion = styled.div<{ + hasEmbeddedFacets?: boolean; inner?: boolean; }>` ${tw`sw-flex-col`}; ${tw`sw-flex`}; ${tw`sw-gap-3`}; - ${({ inner }) => (inner ? tw`sw-gap-1 sw-ml-3` : '')}; + ${({ hasEmbeddedFacets }) => (hasEmbeddedFacets ? tw`sw-gap-0` : '')}; + + ${({ inner }) => (inner ? tw`sw-gap-1 sw-ml-3 sw-mt-1` : '')}; `; const BadgeAndIcons = styled.div` @@ -150,7 +166,7 @@ const ChevronAndTitle = styled(BareButton)<{ cursor: ${({ expandable }) => (expandable ? 'pointer' : 'default')}; `; -const ClearIcon = styled(InteractiveIcon)` +const ClearIcon = styled(DestructiveIcon)` --color: ${themeColor('dangerButton')}; `; diff --git a/server/sonar-web/design-system/src/components/FacetItem.tsx b/server/sonar-web/design-system/src/components/FacetItem.tsx index 0d318feec0a..62d5e38b150 100644 --- a/server/sonar-web/design-system/src/components/FacetItem.tsx +++ b/server/sonar-web/design-system/src/components/FacetItem.tsx @@ -26,8 +26,9 @@ import { ButtonProps, ButtonSecondary } from './buttons'; export type FacetItemProps = Omit<ButtonProps, 'name' | 'onClick'> & { active?: boolean; - name: string; + name: string | React.ReactNode; onClick: (x: string, multiple?: boolean) => void; + small?: boolean; stat?: React.ReactNode; /** Textual version of `name` */ tooltip?: string; @@ -41,11 +42,12 @@ export function FacetItem({ icon, name, onClick, + small, stat, tooltip, value, }: FacetItemProps) { - const disabled = disabledProp || (stat as number) === 0; + const disabled = disabledProp || (stat !== undefined && stat === 0); const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { event.preventDefault(); @@ -56,12 +58,15 @@ export function FacetItem({ return ( <StyledButton active={active} + aria-checked={active} + aria-label={typeof name === 'string' ? name : undefined} className={className} data-facet={value} disabled={disabled} icon={icon} onClick={handleClick} - role="listitem" + role="checkbox" + small={small} title={tooltip} > <span className="container"> @@ -72,10 +77,17 @@ export function FacetItem({ ); } -const StyledButton = styled(ButtonSecondary)<{ active?: boolean }>` +FacetItem.displayName = 'FacetItem'; // so that tests don't see the obfuscated production name + +const StyledButton = styled(ButtonSecondary)<{ active?: boolean; small?: boolean }>` ${tw`sw-body-sm`}; - ${tw`sw-p-1`}; + ${tw`sw-box-border`}; + ${tw`sw-h-7`}; + ${tw`sw-px-1`}; ${tw`sw-rounded-1`}; + ${tw`sw-w-full`}; + + ${({ small }) => (small ? tw`sw-body-xs sw-pr-0` : '')}; --background: ${({ active }) => (active ? themeColor('facetItemSelected') : 'transparent')}; --backgroundHover: ${({ active }) => (active ? themeColor('facetItemSelected') : 'transparent')}; @@ -95,6 +107,15 @@ const StyledButton = styled(ButtonSecondary)<{ active?: boolean }>` ${tw`sw-items-center`}; ${tw`sw-justify-between`}; + & span.name { + ${tw`sw-pr-1`}; + ${tw`sw-truncate`}; + + & mark { + background-color: ${themeColor('searchHighlight')}; + } + } + & span.stat { color: ${themeColor('facetItemLight')}; } diff --git a/server/sonar-web/design-system/src/components/FlagMessage.tsx b/server/sonar-web/design-system/src/components/FlagMessage.tsx index 3a3aed03c94..72ef3a9808f 100644 --- a/server/sonar-web/design-system/src/components/FlagMessage.tsx +++ b/server/sonar-web/design-system/src/components/FlagMessage.tsx @@ -90,6 +90,8 @@ export function FlagMessage(props: Props & React.HTMLAttributes<HTMLDivElement>) ); } +FlagMessage.displayName = 'FlagMessage'; // so that tests don't see the obfuscated production name + export const StyledFlag = styled.div<{ variantInfo: VariantInformation; }>` diff --git a/server/sonar-web/design-system/src/components/InputSearch.tsx b/server/sonar-web/design-system/src/components/InputSearch.tsx index 3c0233ef392..354fab3b5d2 100644 --- a/server/sonar-web/design-system/src/components/InputSearch.tsx +++ b/server/sonar-web/design-system/src/components/InputSearch.tsx @@ -164,7 +164,7 @@ export function InputSearch({ <StyledInteractiveIcon Icon={CloseIcon} aria-label={clearIconAriaLabel} - className="js-input-search-clear" + className="it__search-box-clear" onClick={handleClearClick} size="small" /> @@ -180,6 +180,8 @@ export function InputSearch({ ); } +InputSearch.displayName = 'InputSearch'; // so that tests don't see the obfuscated production name + export const InputSearchWrapper = styled.div` width: var(--inputSize); diff --git a/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx b/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx index 7aa37f175d3..230a5dc7231 100644 --- a/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx +++ b/server/sonar-web/design-system/src/components/KeyboardHintKeys.tsx @@ -17,17 +17,23 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + import styled from '@emotion/styled'; import tw from 'twin.macro'; import { themeColor, themeContrast } from '../helpers'; import { Key } from '../helpers/keyboard'; import { TriangleDownIcon, TriangleLeftIcon, TriangleRightIcon, TriangleUpIcon } from './icons'; -const COMMAND = '⌘'; -const CTRL = 'Ctrl'; -const OPTION = '⌥'; -const ALT = 'Alt'; -const NON_KEY_SYMBOLS = ['+', ' ']; +export const mappedKeys = { + [Key.Alt]: 'Alt', + [Key.ArrowDown]: <TriangleDownIcon />, + [Key.ArrowLeft]: <TriangleLeftIcon />, + [Key.ArrowRight]: <TriangleRightIcon />, + [Key.ArrowUp]: <TriangleUpIcon />, + [Key.Command]: '⌘', + [Key.Control]: 'Ctrl', + [Key.Option]: '⌥', +}; export function KeyboardHintKeys({ command }: { command: string }) { const keys = command @@ -35,11 +41,12 @@ export function KeyboardHintKeys({ command }: { command: string }) { .split(' ') .map((key, index) => { const uniqueKey = `${key}-${index}`; - if (NON_KEY_SYMBOLS.includes(key)) { + + if (!(Object.keys(mappedKeys).includes(key) || Object.values(mappedKeys).includes(key))) { return <span key={uniqueKey}>{key}</span>; } - return <KeyBox key={uniqueKey}>{getKey(key)}</KeyBox>; + return <KeyBox key={uniqueKey}>{mappedKeys[key as keyof typeof mappedKeys] || key}</KeyBox>; }); return <div className="sw-flex sw-gap-1">{keys}</div>; @@ -50,29 +57,6 @@ export const KeyBox = styled.span` ${tw`sw-px-1/2`} ${tw`sw-rounded-1/2`} - color: ${themeContrast('keyboardHintKey')}; background-color: ${themeColor('keyboardHintKey')}; + color: ${themeContrast('keyboardHintKey')}; `; - -function getKey(key: string) { - switch (key) { - case Key.Control: - return CTRL; - case Key.Command: - return COMMAND; - case Key.Alt: - return ALT; - case Key.Option: - return OPTION; - case Key.ArrowUp: - return <TriangleUpIcon />; - case Key.ArrowDown: - return <TriangleDownIcon />; - case Key.ArrowLeft: - return <TriangleLeftIcon />; - case Key.ArrowRight: - return <TriangleRightIcon />; - default: - return key; - } -} diff --git a/server/sonar-web/design-system/src/components/__tests__/DatePicker-test.tsx b/server/sonar-web/design-system/src/components/__tests__/DatePicker-test.tsx index 8edfa140e2a..01aa68be4c7 100644 --- a/server/sonar-web/design-system/src/components/__tests__/DatePicker-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/DatePicker-test.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + import { screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { getMonth, getYear, parseISO } from 'date-fns'; @@ -85,19 +86,46 @@ it('behaves correctly', async () => { expect(getYear(newDate3)).toBe(2019); }); -it('highlights the appropriate days', async () => { +it('should clear the value', async () => { const user = userEvent.setup(); - const value = parseISO('2022-06-14'); - renderDatePicker({ highlightFrom: parseISO('2022-06-12'), showClearButton: true, value }); + const onChange = jest.fn((_: Date) => undefined); + + const currentDate = parseISO('2022-06-13'); + + renderDatePicker({ + currentMonth: currentDate, + onChange, + showClearButton: true, + value: currentDate, + // eslint-disable-next-line jest/no-conditional-in-test + valueFormatter: (date?: Date) => (date ? 'formatted date' : 'no date'), + }); + + await user.click(screen.getByRole('textbox')); + + await user.click(screen.getByLabelText('clear')); + + expect(onChange).toHaveBeenCalledWith(undefined); +}); + +it.each([ + [{ highlightFrom: parseISO('2022-06-12'), value: parseISO('2022-06-14') }], + [{ alignRight: true, highlightTo: parseISO('2022-06-14'), value: parseISO('2022-06-12') }], +])('highlights the appropriate days', async (props) => { + const user = userEvent.setup(); + + const hightlightClass = 'rdp-highlighted'; + + renderDatePicker(props); await user.click(screen.getByRole('textbox')); - expect(screen.getByText('11')).not.toHaveClass('rdp-highlighted'); - expect(screen.getByText('12')).toHaveClass('rdp-highlighted'); - expect(screen.getByText('13')).toHaveClass('rdp-highlighted'); - expect(screen.getByText('14')).toHaveClass('rdp-highlighted'); - expect(screen.getByText('15')).not.toHaveClass('rdp-highlighted'); + expect(screen.getByText('11')).not.toHaveClass(hightlightClass); + expect(screen.getByText('12')).toHaveClass(hightlightClass); + expect(screen.getByText('13')).toHaveClass(hightlightClass); + expect(screen.getByText('14')).toHaveClass(hightlightClass); + expect(screen.getByText('15')).not.toHaveClass(hightlightClass); }); function renderDatePicker(overrides: Partial<DatePicker['props']> = {}) { diff --git a/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx b/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx index 88dd9499885..434a6147e5c 100644 --- a/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/FacetBox-test.tsx @@ -28,11 +28,11 @@ it('should render an empty disabled facet box', async () => { const onClick = jest.fn(); - renderComponent({ disabled: true, onClick }); + renderComponent({ disabled: true, hasEmbeddedFacets: true, onClick }); expect(screen.getByRole('listitem')).toBeInTheDocument(); - expect(screen.queryByRole('region')).not.toBeInTheDocument(); + expect(screen.queryByRole('list')).not.toBeInTheDocument(); expect(screen.getByText('Test FacetBox')).toBeInTheDocument(); @@ -58,7 +58,7 @@ it('should render an inner expanded facet box with count', async () => { open: true, }); - expect(screen.getByRole('region')).toBeInTheDocument(); + expect(screen.getByRole('list')).toBeInTheDocument(); expect(screen.getByRole('button', { expanded: true })).toBeInTheDocument(); diff --git a/server/sonar-web/design-system/src/components/__tests__/FacetItem-test.tsx b/server/sonar-web/design-system/src/components/__tests__/FacetItem-test.tsx index 12703d37f00..a916181172a 100644 --- a/server/sonar-web/design-system/src/components/__tests__/FacetItem-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/FacetItem-test.tsx @@ -30,9 +30,9 @@ it('should render a disabled facet item', async () => { renderComponent({ disabled: true, onClick }); - expect(screen.getByRole('listitem')).toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByRole('checkbox')).toHaveAttribute('aria-disabled', 'true'); - await user.click(screen.getByRole('listitem')); + await user.click(screen.getByRole('checkbox')); expect(onClick).not.toHaveBeenCalled(); }); @@ -44,18 +44,30 @@ it('should render a non-disabled facet item', async () => { renderComponent({ active: true, onClick, stat: 3, value: 'foo' }); - expect(screen.getByRole('listitem')).toHaveAttribute('aria-disabled', 'false'); + expect(screen.getByRole('checkbox')).toHaveAttribute('aria-disabled', 'false'); - await user.click(screen.getByRole('listitem')); + await user.click(screen.getByRole('checkbox')); expect(onClick).toHaveBeenCalledWith('foo', false); await user.keyboard('{Meta>}'); - await user.click(screen.getByRole('listitem')); + await user.click(screen.getByRole('checkbox')); expect(onClick).toHaveBeenLastCalledWith('foo', true); }); +it('should add an aria label if the name is a string', () => { + renderComponent({ name: 'Foo' }); + + expect(screen.getByRole('checkbox')).toHaveAccessibleName('Foo'); +}); + +it('should not add an aria label if the name is not a string', () => { + renderComponent({ name: <div>Foo</div>, small: true }); + + expect(screen.getByRole('checkbox')).not.toHaveAttribute('aria-label'); +}); + function renderComponent(props: Partial<FacetItemProps> = {}) { return render(<FacetItem name="Test facet item" onClick={jest.fn()} value="Value" {...props} />); } diff --git a/server/sonar-web/design-system/src/components/__tests__/KeyboardHintKeys-test.tsx b/server/sonar-web/design-system/src/components/__tests__/KeyboardHintKeys-test.tsx index 4d1ff44cede..b26ee4e2801 100644 --- a/server/sonar-web/design-system/src/components/__tests__/KeyboardHintKeys-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/KeyboardHintKeys-test.tsx @@ -21,24 +21,15 @@ import { Key } from '../../helpers/keyboard'; import { render } from '../../helpers/testUtils'; import { FCProps } from '../../types/misc'; -import { KeyboardHintKeys } from '../KeyboardHintKeys'; +import { KeyboardHintKeys, mappedKeys } from '../KeyboardHintKeys'; -it.each([ - Key.Control, - Key.Command, - Key.Alt, - Key.Option, - Key.ArrowUp, - Key.ArrowDown, - Key.ArrowLeft, - Key.ArrowRight, -])('should render %s', (key) => { +it.each(Object.keys(mappedKeys))('should render %s', (key) => { const { container } = setupWithProps({ command: key }); expect(container).toMatchSnapshot(); }); it('should render multiple keys', () => { - const { container } = setupWithProps({ command: `${Key.ArrowUp} ${Key.ArrowDown}` }); + const { container } = setupWithProps({ command: `Use Ctrl + ${Key.ArrowUp} ${Key.ArrowDown}` }); expect(container).toMatchSnapshot(); }); diff --git a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap index 081af387a40..6ac0d945eef 100644 --- a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHint-test.tsx.snap @@ -34,8 +34,8 @@ exports[`renders on mac 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -94,8 +94,8 @@ exports[`renders on windows 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -138,26 +138,6 @@ exports[`renders with command 1`] = ` color: rgb(106,117,144); } -.emotion-2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - -webkit-justify-content: center; - justify-content: center; - padding-left: 0.125rem; - padding-right: 0.125rem; - border-radius: 0.125rem; - color: rgb(62,67,87); - background-color: rgb(225,230,243); -} - <div> <div class="emotion-0 emotion-1" @@ -165,9 +145,7 @@ exports[`renders with command 1`] = ` <div class="sw-flex sw-gap-1" > - <span - class="emotion-2 emotion-3" - > + <span> command </span> </div> @@ -193,26 +171,6 @@ exports[`renders with title 1`] = ` color: rgb(106,117,144); } -.emotion-2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - -webkit-justify-content: center; - justify-content: center; - padding-left: 0.125rem; - padding-right: 0.125rem; - border-radius: 0.125rem; - color: rgb(62,67,87); - background-color: rgb(225,230,243); -} - <div> <div class="emotion-0 emotion-1" @@ -225,9 +183,7 @@ exports[`renders with title 1`] = ` <div class="sw-flex sw-gap-1" > - <span - class="emotion-2 emotion-3" - > + <span> click </span> </div> @@ -253,26 +209,6 @@ exports[`renders without title 1`] = ` color: rgb(106,117,144); } -.emotion-2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - -webkit-justify-content: center; - justify-content: center; - padding-left: 0.125rem; - padding-right: 0.125rem; - border-radius: 0.125rem; - color: rgb(62,67,87); - background-color: rgb(225,230,243); -} - <div> <div class="emotion-0 emotion-1" @@ -280,9 +216,7 @@ exports[`renders without title 1`] = ` <div class="sw-flex sw-gap-1" > - <span - class="emotion-2 emotion-3" - > + <span> click </span> </div> diff --git a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap index 907e3994ef0..be6c83072f5 100644 --- a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/KeyboardHintKeys-test.tsx.snap @@ -17,8 +17,8 @@ exports[`should render Alt 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -51,8 +51,8 @@ exports[`should render ArrowDown 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -99,8 +99,8 @@ exports[`should render ArrowLeft 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -147,8 +147,8 @@ exports[`should render ArrowRight 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -195,8 +195,8 @@ exports[`should render ArrowUp 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -243,8 +243,8 @@ exports[`should render Command 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -277,8 +277,8 @@ exports[`should render Control 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -311,8 +311,8 @@ exports[`should render Option 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -345,8 +345,8 @@ exports[`should render a default text if no keys match 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> @@ -361,9 +361,7 @@ exports[`should render a default text if no keys match 1`] = ` <span> + </span> - <span - class="emotion-0 emotion-1" - > + <span> click </span> </div> @@ -387,14 +385,25 @@ exports[`should render multiple keys 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> <div class="sw-flex sw-gap-1" > + <span> + Use + </span> + <span + class="emotion-0 emotion-1" + > + Ctrl + </span> + <span> + + + </span> <span class="emotion-0 emotion-1" > @@ -454,8 +463,8 @@ exports[`should render multiple keys with non-key symbols 1`] = ` padding-left: 0.125rem; padding-right: 0.125rem; border-radius: 0.125rem; - color: rgb(62,67,87); background-color: rgb(225,230,243); + color: rgb(62,67,87); } <div> diff --git a/server/sonar-web/design-system/src/components/icons/TestFileIcon.tsx b/server/sonar-web/design-system/src/components/icons/TestFileIcon.tsx index fae7278a2f6..9ab29f18b37 100644 --- a/server/sonar-web/design-system/src/components/icons/TestFileIcon.tsx +++ b/server/sonar-web/design-system/src/components/icons/TestFileIcon.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + import { useTheme } from '@emotion/react'; import { themeColor } from '../../helpers/theme'; import { CustomIcon, IconProps } from './Icon'; @@ -24,6 +25,7 @@ import { CustomIcon, IconProps } from './Icon'; export function TestFileIcon({ fill = 'currentColor', ...iconProps }: IconProps) { const theme = useTheme(); const fillColor = themeColor(fill)({ theme }); + return ( <CustomIcon {...iconProps}> <path diff --git a/server/sonar-web/design-system/src/components/icons/index.ts b/server/sonar-web/design-system/src/components/icons/index.ts index d81089a367a..898e9a46890 100644 --- a/server/sonar-web/design-system/src/components/icons/index.ts +++ b/server/sonar-web/design-system/src/components/icons/index.ts @@ -70,6 +70,7 @@ export { StatusConfirmedIcon } from './StatusConfirmedIcon'; export { StatusOpenIcon } from './StatusOpenIcon'; export { StatusReopenedIcon } from './StatusReopenedIcon'; export { StatusResolvedIcon } from './StatusResolvedIcon'; +export { TestFileIcon } from './TestFileIcon'; export { TrashIcon } from './TrashIcon'; export { TriangleDownIcon } from './TriangleDownIcon'; export { TriangleLeftIcon } from './TriangleLeftIcon'; |