[ui] make disabled color more consistent

pull/452/head
Yangshun Tay 2 years ago
parent 720759628d
commit 766bee0e0c

@ -6,6 +6,7 @@ import { trpc } from '~/utils/trpc';
type Props = Readonly<{
disabled?: boolean;
errorMessage?: string;
isLabelHidden?: boolean;
onSelect: (option: TypeaheadOption) => void;
placeHolder?: string;

@ -74,11 +74,18 @@ export function HiddenLabel() {
export function Disabled() {
return (
<div className="space-y-4">
<TextArea
disabled={true}
label="Comment"
placeholder="You can't type here, it's disabled. (Placeholder)"
/>
<TextArea
disabled={true}
label="Comment"
placeholder="You can't type here, it's disabled."
value="You can't type here, it's disabled. (Value)"
/>
</div>
);
}

@ -111,8 +111,14 @@ export function Disabled() {
<TextInput
disabled={true}
label="Disabled input"
placeholder="John Doe"
placeholder="John Doe (Placeholder)"
type="text"
/>
<TextInput
disabled={true}
label="Disabled input"
type="text"
value="John Doe (Value)"
/>
<TextInput
disabled={true}

@ -128,3 +128,57 @@ export function Required() {
/>
);
}
export function Disabled() {
return (
<Typeahead
disabled={true}
label="Author"
options={[]}
placeholder="John Doe"
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onSelect={() => {}}
/>
);
}
export function Error() {
const people = [
{ id: '1', label: 'Wade Cooper', value: '1' },
{ id: '2', label: 'Arlene Mccoy', value: '2' },
{ id: '3', label: 'Devon Webb', value: '3' },
{ id: '4', label: 'Tom Cook', value: '4' },
{ id: '5', label: 'Tanya Fox', value: '5' },
{ id: '6', label: 'Hellen Schmidt', value: '6' },
];
const [selectedEntry, setSelectedEntry] = useState<TypeaheadOption>(
people[0],
);
const [query, setQuery] = useState('');
const filteredPeople =
query === ''
? people
: people.filter((person) =>
person.label
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.toLowerCase().replace(/\s+/g, '')),
);
return (
<Typeahead
errorMessage={
selectedEntry.id === '1' ? 'Cannot select Wade Cooper' : undefined
}
label="Author"
options={filteredPeople}
required={true}
value={selectedEntry}
onQueryChange={setQuery}
onSelect={setSelectedEntry}
/>
);
}

@ -50,7 +50,7 @@ function CheckboxInput(
className={clsx(
'h-4 w-4 rounded border-slate-300',
disabled
? 'bg-slate-100 text-slate-400'
? 'bg-slate-50 text-slate-400'
: 'text-primary-600 focus:ring-primary-500',
)}
defaultChecked={defaultValue}

@ -88,10 +88,9 @@ function Select<T>(
aria-label={isLabelHidden ? label : undefined}
className={clsx(
display === 'block' && 'block w-full',
'rounded-md py-2 pl-3 pr-8 text-sm focus:outline-none',
'rounded-md py-2 pl-3 pr-8 text-sm focus:outline-none disabled:bg-slate-50 disabled:text-slate-500',
stateClasses[state],
borderClasses[borderStyle],
disabled && 'bg-slate-100',
)}
defaultValue={defaultValue != null ? String(defaultValue) : undefined}
disabled={disabled}

@ -108,9 +108,8 @@ function TextArea(
aria-describedby={hasError ? errorId : undefined}
aria-invalid={hasError ? true : undefined}
className={clsx(
'block w-full rounded-md text-sm',
'block w-full rounded-md text-sm disabled:bg-slate-50 disabled:text-slate-500',
stateClasses[state].textArea,
disabled && 'bg-slate-100',
resizeClasses[resize],
)}
defaultValue={defaultValue}

@ -143,7 +143,7 @@ function TextInput(
<div
className={clsx(
'flex w-full overflow-hidden rounded-md border text-sm focus-within:ring-1',
disabled && 'pointer-events-none select-none bg-slate-100',
disabled && 'pointer-events-none select-none bg-slate-50',
containerClass,
)}>
{(() => {
@ -178,9 +178,8 @@ function TextInput(
aria-describedby={hasError ? errorId : undefined}
aria-invalid={hasError ? true : undefined}
className={clsx(
'w-0 flex-1 border-none text-sm focus:outline-none focus:ring-0',
'w-0 flex-1 border-none text-sm focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:bg-transparent disabled:text-slate-500',
inputClass,
disabled && 'bg-transparent',
)}
defaultValue={defaultValue}
disabled={disabled}

@ -1,5 +1,6 @@
import clsx from 'clsx';
import type { InputHTMLAttributes } from 'react';
import { useId } from 'react';
import { Fragment, useState } from 'react';
import { Combobox, Transition } from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/20/solid';
@ -24,6 +25,7 @@ type Attributes = Pick<
>;
type Props = Readonly<{
errorMessage?: React.ReactNode;
isLabelHidden?: boolean;
label: string;
noResultsMessage?: string;
@ -39,6 +41,27 @@ type Props = Readonly<{
}> &
Readonly<Attributes>;
type State = 'error' | 'normal';
const stateClasses: Record<
State,
Readonly<{
container: string;
input: string;
}>
> = {
error: {
container:
'border-danger-300 focus-within:outline-none focus-within:ring-danger-500 focus-within:border-danger-500',
input: 'text-danger-900 placeholder-danger-300',
},
normal: {
container:
'focus-within:ring-primary-500 focus-within:border-primary-500 border-slate-300',
input: 'placeholder:text-slate-400',
},
};
const textSizes: Record<TypeaheadTextSize, string> = {
default: 'text-sm',
inherit: '',
@ -46,6 +69,7 @@ const textSizes: Record<TypeaheadTextSize, string> = {
export default function Typeahead({
disabled = false,
errorMessage,
isLabelHidden,
label,
noResultsMessage = 'No results',
@ -58,7 +82,11 @@ export default function Typeahead({
onSelect,
...props
}: Props) {
const hasError = errorMessage != null;
const errorId = useId();
const state: State = hasError ? 'error' : 'normal';
const [query, setQuery] = useState('');
return (
<div>
<Combobox
@ -102,14 +130,18 @@ export default function Typeahead({
<div className="relative">
<div
className={clsx(
'focus-visible:ring-offset-primary-300 relative w-full cursor-default overflow-hidden rounded-lg border border-slate-300 bg-white text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2',
'relative w-full cursor-default overflow-hidden rounded-md border text-left focus-within:ring-1',
disabled && 'pointer-events-none select-none bg-slate-50',
stateClasses[state].container,
textSizes[textSize],
)}>
<Combobox.Input
aria-describedby={hasError ? errorId : undefined}
className={clsx(
'w-full border-none py-2 pl-3 pr-10 leading-5 text-slate-900 focus:ring-0',
'w-full border-none py-2 pl-3 pr-10 leading-5 focus:ring-0',
stateClasses[state].input,
textSizes[textSize],
disabled && 'pointer-events-none select-none bg-slate-100',
'disabled:cursor-not-allowed disabled:bg-transparent disabled:text-slate-500',
)}
displayValue={(option) =>
(option as unknown as TypeaheadOption)?.label
@ -170,6 +202,11 @@ export default function Typeahead({
</Transition>
</div>
</Combobox>
{errorMessage && (
<p className="text-danger-600 mt-2 text-sm" id={errorId}>
{errorMessage}
</p>
)}
</div>
);
}

Loading…
Cancel
Save