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

Add a dark version of the checkbox component (#30213)

* Add a dark version of the checkbox component

* Add theming to storybook

* Fix storybook

* adding correct border colors

---------

Co-authored-by: davibaweja <davibaweja@gmail.com>
GitOrigin-RevId: e350ab7a0800edd960d99bb892e527b97106b17d
David 8 месяцев назад
Родитель
Сommit
3d18d02846

+ 1 - 1
services/web/frontend/js/shared/components/ol/ol-form-checkbox.tsx

@@ -35,7 +35,7 @@ function OLFormCheckbox(props: OLFormCheckboxProps) {
       }
     />
   ) : (
-    <Form.Check ref={inputRef} {...rest} />
+    <Form.Check className="form-checkbox" ref={inputRef} {...rest} />
   )
 }
 

+ 4 - 3
services/web/frontend/stories/shared/form/form-check.stories.tsx

@@ -2,10 +2,11 @@ import { useRef, useLayoutEffect } from 'react'
 import { Form } from 'react-bootstrap'
 import type { Meta, StoryObj } from '@storybook/react'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
+import OLFormCheckbox from '@/shared/components/ol/ol-form-checkbox'
 
 const meta: Meta<(typeof Form)['Check']> = {
   title: 'Shared / Components / Form',
-  component: Form.Check,
+  component: OLFormCheckbox,
   parameters: {
     controls: {
       include: ['disabled'],
@@ -40,7 +41,7 @@ export const CheckboxChecked: Story = {
 }
 
 export const CheckboxIndeterminate = (args: Story['args']) => {
-  const ref = useRef<HTMLInputElement>()
+  const ref = useRef<HTMLInputElement>(null)
 
   useLayoutEffect(() => {
     if (ref.current) {
@@ -48,7 +49,7 @@ export const CheckboxIndeterminate = (args: Story['args']) => {
     }
   }, [])
 
-  return <Form.Check ref={ref} {...args} />
+  return <OLFormCheckbox inputRef={ref} {...args} />
 }
 CheckboxIndeterminate.args = {
   id: 'id-2',

+ 183 - 8
services/web/frontend/stylesheets/components/form.scss

@@ -1,16 +1,117 @@
-.form-check-input {
-  @function form-check-box-svg($color) {
-    @return url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/></svg>");
-  }
+@function form-check-box-svg($color) {
+  @return url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/></svg>");
+}
+
+@function form-check-radio-svg($color) {
+  @return url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='2' fill='#{$color}'/></svg>");
+}
+
+@function form-check-indeterminate-svg($color) {
+  @return url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/></svg>");
+}
+
+@mixin form-check-light {
+  --checkbox-label-color: var(--content-primary);
+  --checkbox-border-color: var(--border-primary);
+  --checkbox-bg: var(--bg-light-primary);
+
+  // Hover
+  --checkbox-hover-border-color: var(--border-hover);
+
+  // Checked
+  --checkbox-checked-bg: var(--bg-accent-01);
+  --checkbox-checked-border-color: var(--bg-accent-01);
+  --checkbox-checked-background-image: #{escape-svg(
+      form-check-box-svg($content-primary-dark)
+    )};
+
+  // Indeterminate
+  --checkbox-indeterminate-background-image: #{escape-svg(
+      form-check-indeterminate-svg($content-primary-dark)
+    )};
+
+  // Checked & hover
+  --checkbox-hover-checked-bg: var(--bg-accent-02);
+  --checkbox-hover-checked-border-color: var(--bg-accent-02);
+
+  // Focus
+  --checkbox-focus-border-color: var(--border-primary);
+
+  // Disabled
+  --checkbox-disabled-bg: var(--bg-light-disabled);
+  --checkbox-disabled-border-color: var(--border-disabled);
+
+  // Disabled & checked
+  --checkbox-disabled-checked-background-image: #{escape-svg(
+      form-check-box-svg($content-disabled-dark)
+    )};
+
+  // Disabled & indeterminate
+  --checkbox-disabled-indeterminate-background-image: #{escape-svg(
+      form-check-indeterminate-svg($content-disabled-dark)
+    )};
+}
+
+@mixin form-check-dark {
+  --checkbox-label-color: var(--content-primary-dark);
+  --checkbox-border-color: var(--border-primary-dark);
+  --checkbox-bg: var(--bg-dark-primary);
+
+  // Hover
+  --checkbox-hover-border-color: var(--border-hover-dark);
+
+  // Checked
+  --checkbox-checked-bg: var(--bg-accent-03);
+  --checkbox-checked-border-color: var(--bg-accent-03);
+  --checkbox-checked-background-image: #{escape-svg(
+      form-check-box-svg($content-primary)
+    )};
+
+  // Indeterminate
+  --checkbox-indeterminate-background-image: #{escape-svg(
+      form-check-indeterminate-svg($content-primary)
+    )};
+
+  // Checked & hover
+  --checkbox-hover-checked-bg: var(--bg-accent-03);
+  --checkbox-hover-checked-border-color: var(--bg-accent-03);
+
+  // Focus
+  --checkbox-focus-border-color: var(--border-primary-dark);
+
+  // Disabled
+  --checkbox-disabled-bg: var(--bg-dark-disabled);
+  --checkbox-disabled-border-color: var(--border-disabled-dark);
+
+  // Disabled & checked
+  --checkbox-disabled-checked-background-image: #{escape-svg(
+      form-check-box-svg($content-disabled-dark)
+    )};
+
+  // Disabled & indeterminate
+  --checkbox-disabled-indeterminate-background-image: #{escape-svg(
+      form-check-indeterminate-svg($content-disabled-dark)
+    )};
+}
+
+:root {
+  @include form-check-light;
+}
 
