diff options
author | Kevin Silva <kevin.silva@sonarsource.com> | 2023-11-23 23:37:20 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-11-29 20:02:37 +0000 |
commit | 7b21628bae583ec474406a47a211cc80e229e198 (patch) | |
tree | abd60b0377dd3e4db5b7ec7f4ead77d9a7cc4d93 /server/sonar-web/design-system/src/components | |
parent | fcd2e450c23ec6be7dfacac336c6f207fd6ebebe (diff) | |
download | sonarqube-7b21628bae583ec474406a47a211cc80e229e198.tar.gz sonarqube-7b21628bae583ec474406a47a211cc80e229e198.zip |
SONAR-21070 - Changed project settings webhooks to adapt new UI
Diffstat (limited to 'server/sonar-web/design-system/src/components')
4 files changed, 178 insertions, 2 deletions
diff --git a/server/sonar-web/design-system/src/components/TextAccordion.tsx b/server/sonar-web/design-system/src/components/TextAccordion.tsx new file mode 100644 index 00000000000..7ea6a6f1d00 --- /dev/null +++ b/server/sonar-web/design-system/src/components/TextAccordion.tsx @@ -0,0 +1,115 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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 classNames from 'classnames'; +import { uniqueId } from 'lodash'; +import React, { ReactNode } from 'react'; +import tw from 'twin.macro'; +import { themeColor } from '../helpers'; +import { Note } from './Text'; +import { BareButton } from './buttons'; +import { OpenCloseIndicator } from './icons'; + +interface Props { + ariaLabel: string; + children: ReactNode; + className?: string; + data?: string; + onClick: (data?: string) => void; + open: boolean; + renderHeader?: () => ReactNode; + title: ReactNode; +} + +export function TextAccordion(props: Readonly<Props>) { + const [hoveringInner, setHoveringInner] = React.useState(false); + + const { className, open, renderHeader, title, ariaLabel } = props; + + const id = React.useMemo(() => uniqueId('accordion-'), []); + + function handleClick() { + props.onClick(props.data); + } + + function onDetailEnter() { + setHoveringInner(true); + } + + function onDetailLeave() { + setHoveringInner(false); + } + + return ( + <StyledAccordion + className={classNames('it__text-accordion', className, { + 'no-hover': hoveringInner, + })} + > + <Note as="h3"> + <BareButton + aria-controls={`${id}-panel`} + aria-expanded={open} + aria-label={ariaLabel} + className="sw-flex sw-items-center sw-px-2 sw-py-2 sw-box-border sw-w-full" + id={`${id}-header`} + onClick={handleClick} + > + <AccordionTitle> + <OpenCloseIndicator className="sw-mr-1" open={open} /> + {title} + </AccordionTitle> + {renderHeader?.()} + </BareButton> + </Note> + {open && ( + <AccordionContent onMouseEnter={onDetailEnter} onMouseLeave={onDetailLeave} role="region"> + {props.children} + </AccordionContent> + )} + </StyledAccordion> + ); +} + +const StyledAccordion = styled.div` + transition: border-color 0.3s ease; +`; + +const AccordionTitle = styled.span` + cursor: pointer; + position: relative; + display: inline-flex; + align-items: center; + font-weight: bold; + vertical-align: middle; + transition: color 0.3s ease; + + ${tw`sw-select-none`} + ${tw`sw-pt-4 sw-px-page sw-pb-2`} + + &:hover { + color: ${themeColor('linkDefault')}; + } +`; + +const AccordionContent = styled.div` + ${tw`sw-pl-10`} +`; diff --git a/server/sonar-web/design-system/src/components/__tests__/TextAccordion-test.tsx b/server/sonar-web/design-system/src/components/__tests__/TextAccordion-test.tsx new file mode 100644 index 00000000000..1ffc80211d3 --- /dev/null +++ b/server/sonar-web/design-system/src/components/__tests__/TextAccordion-test.tsx @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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 } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import { render } from '../../helpers/testUtils'; +import { TextAccordion } from '../TextAccordion'; + +it('should behave correctly', async () => { + const user = userEvent.setup(); + const children = 'hello'; + renderAccordion(children); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + await user.click(screen.getByRole('button', { name: 'test-aria' })); + expect(screen.getByText(children)).toBeInTheDocument(); +}); + +function renderAccordion(children: React.ReactNode) { + function AccordionTest() { + const [open, setOpen] = React.useState(false); + + return ( + <TextAccordion + ariaLabel="test-aria" + onClick={() => { + setOpen(!open); + }} + open={open} + renderHeader={() => 'Expand'} + title="test" + > + <div>{children}</div> + </TextAccordion> + ); + } + + return render(<AccordionTest />); +} diff --git a/server/sonar-web/design-system/src/components/index.ts b/server/sonar-web/design-system/src/components/index.ts index 5ed00fbfce7..b39467294fa 100644 --- a/server/sonar-web/design-system/src/components/index.ts +++ b/server/sonar-web/design-system/src/components/index.ts @@ -75,6 +75,7 @@ export * from './Switch'; export * from './Table'; export * from './Tags'; export * from './Text'; +export * from './TextAccordion'; export * from './Title'; export { ToggleButton } from './ToggleButton'; export { Tooltip } from './Tooltip'; diff --git a/server/sonar-web/design-system/src/components/input/InputField.tsx b/server/sonar-web/design-system/src/components/input/InputField.tsx index 781c5243751..c5d97ead8ce 100644 --- a/server/sonar-web/design-system/src/components/input/InputField.tsx +++ b/server/sonar-web/design-system/src/components/input/InputField.tsx @@ -45,7 +45,7 @@ export const InputField = forwardRef<HTMLInputElement, InputProps>( return ( <StyledInput ref={ref} style={{ ...style, '--inputSize': INPUT_SIZES[size] }} {...props} /> ); - } + }, ); InputField.displayName = 'InputField'; @@ -54,7 +54,7 @@ export const InputTextArea = forwardRef<HTMLTextAreaElement, InputTextAreaProps> return ( <StyledTextArea ref={ref} style={{ ...style, '--inputSize': INPUT_SIZES[size] }} {...props} /> ); - } + }, ); InputTextArea.displayName = 'InputTextArea'; @@ -140,6 +140,11 @@ const StyledInput = styled.input` ${baseStyle} ${tw`sw-h-control`} } + input[type='password']& { + ${getInputVariant} + ${baseStyle} + ${tw`sw-h-control`} + } `; const StyledTextArea = styled.textarea` |