diff --git a/packages/react/src/components/form/Checkbox/Checkbox.module.css b/packages/css/checkbox.css similarity index 70% rename from packages/react/src/components/form/Checkbox/Checkbox.module.css rename to packages/css/checkbox.css index b86108c940..558e103e8b 100644 --- a/packages/react/src/components/form/Checkbox/Checkbox.module.css +++ b/packages/css/checkbox.css @@ -1,5 +1,5 @@ @layer fds.checkbox { - .container { + .fds-checkbox { --fds-checkbox-size: 1.75rem; --fds-checkbox-focus-border-width: 3px; --fds-checkbox-background: var(--fds-semantic-background-default); @@ -9,13 +9,13 @@ display: grid; } - .container:has(.label) { + .fds-checkbox:has(.fds-checkbox__label) { grid-template-columns: var(--fds-checkbox-size) auto; gap: var(--fds-spacing-2); } /* Checkbox */ - .input { + .fds-checkbox__input { position: relative; width: var(--fds-checkbox-size); height: var(--fds-checkbox-size); @@ -30,7 +30,7 @@ border-radius: var(--fds-border_radius-medium); } - .input::before { + .fds-checkbox__input::before { position: absolute; content: ''; display: block; @@ -43,7 +43,7 @@ border-radius: var(--fds-border_radius-medium); } - .label { + .fds-checkbox__label { min-height: var(--fds-sizing-10); min-width: min-content; display: inline-flex; @@ -53,44 +53,44 @@ cursor: pointer; } - .description { + .fds-checkbox__description { margin-top: calc(var(--fds-spacing-3) * -1); color: var(--fds-semantic-text-neutral-subtle); grid-column: 2; } - .disabled > .input, - .disabled > .label, - .disabled > .input::before { + .fds-checkbox--disabled > .fds-checkbox__input, + .fds-checkbox--disabled > .fds-checkbox__label, + .fds-checkbox--disabled > .fds-checkbox__input::before { cursor: not-allowed; } - .disabled > .label, - .disabled > .input, - .disabled > .description { + .fds-checkbox--disabled > .fds-checkbox__label, + .fds-checkbox--disabled > .fds-checkbox__input, + .fds-checkbox--disabled > .fds-checkbox__description { opacity: var(--fds-opacity-disabled); } - .readonly > .label, - .readonly > .input, - .readonly > .input::before { + .fds-checkbox--readonly > .fds-checkbox__label, + .fds-checkbox--readonly > .fds-checkbox__input, + .fds-checkbox--readonly > .fds-checkbox__input::before { cursor: default; } - .input:focus-visible { + .fds-checkbox__input:focus-visible { outline-offset: 0; outline: var(--fds-checkbox-focus-border-width) solid var(--fds-semantic-border-focus-outline); box-shadow: inset 0 0 0 var(--fds-checkbox-focus-border-width) var(--fds-semantic-border-focus-boxshadow); } - .input:checked { + .fds-checkbox__input:checked { --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); background: var(--fds-checkbox-border-color); background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M18.5509 6.32414C18.9414 6.71467 18.9414 7.34783 18.5509 7.73836L10.5821 15.7071C10.1916 16.0976 9.55842 16.0976 9.16789 15.7071L4.94914 11.4884C4.55862 11.0978 4.55862 10.4647 4.94914 10.0741C5.33967 9.68362 5.97283 9.68362 6.36336 10.0741L9.875 13.5858L17.1366 6.32414C17.5272 5.93362 18.1603 5.93362 18.5509 6.32414Z' fill='white'/%3E%3C/svg%3E%0A"); } - .input:indeterminate { + .fds-checkbox__input:indeterminate { --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); background-color: var(--fds-checkbox-border-color); @@ -98,70 +98,76 @@ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.25 11.25C4.25 10.4216 4.92157 9.75 5.75 9.75H16.75C17.5784 9.75 18.25 10.4216 18.25 11.25C18.25 12.0784 17.5784 12.75 16.75 12.75H5.75C4.92157 12.75 4.25 12.0784 4.25 11.25Z' fill='white' /%3E%3C/svg%3E%0A"); } - .readonly > .input { + .fds-checkbox--readonly > .fds-checkbox__input { --fds-checkbox-border-color: var(--fds-semantic-border-neutral-subtle); --fds-checkbox-background: var(--fds-semantic-surface-neutral-subtle); } - .input:checked:not(:focus-visible) { + .fds-checkbox__input:checked:not(:focus-visible) { box-shadow: inset 0 0 0 2px var(--fds-checkbox-border-color); } - .readonly > .input:checked { + .fds-checkbox--readonly > .fds-checkbox__input:checked { background: var(--fds-checkbox-background); background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M18.5509 6.32414C18.9414 6.71467 18.9414 7.34783 18.5509 7.73836L10.5821 15.7071C10.1916 16.0976 9.55842 16.0976 9.16789 15.7071L4.94914 11.4884C4.55862 11.0978 4.55862 10.4647 4.94914 10.0741C5.33967 9.68362 5.97283 9.68362 6.36336 10.0741L9.875 13.5858L17.1366 6.32414C17.5272 5.93362 18.1603 5.93362 18.5509 6.32414Z' fill='%2368707c'/%3E%3C/svg%3E%0A"); } - .readonly > .input:indeterminate { + .fds-checkbox--readonly > .fds-checkbox__input:indeterminate { background: var(--fds-checkbox-background); background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.25 11.25C4.25 10.4216 4.92157 9.75 5.75 9.75H16.75C17.5784 9.75 18.25 10.4216 18.25 11.25C18.25 12.0784 17.5784 12.75 16.75 12.75H5.75C4.92157 12.75 4.25 12.0784 4.25 11.25Z' fill='%2368707c' /%3E%3C/svg%3E%0A"); } - .error > .input:not(:disabled, :focus-visible) { + .fds-checkbox--error > .fds-checkbox__input:not(:disabled, :focus-visible) { --fds-checkbox-border-color: var(--fds-semantic-border-danger-default); } /* Only use hover for non-touch devices to prevent sticky-hovering "input:not(:read-only)" does not work so using ".container:not(.readonly) >" instead */ @media (hover: hover) and (pointer: fine) { - .container:not(.readonly, .disabled) > .label:hover, - .container:not(.readonly, .disabled) > .input:hover + .label { + .fds-checkbox:not(.fds-checkbox--readonly, .fds-checkbox--disabled) > .fds-checkbox__label:hover, + .fds-checkbox:not(.fds-checkbox--readonly, .fds-checkbox--disabled) > .fds-checkbox__input:hover + .fds-checkbox__label { color: var(--fds-semantic-text-action-hover); } - .container:not(.readonly, .disabled) > .input:hover:not(:checked) { + .fds-checkbox:not(.fds-checkbox--readonly, .fds-checkbox--disabled) > .fds-checkbox__input:hover:not(:checked) { --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); - box-shadow: var(--fds-checkbox-border__hover), inset 0 0 0 2px var(--fds-checkbox-border-color); + box-shadow: + var(--fds-checkbox-border__hover), + inset 0 0 0 2px var(--fds-checkbox-border-color); } - .container:not(.readonly, .disabled) > .input:hover:checked { + .fds-checkbox:not(.fds-checkbox--readonly, .fds-checkbox--disabled) > .fds-checkbox__input:hover:checked { --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); - box-shadow: var(--fds-checkbox-border__hover), inset 0 0 0 2px var(--fds-checkbox-border-color); + box-shadow: + var(--fds-checkbox-border__hover), + inset 0 0 0 2px var(--fds-checkbox-border-color); } - .container:not(.readonly, .disabled) > .input:hover:checked:focus-visible { - box-shadow: var(--fds-checkbox-border__hover), inset 0 0 0 var(--fds-checkbox-focus-border-width) var(--fds-semantic-border-focus-boxshadow); + .fds-checkbox:not(.fds-checkbox--readonly, .fds-checkbox--disabled) > .fds-checkbox__input:hover:checked:focus-visible { + box-shadow: + var(--fds-checkbox-border__hover), + inset 0 0 0 var(--fds-checkbox-focus-border-width) var(--fds-semantic-border-focus-boxshadow); } } /** Sizing */ - .small { + .fds-checkbox--small { --fds-checkbox-size: var(--fds-sizing-5); min-height: var(--fds-sizing-10); } - .medium { + .fds-checkbox--medium { --fds-checkbox-size: var(--fds-sizing-6); min-height: var(--fds-sizing-11); } - .large { + .fds-checkbox--large { --fds-checkbox-size: var(--fds-sizing-7); min-height: var(--fds-sizing-12); diff --git a/packages/css/index.css b/packages/css/index.css index 7d4edf9b40..00d91ea25b 100644 --- a/packages/css/index.css +++ b/packages/css/index.css @@ -11,3 +11,4 @@ @import url('./skiplink.css'); @import url('./accordion.css'); @import url('./box.css'); +@import url('./checkbox.css'); diff --git a/packages/css/react-css-modules.css b/packages/css/react-css-modules.css index 178755ee34..b3b25981f4 100644 --- a/packages/css/react-css-modules.css +++ b/packages/css/react-css-modules.css @@ -956,176 +956,6 @@ } } -@layer fds.checkbox { - .fds-checkbox-container-ad9a8b9c { - --fds-checkbox-size: 1.75rem; - --fds-checkbox-focus-border-width: 3px; - --fds-checkbox-background: var(--fds-semantic-background-default); - --fds-checkbox-border-color: var(--fds-semantic-border-input-default); - --fds-checkbox-border__hover: 0 0 0 var(--fds-spacing-2) var(--fds-semantic-surface-info-subtle-hover); - - display: grid; - } - - .fds-checkbox-container-ad9a8b9c:has(.fds-checkbox-label-ad9a8b9c) { - grid-template-columns: var(--fds-checkbox-size) auto; - gap: var(--fds-spacing-2); - } - - /* Checkbox */ - .fds-checkbox-input-ad9a8b9c { - position: relative; - width: var(--fds-checkbox-size); - height: var(--fds-checkbox-size); - z-index: 1; - appearance: none; - margin: 0; - align-self: center; - outline: none; - cursor: pointer; - box-shadow: inset 0 0 0 2px var(--fds-checkbox-border-color); - background: var(--fds-checkbox-background); - border-radius: var(--fds-border_radius-medium); - } - - .fds-checkbox-input-ad9a8b9c::before { - position: absolute; - content: ''; - display: block; - width: 2.75rem; - height: 2.75rem; - transform: translate(-50%, -50%); - top: 50%; - left: 50%; - cursor: pointer; - border-radius: var(--fds-border_radius-medium); - } - - .fds-checkbox-label-ad9a8b9c { - min-height: var(--fds-sizing-10); - min-width: min-content; - display: inline-flex; - flex-direction: row; - gap: var(--fds-spacing-1); - align-items: center; - cursor: pointer; - } - - .fds-checkbox-description-ad9a8b9c { - margin-top: calc(var(--fds-spacing-3) * -1); - color: var(--fds-semantic-text-neutral-subtle); - grid-column: 2; - } - - .fds-checkbox-disabled-ad9a8b9c > .fds-checkbox-input-ad9a8b9c, - .fds-checkbox-disabled-ad9a8b9c > .fds-checkbox-label-ad9a8b9c, - .fds-checkbox-disabled-ad9a8b9c > .fds-checkbox-input-ad9a8b9c::before { - cursor: not-allowed; - } - - .fds-checkbox-disabled-ad9a8b9c > .fds-checkbox-label-ad9a8b9c, - .fds-checkbox-disabled-ad9a8b9c > .fds-checkbox-input-ad9a8b9c, - .fds-checkbox-disabled-ad9a8b9c > .fds-checkbox-description-ad9a8b9c { - opacity: var(--fds-opacity-disabled); - } - - .fds-checkbox-readonly-ad9a8b9c > .fds-checkbox-label-ad9a8b9c, - .fds-checkbox-readonly-ad9a8b9c > .fds-checkbox-input-ad9a8b9c, - .fds-checkbox-readonly-ad9a8b9c > .fds-checkbox-input-ad9a8b9c::before { - cursor: default; - } - - .fds-checkbox-input-ad9a8b9c:focus-visible { - outline-offset: 0; - outline: var(--fds-checkbox-focus-border-width) solid var(--fds-semantic-border-focus-outline); - box-shadow: inset 0 0 0 var(--fds-checkbox-focus-border-width) var(--fds-semantic-border-focus-boxshadow); - } - - .fds-checkbox-input-ad9a8b9c:checked { - --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); - - background: var(--fds-checkbox-border-color); - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M18.5509 6.32414C18.9414 6.71467 18.9414 7.34783 18.5509 7.73836L10.5821 15.7071C10.1916 16.0976 9.55842 16.0976 9.16789 15.7071L4.94914 11.4884C4.55862 11.0978 4.55862 10.4647 4.94914 10.0741C5.33967 9.68362 5.97283 9.68362 6.36336 10.0741L9.875 13.5858L17.1366 6.32414C17.5272 5.93362 18.1603 5.93362 18.5509 6.32414Z' fill='white'/%3E%3C/svg%3E%0A"); - } - - .fds-checkbox-input-ad9a8b9c:indeterminate { - --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); - - background-color: var(--fds-checkbox-border-color); - background-repeat: no-repeat; - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.25 11.25C4.25 10.4216 4.92157 9.75 5.75 9.75H16.75C17.5784 9.75 18.25 10.4216 18.25 11.25C18.25 12.0784 17.5784 12.75 16.75 12.75H5.75C4.92157 12.75 4.25 12.0784 4.25 11.25Z' fill='white' /%3E%3C/svg%3E%0A"); - } - - .fds-checkbox-readonly-ad9a8b9c > .fds-checkbox-input-ad9a8b9c { - --fds-checkbox-border-color: var(--fds-semantic-border-neutral-subtle); - --fds-checkbox-background: var(--fds-semantic-surface-neutral-subtle); - } - - .fds-checkbox-input-ad9a8b9c:checked:not(:focus-visible) { - box-shadow: inset 0 0 0 2px var(--fds-checkbox-border-color); - } - - .fds-checkbox-readonly-ad9a8b9c > .fds-checkbox-input-ad9a8b9c:checked { - background: var(--fds-checkbox-background); - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M18.5509 6.32414C18.9414 6.71467 18.9414 7.34783 18.5509 7.73836L10.5821 15.7071C10.1916 16.0976 9.55842 16.0976 9.16789 15.7071L4.94914 11.4884C4.55862 11.0978 4.55862 10.4647 4.94914 10.0741C5.33967 9.68362 5.97283 9.68362 6.36336 10.0741L9.875 13.5858L17.1366 6.32414C17.5272 5.93362 18.1603 5.93362 18.5509 6.32414Z' fill='%2368707c'/%3E%3C/svg%3E%0A"); - } - - .fds-checkbox-readonly-ad9a8b9c > .fds-checkbox-input-ad9a8b9c:indeterminate { - background: var(--fds-checkbox-background); - background-repeat: no-repeat; - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 23 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.25 11.25C4.25 10.4216 4.92157 9.75 5.75 9.75H16.75C17.5784 9.75 18.25 10.4216 18.25 11.25C18.25 12.0784 17.5784 12.75 16.75 12.75H5.75C4.92157 12.75 4.25 12.0784 4.25 11.25Z' fill='%2368707c' /%3E%3C/svg%3E%0A"); - } - - .fds-checkbox-error-ad9a8b9c > .fds-checkbox-input-ad9a8b9c:not(:disabled, :focus-visible) { - --fds-checkbox-border-color: var(--fds-semantic-border-danger-default); - } - - /* Only use hover for non-touch devices to prevent sticky-hovering - "input:not(:read-only)" does not work so using ".container:not(.readonly) >" instead */ - @media (hover: hover) and (pointer: fine) { - .fds-checkbox-container-ad9a8b9c:not(.fds-checkbox-readonly-ad9a8b9c, .fds-checkbox-disabled-ad9a8b9c) > .fds-checkbox-label-ad9a8b9c:hover, - .fds-checkbox-container-ad9a8b9c:not(.fds-checkbox-readonly-ad9a8b9c, .fds-checkbox-disabled-ad9a8b9c) > .fds-checkbox-input-ad9a8b9c:hover + .fds-checkbox-label-ad9a8b9c { - color: var(--fds-semantic-text-action-hover); - } - - .fds-checkbox-container-ad9a8b9c:not(.fds-checkbox-readonly-ad9a8b9c, .fds-checkbox-disabled-ad9a8b9c) > .fds-checkbox-input-ad9a8b9c:hover:not(:checked) { - --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); - - box-shadow: var(--fds-checkbox-border__hover), inset 0 0 0 2px var(--fds-checkbox-border-color); - } - - .fds-checkbox-container-ad9a8b9c:not(.fds-checkbox-readonly-ad9a8b9c, .fds-checkbox-disabled-ad9a8b9c) > .fds-checkbox-input-ad9a8b9c:hover:checked { - --fds-checkbox-border-color: var(--fds-semantic-border-input-hover); - - box-shadow: var(--fds-checkbox-border__hover), inset 0 0 0 2px var(--fds-checkbox-border-color); - } - - .fds-checkbox-container-ad9a8b9c:not(.fds-checkbox-readonly-ad9a8b9c, .fds-checkbox-disabled-ad9a8b9c) > .fds-checkbox-input-ad9a8b9c:hover:checked:focus-visible { - box-shadow: var(--fds-checkbox-border__hover), inset 0 0 0 var(--fds-checkbox-focus-border-width) var(--fds-semantic-border-focus-boxshadow); - } - } - - /** Sizing */ - - .fds-checkbox-small-ad9a8b9c { - --fds-checkbox-size: var(--fds-sizing-5); - - min-height: var(--fds-sizing-10); - } - - .fds-checkbox-medium-ad9a8b9c { - --fds-checkbox-size: var(--fds-sizing-6); - - min-height: var(--fds-sizing-11); - } - - .fds-checkbox-large-ad9a8b9c { - --fds-checkbox-size: var(--fds-sizing-7); - - min-height: var(--fds-sizing-12); - } -} - @layer fds.fieldset { .fds-fieldset-fieldset-2b3c05fc { margin: 0; diff --git a/packages/react/src/components/form/Checkbox/Checkbox.tsx b/packages/react/src/components/form/Checkbox/Checkbox.tsx index 8d6d7df3da..ae7ec56472 100644 --- a/packages/react/src/components/form/Checkbox/Checkbox.tsx +++ b/packages/react/src/components/form/Checkbox/Checkbox.tsx @@ -1,13 +1,12 @@ import type { InputHTMLAttributes, ReactNode } from 'react'; import { forwardRef } from 'react'; -import cl from 'clsx'; +import cl from 'clsx/lite'; import { useMergeRefs } from '@floating-ui/react'; import { omit } from '../../../utilities'; import { Label, Paragraph } from '../../Typography'; import type { FormFieldProps } from '../useFormField'; -import classes from './Checkbox.module.css'; import { useCheckbox } from './useCheckbox'; export type CheckboxProps = { @@ -22,79 +21,71 @@ export type CheckboxProps = { } & Omit & Omit, 'size' | 'value'>; -export const Checkbox = forwardRef( - (props, ref) => { - const { children, description, className, style, ...rest } = props; - const { - inputProps, - descriptionId, - hasError, - size = 'medium', - readOnly, - } = useCheckbox(props); +export const Checkbox = forwardRef((props, ref) => { + const { children, description, className, style, ...rest } = props; + const { inputProps, descriptionId, hasError, size = 'medium', readOnly } = useCheckbox(props); - const inputRef = useMergeRefs([ - ref, - (el) => { - if (el) { - el.indeterminate = rest.indeterminate ?? false; - } - }, - ]); + const inputRef = useMergeRefs([ + ref, + (el) => { + if (el) { + el.indeterminate = rest.indeterminate ?? false; + } + }, + ]); - return ( - +
-
- - {children && ( - <> - - {description && ( - -
- {description} -
-
- )} - - )} -
- - ); - }, -); + {description} +
+
+ )} + + )} + + + ); +}); Checkbox.displayName = 'Checkbox';