Просмотр исходного кода

ref(checkboxFancy): Added indeterminate option (#18355)

Priscila Oliveira 4 лет назад
Родитель
Сommit
e54cbebebc

+ 1 - 0
.gitignore

@@ -46,3 +46,4 @@ package-lock.json
 .webpack.meta
 pip-wheel-metadata/
 Brewfile.lock.json
+~/

+ 2 - 2
docs-ui/components/checkboxFancy.stories.js

@@ -4,7 +4,7 @@ import {withInfo} from '@storybook/addon-info';
 import {number, boolean} from '@storybook/addon-knobs';
 import styled from '@emotion/styled';
 
-import CheckboxFancy from 'app/components/checkboxFancy';
+import CheckboxFancy from 'app/components/checkboxFancy/checkboxFancy';
 
 storiesOf('Style|Icons', module).add(
   'CheckboxFancy',
@@ -13,7 +13,7 @@ storiesOf('Style|Icons', module).add(
       <Container>
         <CheckboxFancy
           size={`${number('Size', 100)}px`}
-          checked={boolean('Checked', true)}
+          isChecked={boolean('Checked', true)}
         />
       </Container>
     );

+ 0 - 74
src/sentry/static/sentry/app/components/checkboxFancy.tsx

@@ -1,74 +0,0 @@
-import React from 'react';
-import styled from '@emotion/styled';
-import {css} from '@emotion/core';
-import PropTypes from 'prop-types';
-
-import InlineSvg from 'app/components/inlineSvg';
-
-type Props = {
-  disabled?: boolean;
-  checked?: boolean;
-  size?: string;
-  className?: string;
-};
-
-const getDisabledStyles = p =>
-  p.disabled &&
-  css`
-    background: ${p.checked ? p.theme.gray1 : p.theme.offWhite};
-    border-color: ${p.theme.gray1};
-  `;
-
-const getHoverStyles = p =>
-  !p.disabled &&
-  css`
-    border: 2px solid ${p.checked ? p.theme.purple : p.theme.gray4};
-  `;
-
-const CheckboxFancy = styled(({checked, disabled, className}: Props) => (
-  <div
-    role="checkbox"
-    aria-disabled={disabled}
-    aria-checked={checked}
-    className={className}
-  >
-    {checked && <Check src="icon-checkmark-sm" />}
-  </div>
-))`
-  width: ${p => p.size};
-  height: ${p => p.size};
-  border-radius: 5px;
-  background: ${p => (p.checked ? p.theme.purple : null)};
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.05) inset;
-  border: 2px solid ${p => (p.checked ? p.theme.purple : p.theme.gray2)};
-  cursor: ${p => (p.disabled ? 'disabled' : 'pointer')};
-  ${p => !p.checked && 'transition: 500ms border ease-out'};
-
-  &:hover {
-    ${getHoverStyles}
-  }
-
-  ${getDisabledStyles}
-`;
-
-CheckboxFancy.defaultProps = {
-  checked: false,
-  size: '16px',
-};
-
-CheckboxFancy.propTypes = {
-  checked: PropTypes.bool,
-  disabled: PropTypes.bool,
-  size: PropTypes.string,
-};
-
-const Check = styled(InlineSvg)`
-  width: 70%;
-  height: 70%;
-  color: #fff;
-`;
-
-export default CheckboxFancy;

+ 67 - 0
src/sentry/static/sentry/app/components/checkboxFancy/checkboxFancy.tsx

@@ -0,0 +1,67 @@
+import React from 'react';
+import styled from '@emotion/styled';
+import {css} from '@emotion/core';
+
+import {Theme} from 'app/utils/theme';
+
+import CheckboxFancyContent from './checkboxFancyContent';
+
+type Props = {
+  isDisabled?: boolean;
+  size?: string;
+  className?: string;
+} & React.ComponentProps<typeof CheckboxFancyContent>;
+
+const disabledStyles = (p: Props & {theme: Theme}) =>
+  p.isDisabled &&
+  css`
+    background: ${p.isChecked || p.isIndeterminate ? p.theme.gray1 : p.theme.offWhite};
+    border-color: ${p.theme.gray1};
+  `;
+
+const hoverStyles = (p: Props & {theme: Theme}) =>
+  !p.isDisabled &&
+  css`
+    border: 2px solid ${p.isChecked || p.isIndeterminate ? p.theme.purple : p.theme.gray4};
+  `;
+
+const CheckboxFancy = styled(
+  ({isChecked, className, isDisabled, isIndeterminate}: Props) => (
+    <div
+      data-test-id="checkbox-fancy"
+      role="checkbox"
+      aria-disabled={isDisabled}
+      aria-checked={isChecked}
+      className={className}
+    >
+      <CheckboxFancyContent isIndeterminate={isIndeterminate} isChecked={isChecked} />
+    </div>
+  )
+)`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.05) inset;
+  width: ${p => p.size};
+  height: ${p => p.size};
+  border-radius: 5px;
+  background: ${p => (p.isChecked || p.isIndeterminate ? p.theme.purple : 'transparent')};
+  border: 2px solid
+    ${p => (p.isChecked || p.isIndeterminate ? p.theme.purple : p.theme.gray2)};
+  cursor: ${p => (p.isDisabled ? 'not-allowed' : 'pointer')};
+  ${p => (!p.isChecked || !p.isIndeterminate) && 'transition: 500ms border ease-out'};
+
+  &:hover {
+    ${hoverStyles}
+  }
+
+  ${disabledStyles}
+`;
+
+CheckboxFancy.defaultProps = {
+  size: '16px',
+  isChecked: false,
+  isIndeterminate: false,
+};
+
+export default CheckboxFancy;

+ 23 - 0
src/sentry/static/sentry/app/components/checkboxFancy/checkboxFancyContent.tsx

@@ -0,0 +1,23 @@
+import React from 'react';
+
+import {IconCheckmark} from 'app/icons/iconCheckmark';
+import {IconSubtract} from 'app/icons/iconSubtract';
+
+type Props = {
+  isChecked?: boolean;
+  isIndeterminate?: boolean;
+};
+
+const CheckboxFancyContent = ({isChecked, isIndeterminate}: Props) => {
+  if (isIndeterminate) {
+    return <IconSubtract size="70%" color="white" />;
+  }
+
+  if (isChecked) {
+    return <IconCheckmark size="70%" color="white" />;
+  }
+
+  return null;
+};
+
+export default CheckboxFancyContent;

+ 2 - 2
src/sentry/static/sentry/app/components/globalSelectionHeaderRow.jsx

@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
 import React from 'react';
 import styled from '@emotion/styled';
 
-import CheckboxFancy from 'app/components/checkboxFancy';
+import CheckboxFancy from 'app/components/checkboxFancy/checkboxFancy';
 import space from 'app/styles/space';
 
 class GlobalSelectionHeaderRow extends React.Component {
@@ -28,7 +28,7 @@ class GlobalSelectionHeaderRow extends React.Component {
   render() {
     const {checked, onCheckClick, multi, renderCheckbox, children, ...props} = this.props;
 
-    const checkbox = <CheckboxFancy disabled={!multi} checked={checked} />;
+    const checkbox = <CheckboxFancy isDisabled={!multi} isChecked={checked} />;
 
     return (
       <Container isChecked={checked} {...props}>

+ 9 - 1
src/sentry/static/sentry/app/icons/iconCheckmark.tsx

@@ -16,7 +16,15 @@ export const IconCheckmark = React.forwardRef(function IconCheckmark(
   const size = theme.iconSizes[providedSize] ?? providedSize;
 
   return (
-    <svg viewBox="0 0 16 16" fill={color} height={size} width={size} {...props} ref={ref}>
+    <svg
+      data-test-id="icon-check-mark"
+      viewBox="0 0 16 16"
+      fill={color}
+      height={size}
+      width={size}
+      {...props}
+      ref={ref}
+    >
       {providedCircle === true ? (
         <g>
           <path d="M7,12a.78.78,0,0,1-.57-.26L4,9.05A.76.76,0,0,1,4.07,8a.75.75,0,0,1,1.06.07l1.75,2L10.77,4.3A.75.75,0,0,1,12,5.14L7.58,11.7A.77.77,0,0,1,7,12Z" />

+ 9 - 1
src/sentry/static/sentry/app/icons/iconSubtract.tsx

@@ -16,7 +16,15 @@ export const IconSubtract = React.forwardRef(function IconSubtract(
   const size = theme.iconSizes[providedSize] ?? providedSize;
 
   return (
-    <svg viewBox="0 0 16 16" fill={color} height={size} width={size} {...props} ref={ref}>
+    <svg
+      data-test-id="icon-subtract"
+      viewBox="0 0 16 16"
+      fill={color}
+      height={size}
+      width={size}
+      {...props}
+      ref={ref}
+    >
       {providedCircle === true ? (
         <g>
           <path d="M8,16a8,8,0,1,1,8-8A8,8,0,0,1,8,16ZM8,1.53A6.47,6.47,0,1,0,14.47,8,6.47,6.47,0,0,0,8,1.53Z" />

+ 3 - 1
src/sentry/static/sentry/app/types/iconProps.tsx

@@ -1,6 +1,8 @@
+import {IconSizes} from 'app/utils/theme';
+
 export type IconProps = React.SVGAttributes<SVGElement> & {
   color?: string;
-  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | string;
+  size?: IconSizes | string;
   direction?: 'up' | 'right' | 'down' | 'left';
   solid?: boolean;
   circle?: boolean;

+ 10 - 7
src/sentry/static/sentry/app/utils/theme.tsx

@@ -191,18 +191,20 @@ const button = {
   },
 } as const;
 
+const iconSizes = {
+  xs: '12px',
+  sm: '16px',
+  md: '20px',
+  lg: '24px',
+  xl: '32px',
+};
+
 const theme = {
   breakpoints: ['768px', '992px', '1200px', '1440px', '2560px'],
 
   ...colors,
 
-  iconSizes: {
-    xs: '12px',
-    sm: '16px',
-    md: '20px',
-    lg: '24px',
-    xl: '32px',
-  },
+  iconSizes,
 
   iconDirections: {
     up: '0',
@@ -327,5 +329,6 @@ const theme = {
 
 export type Theme = typeof theme;
 export type Color = keyof typeof colors;
+export type IconSizes = keyof typeof iconSizes;
 
 export default theme;

Некоторые файлы не были показаны из-за большого количества измененных файлов