Skip to content

Commit

Permalink
fix(Chip): use input component (#2683)
Browse files Browse the repository at this point in the history
- Fixes #2669
- Fixes wrong height implemented (now correctly `32px`)
- Implements simplified states after dialogue with Marianne
- Fixes better alignment of label vs. radio/checkbox
- Implements logic so elements with the `ds-focus--visible` class
automatically hides focus ring on children (no need for confusing,
nested focus rings)
  • Loading branch information
eirikbacker authored Oct 28, 2024
1 parent d5e0ba1 commit ce23f32
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 84 deletions.
6 changes: 6 additions & 0 deletions .changeset/shy-cameras-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@digdir/designsystemet-css": patch
"@digdir/designsystemet-react": patch
---

Chip: Use correct `32px` height to align nicely with `<Tag>`
14 changes: 11 additions & 3 deletions packages/css/base/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,17 @@
* We use both box-shadow and outline to ensure that the focus style is visible,
* in case box-shadow is overridden.
*/
box-shadow: var(--dsc-focus-boxShadow);
outline: var(--dsc-focus-outline);
outline-offset: var(--dsc-focus-border-width);
box-shadow: var(--ds--focus, var(--dsc-focus-boxShadow));
outline: var(--ds--focus, var(--dsc-focus-outline));
outline-offset: var(--ds--focus, var(--dsc-focus-border-width));

/**
* Using CSS custom properties toggle trick to ensure focus-visible is only shown on outermost element
* https://css-tricks.com/the-css-custom-property-toggle-trick/
*/
* {
--ds--focus: ;
}
}

