fix input clearable button styles

This commit is contained in:
jeffvli
2026-07-29 21:13:12 -07:00
parent 77ea7f9c75
commit 75c43d6724
14 changed files with 229 additions and 35 deletions
@@ -17,6 +17,10 @@
color: var(--theme-colors-foreground); color: var(--theme-colors-foreground);
background: var(--theme-colors-background); background: var(--theme-colors-background);
} }
&.clearable {
padding-right: 4rem;
}
} }
.input:focus, .input:focus,
@@ -53,3 +57,20 @@
.option:hover { .option:hover {
background: lighten(var(--theme-colors-surface), 5%); background: lighten(var(--theme-colors-surface), 5%);
} }
.clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
}
@@ -1,6 +1,7 @@
import type { AutocompleteProps as MantineAutocompleteProps } from '@mantine/core'; import type { AutocompleteProps as MantineAutocompleteProps } from '@mantine/core';
import { Autocomplete as MantineAutocomplete } from '@mantine/core'; import { Autocomplete as MantineAutocomplete } from '@mantine/core';
import clsx from 'clsx';
import { CSSProperties, forwardRef } from 'react'; import { CSSProperties, forwardRef } from 'react';
import styles from './autocomplete.module.css'; import styles from './autocomplete.module.css';
@@ -14,6 +15,7 @@ export const Autocomplete = forwardRef<HTMLInputElement, AutocompleteProps>(
( (
{ {
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
size = 'sm', size = 'sm',
style, style,
@@ -28,13 +30,21 @@ export const Autocomplete = forwardRef<HTMLInputElement, AutocompleteProps>(
classNames={{ classNames={{
description: styles.description, description: styles.description,
dropdown: styles.dropdown, dropdown: styles.dropdown,
input: styles.input, input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label, label: styles.label,
option: styles.option, option: styles.option,
root: styles.root, root: styles.root,
section: styles.section, section: styles.section,
...classNames, ...classNames,
}} }}
clearable={clearable}
clearButtonProps={{
classNames: {
root: styles.clearButton,
},
}}
ref={ref} ref={ref}
size={size} size={size}
spellCheck={false} spellCheck={false}
@@ -8,6 +8,10 @@
color: var(--theme-colors-surface-foreground); color: var(--theme-colors-surface-foreground);
background: var(--theme-colors-surface); background: var(--theme-colors-surface);
border: 1px solid transparent; border: 1px solid transparent;
&.clearable {
padding-right: 4rem;
}
} }
.section { .section {
@@ -27,3 +31,20 @@
font-size: var(--theme-font-size-xs); font-size: var(--theme-font-size-xs);
color: var(--theme-colors-foreground-muted); color: var(--theme-colors-foreground-muted);
} }
.clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
}
@@ -7,6 +7,7 @@ import {
DateInput as MantineDateInput, DateInput as MantineDateInput,
DateTimePicker as MantineDateTimeInput, DateTimePicker as MantineDateTimeInput,
} from '@mantine/dates'; } from '@mantine/dates';
import clsx from 'clsx';
import styles from './date-picker.module.css'; import styles from './date-picker.module.css';
@@ -17,6 +18,7 @@ interface DateInputProps extends MantineDateInputProps {
export const DateInput = ({ export const DateInput = ({
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
size = 'sm', size = 'sm',
style, style,
@@ -27,13 +29,19 @@ export const DateInput = ({
<MantineDateInput <MantineDateInput
classNames={{ classNames={{
description: styles.description, description: styles.description,
input: styles.input, input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label, label: styles.label,
required: styles.required, required: styles.required,
root: styles.root, root: styles.root,
section: styles.section, section: styles.section,
...classNames, ...classNames,
}} }}
clearable={clearable}
clearButtonProps={{
className: styles.clearButton,
}}
size={size} size={size}
style={{ maxWidth, width, ...style }} style={{ maxWidth, width, ...style }}
{...props} {...props}
@@ -48,6 +56,7 @@ interface DateTimeInputProps extends MantineDateTimeInputProps {
export const DateTimeInput = ({ export const DateTimeInput = ({
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
size = 'sm', size = 'sm',
style, style,
@@ -58,13 +67,19 @@ export const DateTimeInput = ({
<MantineDateTimeInput <MantineDateTimeInput
classNames={{ classNames={{
description: styles.description, description: styles.description,
input: styles.input, input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label, label: styles.label,
required: styles.required, required: styles.required,
root: styles.root, root: styles.root,
section: styles.section, section: styles.section,
...classNames, ...classNames,
}} }}
clearable={clearable}
clearButtonProps={{
className: styles.clearButton,
}}
size={size} size={size}
style={{ maxWidth, width, ...style }} style={{ maxWidth, width, ...style }}
{...props} {...props}
@@ -8,6 +8,10 @@
color: var(--theme-colors-surface-foreground); color: var(--theme-colors-surface-foreground);
background: var(--theme-colors-surface); background: var(--theme-colors-surface);
border: 1px solid transparent; border: 1px solid transparent;
&.clearable {
padding-right: 4rem;
}
} }
.section { .section {
@@ -27,3 +31,20 @@
font-size: var(--theme-font-size-xs); font-size: var(--theme-font-size-xs);
color: var(--theme-colors-foreground-muted); color: var(--theme-colors-foreground-muted);
} }
.clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
}
@@ -1,6 +1,7 @@
import type { DateTimePickerProps as MantineDateTimePickerProps } from '@mantine/dates'; import type { DateTimePickerProps as MantineDateTimePickerProps } from '@mantine/dates';
import { DateTimePicker as MantineDateTimePicker } from '@mantine/dates'; import { DateTimePicker as MantineDateTimePicker } from '@mantine/dates';
import clsx from 'clsx';
import styles from './date-time-picker.module.css'; import styles from './date-time-picker.module.css';
@@ -11,6 +12,7 @@ interface DateTimePickerProps extends MantineDateTimePickerProps {
export const DateTimePicker = ({ export const DateTimePicker = ({
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
popoverProps, popoverProps,
size = 'sm', size = 'sm',
@@ -22,13 +24,19 @@ export const DateTimePicker = ({
<MantineDateTimePicker <MantineDateTimePicker
classNames={{ classNames={{
description: styles.description, description: styles.description,
input: styles.input, input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label, label: styles.label,
required: styles.required, required: styles.required,
root: styles.root, root: styles.root,
section: styles.section, section: styles.section,
...classNames, ...classNames,
}} }}
clearable={clearable}
clearButtonProps={{
className: styles.clearButton,
}}
popoverProps={{ withinPortal: true, ...popoverProps }} popoverProps={{ withinPortal: true, ...popoverProps }}
size={size} size={size}
style={{ maxWidth, width, ...style }} style={{ maxWidth, width, ...style }}
@@ -19,6 +19,10 @@
color: var(--theme-colors-foreground); color: var(--theme-colors-foreground);
background: var(--theme-colors-background); background: var(--theme-colors-background);
} }
&.clearable {
padding-right: 4rem;
}
} }
.input:focus, .input:focus,
@@ -44,3 +48,20 @@
font-size: var(--theme-font-size-xs); font-size: var(--theme-font-size-xs);
color: var(--theme-colors-foreground-muted); color: var(--theme-colors-foreground-muted);
} }
.clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
}
@@ -2,6 +2,7 @@ import {
FileInput as MantineFileInput, FileInput as MantineFileInput,
FileInputProps as MantineFileInputProps, FileInputProps as MantineFileInputProps,
} from '@mantine/core'; } from '@mantine/core';
import clsx from 'clsx';
import { CSSProperties, forwardRef } from 'react'; import { CSSProperties, forwardRef } from 'react';
import styles from './file-input.module.css'; import styles from './file-input.module.css';
@@ -16,6 +17,7 @@ export const FileInput = forwardRef<HTMLButtonElement, FileInputProps>(
{ {
children, children,
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
size = 'sm', size = 'sm',
style, style,
@@ -29,7 +31,9 @@ export const FileInput = forwardRef<HTMLButtonElement, FileInputProps>(
<MantineFileInput <MantineFileInput
classNames={{ classNames={{
description: styles.description, description: styles.description,
input: styles.input, input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label, label: styles.label,
required: styles.required, required: styles.required,
root: styles.root, root: styles.root,
@@ -37,6 +41,10 @@ export const FileInput = forwardRef<HTMLButtonElement, FileInputProps>(
wrapper: styles.wrapper, wrapper: styles.wrapper,
...classNames, ...classNames,
}} }}
clearable={clearable}
clearButtonProps={{
className: styles.clearButton,
}}
ref={ref} ref={ref}
size={size} size={size}
style={{ maxWidth, width, ...style }} style={{ maxWidth, width, ...style }}
@@ -34,6 +34,10 @@
color: var(--theme-colors-foreground); color: var(--theme-colors-foreground);
background: var(--theme-colors-background); background: var(--theme-colors-background);
} }
&.clearable {
padding-right: 4rem;
}
} }
.input:focus, .input:focus,
@@ -75,5 +79,18 @@
} }
.clear-button { .clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important; background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
} }
@@ -2,6 +2,7 @@ import {
MultiSelect as MantineMultiSelect, MultiSelect as MantineMultiSelect,
MultiSelectProps as MantineMultiSelectProps, MultiSelectProps as MantineMultiSelectProps,
} from '@mantine/core'; } from '@mantine/core';
import clsx from 'clsx';
import { CSSProperties, useMemo } from 'react'; import { CSSProperties, useMemo } from 'react';
import styles from './multi-select.module.css'; import styles from './multi-select.module.css';
@@ -11,34 +12,35 @@ export interface MultiSelectProps extends MantineMultiSelectProps {
width?: CSSProperties['width']; width?: CSSProperties['width'];
} }
const defaultClassNames = {
description: styles.description,
dropdown: styles.dropdown,
input: styles.input,
label: styles.label,
option: styles.option,
pill: styles.pill,
pillsList: styles.pillsList,
root: styles.root,
};
const defaultClearButtonProps = { const defaultClearButtonProps = {
classNames: { classNames: {
root: styles.clearButton, root: styles.clearButton,
}, },
variant: 'transparent' as const,
}; };
export const MultiSelect = ({ export const MultiSelect = ({
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
variant = 'default', variant = 'default',
width, width,
...props ...props
}: MultiSelectProps) => { }: MultiSelectProps) => {
const mergedClassNames = useMemo( const mergedClassNames = useMemo(
() => (classNames ? { ...defaultClassNames, ...classNames } : defaultClassNames), () => ({
[classNames], description: styles.description,
dropdown: styles.dropdown,
input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label,
option: styles.option,
pill: styles.pill,
pillsList: styles.pillsList,
root: styles.root,
...classNames,
}),
[classNames, clearable],
); );
const style = useMemo( const style = useMemo(
@@ -49,6 +51,7 @@ export const MultiSelect = ({
return ( return (
<MantineMultiSelect <MantineMultiSelect
classNames={mergedClassNames} classNames={mergedClassNames}
clearable={clearable}
clearButtonProps={defaultClearButtonProps} clearButtonProps={defaultClearButtonProps}
style={style} style={style}
variant={variant} variant={variant}
@@ -17,6 +17,10 @@
color: var(--theme-colors-foreground); color: var(--theme-colors-foreground);
background: var(--theme-colors-background); background: var(--theme-colors-background);
} }
&.clearable {
padding-right: 4rem;
}
} }
.input:focus, .input:focus,
@@ -63,3 +67,20 @@
font-size: var(--theme-font-size-xs); font-size: var(--theme-font-size-xs);
color: var(--theme-colors-foreground-muted); color: var(--theme-colors-foreground-muted);
} }
.clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
}
+9 -1
View File
@@ -1,6 +1,7 @@
import type { SelectProps as MantineSelectProps } from '@mantine/core'; import type { SelectProps as MantineSelectProps } from '@mantine/core';
import { Select as MantineSelect } from '@mantine/core'; import { Select as MantineSelect } from '@mantine/core';
import clsx from 'clsx';
import { CSSProperties } from 'react'; import { CSSProperties } from 'react';
import styles from './select.module.css'; import styles from './select.module.css';
@@ -25,7 +26,9 @@ export const Select = ({
classNames={{ classNames={{
description: styles.description, description: styles.description,
dropdown: styles.dropdown, dropdown: styles.dropdown,
input: styles.input, input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
label: styles.label, label: styles.label,
option: styles.option, option: styles.option,
root: styles.root, root: styles.root,
@@ -33,6 +36,11 @@ export const Select = ({
...classNames, ...classNames,
}} }}
clearable={clearable} clearable={clearable}
clearButtonProps={{
classNames: {
root: styles.clearButton,
},
}}
spellCheck={false} spellCheck={false}
style={{ maxWidth, width }} style={{ maxWidth, width }}
variant={variant} variant={variant}
@@ -38,6 +38,10 @@
background: var(--theme-colors-surface); background: var(--theme-colors-surface);
} }
} }
&.clearable {
padding-right: 4rem;
}
} }
.input:focus-within { .input:focus-within {
@@ -68,5 +72,18 @@
} }
.clear-button { .clear-button {
color: var(--theme-colors-foreground) !important;
background: transparent !important; background: transparent !important;
&:hover,
&:active,
&:focus-visible {
@mixin dark {
background-color: lighten(var(--theme-colors-background), 10%) !important;
}
@mixin light {
background-color: darken(var(--theme-colors-background), 5%) !important;
}
}
} }
+18 -15
View File
@@ -2,6 +2,7 @@ import {
TagsInput as MantineTagsInput, TagsInput as MantineTagsInput,
TagsInputProps as MantineTagsInputProps, TagsInputProps as MantineTagsInputProps,
} from '@mantine/core'; } from '@mantine/core';
import clsx from 'clsx';
import { CSSProperties, useMemo } from 'react'; import { CSSProperties, useMemo } from 'react';
import styles from './tags-input.module.css'; import styles from './tags-input.module.css';
@@ -11,35 +12,36 @@ export interface TagsInputProps extends MantineTagsInputProps {
width?: CSSProperties['width']; width?: CSSProperties['width'];
} }
const defaultClassNames = {
description: styles.description,
dropdown: styles.dropdown,
input: styles.input,
inputField: styles.inputField,
label: styles.label,
option: styles.option,
pill: styles.pill,
pillsList: styles.pillsList,
root: styles.root,
};
const defaultClearButtonProps = { const defaultClearButtonProps = {
classNames: { classNames: {
root: styles.clearButton, root: styles.clearButton,
}, },
variant: 'transparent' as const,
}; };
export const TagsInput = ({ export const TagsInput = ({
classNames, classNames,
clearable = false,
maxWidth, maxWidth,
variant = 'default', variant = 'default',
width, width,
...props ...props
}: TagsInputProps) => { }: TagsInputProps) => {
const mergedClassNames = useMemo( const mergedClassNames = useMemo(
() => (classNames ? { ...defaultClassNames, ...classNames } : defaultClassNames), () => ({
[classNames], description: styles.description,
dropdown: styles.dropdown,
input: clsx(styles.input, {
[styles.clearable]: clearable,
}),
inputField: styles.inputField,
label: styles.label,
option: styles.option,
pill: styles.pill,
pillsList: styles.pillsList,
root: styles.root,
...classNames,
}),
[classNames, clearable],
); );
const style = useMemo( const style = useMemo(
@@ -50,6 +52,7 @@ export const TagsInput = ({
return ( return (
<MantineTagsInput <MantineTagsInput
classNames={mergedClassNames} classNames={mergedClassNames}
clearable={clearable}
clearButtonProps={defaultClearButtonProps} clearButtonProps={defaultClearButtonProps}
style={style} style={style}
variant={variant} variant={variant}