diff --git a/services/web/frontend/js/shared/components/ol/ol-form-checkbox.tsx b/services/web/frontend/js/shared/components/ol/ol-form-checkbox.tsx index 89bb175bc7..825a3bb01f 100644 --- a/services/web/frontend/js/shared/components/ol/ol-form-checkbox.tsx +++ b/services/web/frontend/js/shared/components/ol/ol-form-checkbox.tsx @@ -35,7 +35,7 @@ function OLFormCheckbox(props: OLFormCheckboxProps) { } /> ) : ( - + ) } diff --git a/services/web/frontend/stories/shared/form/form-check.stories.tsx b/services/web/frontend/stories/shared/form/form-check.stories.tsx index c22a95036e..f55c4863ac 100644 --- a/services/web/frontend/stories/shared/form/form-check.stories.tsx +++ b/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() + const ref = useRef(null) useLayoutEffect(() => { if (ref.current) { @@ -48,7 +49,7 @@ export const CheckboxIndeterminate = (args: Story['args']) => { } }, []) - return + return } CheckboxIndeterminate.args = { id: 'id-2', diff --git a/services/web/frontend/stylesheets/components/form.scss b/services/web/frontend/stylesheets/components/form.scss index dff7b32f34..f3cc1d63b0 100644 --- a/services/web/frontend/stylesheets/components/form.scss +++ b/services/web/frontend/stylesheets/components/form.scss @@ -1,16 +1,117 @@ +@function form-check-box-svg($color) { + @return url("data:image/svg+xml,"); +} + +@function form-check-radio-svg($color) { + @return url("data:image/svg+xml,"); +} + +@function form-check-indeterminate-svg($color) { + @return url("data:image/svg+xml,"); +} + +@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; +} + +@include theme('default') { + .ide-redesign-main, + .project-ds-nav-page { + @include form-check-dark; + } +} + +#storybook-root { + @include theme('default') { + @include form-check-dark; + } +} + .form-check-input { - @function form-check-box-svg($color) { - @return url("data:image/svg+xml,"); - } - - @function form-check-radio-svg($color) { - @return url("data:image/svg+xml,"); - } - - @function form-check-indeterminate-svg($color) { - @return url("data:image/svg+xml,"); - } - &: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 { diff --git a/services/web/frontend/stylesheets/components/modal.scss b/services/web/frontend/stylesheets/components/modal.scss index 1f91d8dccc..2eeec89bc4 100644 --- a/services/web/frontend/stylesheets/components/modal.scss +++ b/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) {