[data-size='xs'] {
Expand Down
129 changes: 52 additions & 77 deletions packages/css/chip.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
.ds-chip {
--dsc-chip-background: var(--ds-color-accent-surface-default);
--dsc-chip-background--hover: var(--ds-color-accent-surface-hover);
--dsc-chip-background--active: var(--ds-color-accent-surface-active);
--dsc-chip-background--checked: var(--ds-color-accent-base-default);
--dsc-chip-background--checked--hover: var(--ds-color-accent-base-hover);
--dsc-chip-background--checked--active: var(--ds-color-accent-base-active);
--dsc-chip-border-color: var(--ds-color-accent-border-subtle);
--dsc-chip-border-radius: var(--ds-border-radius-full);
--dsc-chip-border-color--checked: transparent;
--dsc-chip-color: var(--ds-color-accent-text-default);
--dsc-chip-height: var(--ds-sizing-8);
--dsc-chip-icon-size: var(--ds-spacing-6);
--dsc-chip-input-color: var(--ds-color-accent-border-default);
--dsc-chip-input-size: var(--ds-spacing-5);
--dsc-chip-padding: 0 var(--ds-spacing-3);
--dsc-chip-color--checked: var(--ds-color-accent-contrast-default);
--dsc-chip-input-color: var(--ds-color-accent-border-strong);
--dsc-chip-input-color--checked: var(--ds-color-accent-base-default);

@composes ds-focus from './base/base.css';
--dsc-chip-border-radius: var(--ds-border-radius-full);
--dsc-chip-height: var(--ds-sizing-9);
--dsc-chip-icon-size: var(--ds-spacing-7);
--dsc-chip-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' fill='none' viewBox='0 0 24 24' focusable='false' role='img'%3E%3Cpath fill='currentColor' d='M6.53 5.47a.75.75 0 0 0-1.06 1.06L10.94 12l-5.47 5.47a.75.75 0 1 0 1.06 1.06L12 13.06l5.47 5.47a.75.75 0 1 0 1.06-1.06L13.06 12l5.47-5.47a.75.75 0 0 0-1.06-1.06L12 10.94z'%3E%3C/path%3E%3C/svg%3E");
--dsc-chip-input-size: var(--ds-spacing-6);
--gap: calc((var(--dsc-chip-height) - var(--dsc-chip-input-size)) / 2); /* Distance between edge of input and chip */

align-items: center;
background: var(--dsc-chip-background);
Expand All @@ -20,15 +28,20 @@
cursor: pointer;
display: inline-flex;
font-family: inherit;
gap: var(--gap);
line-height: var(--ds-line-height-sm);
margin: 0;
min-height: var(--dsc-chip-height);
padding: var(--dsc-chip-padding);
padding: 0 var(--ds-spacing-3);
text-decoration: none;

@composes ds-focus from './base/base.css';

&:not([data-size]) {
font-size: var(--ds-font-size-minus-1);
}

/* Make focus ring also when input inside is focused */
/* Show focus ring when input inside is focused by keyboard interaction */
&:has(:focus-visible) {
@composes ds-focus--visible from './base/base.css';
}
Expand All @@ -40,92 +53,54 @@
opacity: var(--ds-disabled-opacity);
}

&:has(input[type='checkbox']) {
--dsc-chip-border-radius: var(--ds-border-radius-md);
--dsc-chip-padding: 0 var(--ds-spacing-2) 0 var(--ds-spacing-3);
&[data-removable] {
padding-inline-end: var(--gap);

&::after {
content: '';
background: currentcolor;
height: var(--dsc-chip-icon-size);
mask: center / contain no-repeat var(--dsc-chip-icon-url);
width: var(--dsc-chip-icon-size);
}
}

&[data-removable]::after {
--gap: calc((var(--dsc-chip-height) - var(--dsc-chip-icon-size)) / 2); /* Gap is based on remaining space between icon and edge */
&:has(input[type='radio']) {
padding-inline-start: var(--gap);
}

background: currentcolor;
content: '';
height: var(--dsc-chip-icon-size);
margin: 0 calc(var(--gap) * -1) 0 var(--gap);
mask: center / contain no-repeat
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' fill='none' viewBox='0 0 24 24' focusable='false' role='img'%3E%3Cpath fill='currentColor' d='M6.53 5.47a.75.75 0 0 0-1.06 1.06L10.94 12l-5.47 5.47a.75.75 0 1 0 1.06 1.06L12 13.06l5.47 5.47a.75.75 0 1 0 1.06-1.06L13.06 12l5.47-5.47a.75.75 0 0 0-1.06-1.06L12 10.94z'%3E%3C/path%3E%3C/svg%3E");
width: var(--dsc-chip-icon-size);
&:has(input[type='checkbox']) {
--dsc-chip-border-radius: var(--ds-border-radius-md);
padding-inline: var(--gap);
}

& > input {
--gap: calc((var(--dsc-chip-height) - var(--dsc-chip-input-size)) / 2); /* Gap is based on remaining space between input and edge */

appearance: none;
background: none;
border: 2px solid;
box-sizing: border-box;
color: var(--dsc-chip-input-color);
height: var(--dsc-chip-input-size);
margin: 0 var(--gap) 0 calc(var(--gap) * -1);
outline: none;
width: var(--dsc-chip-input-size);

&[type='radio'] {
border-radius: var(--ds-border-radius-full);
}

&[type='radio']:checked {
border-width: calc(var(--dsc-chip-input-size) / 3.5); /* Matches Figma */
}

&[type='checkbox'] {
border-radius: var(--ds-border-radius-sm);
}

&[type='checkbox']:checked {
background: currentcolor;
mask: center / cover no-repeat
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M24 0H0v24h24V0Zm-4.44 8.56a1.5 1.5 0 0 0-2.12-2.12L10 13.88l-3.44-3.44a1.5 1.5 0 0 0-2.12 2.12l4.5 4.5a1.5 1.5 0 0 0 2.12 0l8.5-8.5Z'/%3E%3C/svg%3E");
}
--dsc-input-background--checked: var(--dsc-chip-color);
--dsc-input-background: transparent;
--dsc-input-border-color--checked: var(--dsc-chip-color);
--dsc-input-border-color: var(--dsc-chip-input-color);
--dsc-input-color--checked: var(--dsc-chip-input-color--checked);
--dsc-input-size--toggle: var(--dsc-chip-input-size);
}

&:has(input:checked),
&[data-removable] {
--dsc-chip-background: var(--ds-color-accent-base-default);
--dsc-chip-border-color: transparent;
--dsc-chip-color: var(--ds-color-accent-contrast-default);
--dsc-chip-input-color: currentcolor;
--dsc-chip-color: var(--dsc-chip-color--checked);
--dsc-chip-background: var(--dsc-chip-background--checked);
--dsc-chip-border-color: var(--dsc-chip-border-color--checked);
--dsc-chip-background--hover: var(--dsc-chip-background--checked--hover);
--dsc-chip-background--active: var(--dsc-chip-background--checked--active);
}

/* Only use hover for non-touch devices to prevent sticky-hovering */
@media (hover: hover) and (pointer: fine) {
&:where(:not(:disabled, :has(input:disabled), [aria-disabled='true'])) {
&:not(:has(:disabled, [aria-disabled='true'])) {
&:hover {
--dsc-chip-background: var(--ds-color-accent-surface-hover);
--dsc-chip-border-color: var(--ds-color-accent-border-default);
--dsc-chip-color: var(--ds-color-accent-text-default);
--dsc-chip-input-color: var(--ds-color-accent-border-strong);
--dsc-chip-background: var(--dsc-chip-background--hover);
}

&:active {
--dsc-chip-background: var(--ds-color-accent-surface-active);
--dsc-chip-border-color: var(--ds-color-accent-border-strong);
--dsc-chip-input-color: var(--ds-color-accent-border-strong);
}

&[data-removable]:hover,
&:has(input:checked):hover {
--dsc-chip-background: var(--ds-color-accent-base-hover);
--dsc-chip-border-color: transparent;
--dsc-chip-color: var(--ds-color-accent-contrast-default);
--dsc-chip-input-color: currentcolor;
}

&[data-removable]:active,
&:has(input:checked):active {
--dsc-chip-background: var(--ds-color-accent-base-active);
--dsc-chip-border-color: transparent;
--dsc-chip-color: var(--ds-color-accent-contrast-default);
--dsc-chip-background: var(--dsc-chip-background--active);
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions packages/css/field.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@
& input {
grid-column: 1; /* Always place input in column 1 */
grid-row: 1; /* Always place input in row 1 */
outline: none;
box-shadow: none;
}

&:not(:has([readonly], [aria-disabled='true'], :disabled)) label {
Expand Down
7 changes: 6 additions & 1 deletion packages/css/input.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,24 @@
}

/**
* Toggle inputs
* Toggle inputs and select
*/
&:read-only:not([readonly], [aria-disabled='true'], :disabled) {
cursor: pointer;
}

/**
* Toggle inputs
*/
&[type='checkbox'],
&[type='radio'] {
--dsc-input-border-width: var(--dsc-input-border-width--toggle);
--dsc-input-padding: calc(var(--ds-sizing-1) / 2);
--dsc-input-size: var(--dsc-input-size--toggle);

flex-shrink: 0; /* Never shrink a toggle input */
line-height: inherit; /* Inherit line height so we can use 1lh to align with first line of label */
translate: 0 calc((1lh - var(--dsc-input-size)) / 2); /* Align with first line of label text */
width: var(--dsc-input-size);
}

Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/components/Chip/Chips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import cl from 'clsx/lite';
import { forwardRef } from 'react';
import type { ButtonHTMLAttributes, InputHTMLAttributes } from 'react';
import type { DefaultProps } from '../../types';
import { Input } from '../form/Input';

type ChipBaseProps = {
/**
Expand Down Expand Up @@ -70,7 +71,7 @@ export const ChipCheckbox = forwardRef<HTMLLabelElement, ChipCheckboxProps>(
data-size={size}
ref={ref}
>
<input {...rest} type={inputType} />
<Input {...rest} type={inputType} />
<Slottable>{children}</Slottable>
</Component>
);
Expand Down

0 comments on commit ce23f32

Please sign in to comment.