fix: make use of design system label component in select

minor tweaks to make sure input and select behaves consistently
This commit is contained in:
Christian Andolf
2025-06-13 16:23:11 +02:00
parent 4a00527d1d
commit 603c7dd2bf
7 changed files with 50 additions and 46 deletions

View File

@@ -6,7 +6,7 @@
display: grid; display: grid;
min-width: 0; /* allow shrinkage */ min-width: 0; /* allow shrinkage */
height: 56px; height: 56px;
padding: var(--Space-x15); padding: 0 var(--Space-x15);
box-sizing: border-box; box-sizing: border-box;
cursor: text; cursor: text;
@@ -43,7 +43,7 @@
&:focus, &:focus,
&:placeholder-shown, &:placeholder-shown,
&[value]:not([value='']) { &[value]:not([value='']) {
height: 18px; height: 24px;
outline: none; outline: none;
} }
@@ -54,7 +54,7 @@
@media (hover: hover) { @media (hover: hover) {
.input:active:not(:disabled) { .input:active:not(:disabled) {
height: 18px; height: 24px;
outline: none; outline: none;
} }
} }

View File

@@ -2,11 +2,18 @@ import { labelVariants } from './variants'
import type { LabelProps } from './types' import type { LabelProps } from './types'
export function Label({ children, className, required, size }: LabelProps) { export function Label({
children,
className,
selected,
required,
size,
}: LabelProps) {
const classNames = labelVariants({ const classNames = labelVariants({
className, className,
size, size,
required, required,
selected,
}) })
return <span className={classNames}>{children}</span> return <span className={classNames}>{children}</span>

View File

@@ -43,23 +43,22 @@
content: ' *'; content: ' *';
} }
input:focus, input:focus ~ .label,
input:placeholder-shown, input:placeholder-shown ~ .label,
input[value]:not([value='']), input[value]:not([value='']) ~ .label,
textarea:focus, textarea:focus ~ .label,
textarea:placeholder-shown, textarea:placeholder-shown ~ .label,
textarea[value]:not([value='']) { textarea[value]:not([value='']) ~ .label,
& ~ .label { .selected {
font-family: var(--Label-Font-family), var(--Label-Font-fallback); font-family: var(--Label-Font-family), var(--Label-Font-fallback);
font-size: var(--Label-Size); font-size: var(--Label-Size);
font-weight: var(--Label-Font-weight); font-weight: var(--Label-Font-weight);
letter-spacing: var(--Label-Letter-spacing); letter-spacing: var(--Label-Letter-spacing);
text-transform: unset; text-transform: unset;
line-height: 1.5; line-height: 1.5;
text-decoration: none; text-decoration: none;
margin-bottom: var(--Space-x05); margin-bottom: var(--Space-x025);
}
} }
input:disabled, input:disabled,
@@ -79,7 +78,7 @@ textarea:disabled {
line-height: 1.5; line-height: 1.5;
text-decoration: none; text-decoration: none;
margin-bottom: var(--Space-x05); margin-bottom: var(--Space-x025);
} }
} }

View File