-  @function form-check-radio-svg($color) {
-    @return url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='2' fill='#{$color}'/></svg>");
+@include theme('default') {
+  .ide-redesign-main,
+  .project-ds-nav-page {
+    @include form-check-dark;
   }
+}
 
-  @function form-check-indeterminate-svg($color) {
-    @return url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><path fill='none' stroke='#{$color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/></svg>");
+#storybook-root {
+  @include theme('default') {
+    @include form-check-dark;
   }
+}
 
+.form-check-input {
   &:hover {
     &:not(:disabled) {
       border-color: var(--border-hover);
@@ -59,6 +160,76 @@
   }
 }
 
+// TODO: compare to live storybook
+// NOTE: Nesting inside .form-checkbox to avoid affecting other form checks
+// such as input switches and radio buttons.
+.form-checkbox {
+  .form-check-input {
+    background-color: var(--checkbox-bg);
+    border-color: var(--checkbox-border-color);
+
+    &:checked,
+    &:indeterminate {
+      background-color: var(--checkbox-checked-bg);
+      border-color: var(--checkbox-checked-border-color);
+    }
+
+    &:checked {
+      background-image: var(--checkbox-checked-background-image);
+    }
+
+    &:indeterminate {
+      background-image: var(--checkbox-indeterminate-background-image);
+    }
+
+    &:hover {
+      &:not(:disabled) {
+        border-color: var(--checkbox-hover-border-color);
+
+        &:checked,
+        &:indeterminate {
+          background-color: var(--checkbox-hover-checked-bg);
+          border-color: var(--checkbox-hover-checked-border-color);
+        }
+      }
+    }
+
+    &:disabled {
+      background-color: var(--checkbox-disabled-bg);
+      border-color: var(--checkbox-disabled-border-color);
+
+      &:indeterminate {
+        background-color: var(--checkbox-disabled-bg);
+        border-color: var(--checkbox-disabled-border-color);
+        background-image: var(
+          --checkbox-disabled-indeterminate-background-image
+        );
+      }
+    }
+
+    // Use disabled attribute in addition of :disabled pseudo-class
+    // See: https://github.com/twbs/bootstrap/issues/28247
+    &[disabled],
+    &:disabled {
+      ~ .form-check-label {
+        color: $input-disabled-color;
+      }
+
+      &:checked {
+        background-image: var(--checkbox-disabled-checked-background-image);
+      }
+    }
+
+    &:focus-visible {
+      border-color: var(--checkbox-focus-border-color);
+    }
+  }
+}
+
+.form-check-label {
+  color: var(--checkbox-label-color);
+}
+
 .form-control {
   &[disabled],
   &:disabled {
@@ -240,6 +411,10 @@
   .checkbox-label {
     margin-left: var(--spacing-04);
   }
+
+  .form-check-label {
+    color: var(--checkbox-label-color);
+  }
 }
 
 %input-focus-style {

+ 2 - 1
services/web/frontend/stylesheets/components/modal.scss

@@ -3,8 +3,9 @@
 }
 
 .modal {
-  // Until we add a dark modal version, all dropdowns in modals should use light theme
+  // Until we add a dark modal version, all core components in modals should use light theme
   @include light-dropdown-menu;
+  @include form-check-light;
 }
 
 @include media-breakpoint-up(sm) {