@@ -12,6 +12,9 @@ export const labelVariants = cva(styles.label, {
required: { required: {
true: styles.required, true: styles.required,
}, },
selected: {
true: styles.selected,
},
}, },
defaultVariants: { defaultVariants: {
size: 'regular', size: 'regular',

View File

@@ -16,6 +16,7 @@ import type { SelectProps, SelectFilterProps } from './types'
import styles from './select.module.css' import styles from './select.module.css'
import { useState } from 'react' import { useState } from 'react'
import { Label } from '../Label'
export function Select({ export function Select({
name, name,
@@ -64,15 +65,12 @@ export function Select({
{({ selectedText }) => { {({ selectedText }) => {
return ( return (
<> <>
<Typography <Label
variant={ className={styles.label}
selectedText || isOpen selected={Boolean(selectedText || isOpen)}
? 'Label/xsRegular'
: 'Body/Paragraph/mdRegular'
}
> >
<span className={styles.label}>{label}</span> {label}
</Typography> </Label>
<Typography variant="Body/Paragraph/mdRegular"> <Typography variant="Body/Paragraph/mdRegular">
<span className={styles.selectedText}>{selectedText}</span> <span className={styles.selectedText}>{selectedText}</span>
</Typography> </Typography>

View File

@@ -7,7 +7,7 @@ import {
Key, Key,
ListBox, ListBox,
Popover, Popover,
Label, Label as AriaLabel,
ComboBoxStateContext, ComboBoxStateContext,
} from 'react-aria-components' } from 'react-aria-components'
import { import {
@@ -26,6 +26,7 @@ import { SelectItem } from './SelectItem'
import type { SelectFilterProps } from './types' import type { SelectFilterProps } from './types'
import styles from './select.module.css' import styles from './select.module.css'
import { Label } from '../Label'
/** /**
* ComboBoxInner * ComboBoxInner
@@ -124,7 +125,7 @@ export function SelectFilter({
{...props} {...props}
> >
<ComboBoxInner inputRef={inputRef}> <ComboBoxInner inputRef={inputRef}>
<Label> <AriaLabel>
{icon ? ( {icon ? (
<MaterialIcon <MaterialIcon
icon={icon} icon={icon}
@@ -135,13 +136,9 @@ export function SelectFilter({
) : null} ) : null}
<span className={styles.displayText}> <span className={styles.displayText}>
<Typography <Label className={styles.label} selected={Boolean(focus || value)}>
variant={ {label}
focus || value ? 'Label/xsRegular' : 'Body/Paragraph/mdRegular' </Label>
}
>
<span className={styles.label}>{label}</span>
</Typography>
<Typography variant="Body/Paragraph/mdRegular"> <Typography variant="Body/Paragraph/mdRegular">
<Input <Input
ref={inputRef} ref={inputRef}
@@ -151,7 +148,7 @@ export function SelectFilter({
/> />
</Typography> </Typography>
</span> </span>
</Label> </AriaLabel>
<Button className={styles.button}> <Button className={styles.button}>
<MaterialIcon <MaterialIcon
icon="chevron_right" icon="chevron_right"

View File

@@ -4,6 +4,7 @@
border: 1px solid var(--Border-Interactive-Default); border: 1px solid var(--Border-Interactive-Default);
border-radius: var(--Corner-radius-md); border-radius: var(--Corner-radius-md);
height: 56px; height: 56px;
box-sizing: border-box;
&[data-required] .label::after { &[data-required] .label::after {
content: ' *'; content: ' *';
@@ -14,7 +15,7 @@
} }
.selectedText { .selectedText {
min-height: 18px; min-height: 24px;
} }
} }
&[data-focused] { &[data-focused] {
@@ -26,7 +27,7 @@
outline: none; outline: none;
} }
.input { .input {
min-height: 18px; min-height: 24px;
} }
.label { .label {
color: var(--Text-Interactive-Focus); color: var(--Text-Interactive-Focus);
@@ -58,8 +59,8 @@
align-items: center; align-items: center;
gap: var(--Space-x1); gap: var(--Space-x1);
width: 100%; width: 100%;
height: 56px; height: 100%;
padding: var(--Space-x15); padding: 0 var(--Space-x15);
box-sizing: border-box; box-sizing: border-box;
.button { .button {
@@ -83,7 +84,7 @@
width: 100%; width: 100%;
&[value]:not([value='']) { &[value]:not([value='']) {
min-height: 18px; min-height: 24px;
} }
} }
@@ -94,13 +95,12 @@
} }
.selectedText:not(:empty) { .selectedText:not(:empty) {
min-height: 18px; min-height: 24px;
} }
.displayText { .displayText {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: calc(var(--Space-x05) / 2);
flex: 1; flex: 1;
justify-content: center; justify-content: center;
height: 100%; height: 100%;