* feat: 447 Refactored 'progress' intent to be 'prompt' as now white. Added yellow 'selected' intent * feat: 447 Colour consolidation * feat: 447 Colour consolidation extra renaming * feat: 447 Fixing specified red colours * feat: 447 Removed unused darker red * feat: 447 Documenting additional colours in storybook * feat: 447 Buttons updated (except 'accent', which will probably get removed when navs built) * feat: 447 Text inputs updated * feat:frontend-monorepo-447: Trading nav * feat:frontend-monorepo-447: Updated toggle button colours * feat:frontend-monorepo-447: Custom checkboxes * feat:frontend-monorepo-447: Tweaks to radio buttons * feat:frontend-monorepo-447: Input dates get dark color scheme in dark mode * feat:frontend-monorepo-447: Dropdown updates * feat:frontend-monorepo-447: Icon menu * feat:frontend-monorepo-447: Focus visual styles moved to focus-visible for radios and toggle * feat:frontend-monorepo-447: Tweak to focus styles for text input and textarea * feat:frontend-monorepo-447: Labeled input * feat:frontend-monorepo-447: Labeled input description red when in error * feat:frontend-monorepo-447: Tooltip visual update * feat:frontend-monorepo-447: Added disabled state to checkbox * feat:frontend-monorepo-447: Custom select with radix * feat:frontend-monorepo-447: Reverted back to native Select for a11y concerns * feat:frontend-monorepo-447: Added visual cue for dropdown items when multiple can be selected * feat:frontend-monorepo-447: Removed shadow from buttons in Explorer where it looked wrong * feat:frontend-monorepo-447: Added box shadow classes into tailwind theme * feat:frontend-monorepo-447: Colour primitives documentation updated * feat:frontend-monorepo-447: Cleaning up box shadow use further * feat:frontend-monorepo-447: Intents util updated * feat:frontend-monorepo-447: Dialog component updated * feat:frontend-monorepo-447: Callout component updated * feat:frontend-monorepo-447: Adjusted apps to handle toolkit changes * feat:frontend-monorepo-447: Moved tabs to ui-toolkit and styled * feat:frontend-monorepo-447: Fixed ui-toolkit tests * feat:frontend-monorepo-447: Token eth wallet made dark to support new buttons * feat:frontend-monorepo-447: Ran prettier * frontend-monorepo-447: Simplified button class functions and exported for use on other elements * frontend-monorepo-447: Used newly exported button classes on Link elements in eth-wallet * frontend-monorepo-447: Moved trading nav from ui-toolkit to trading app * frontend-monorepo-447: Simplified intents and updated stories * frontend-monorepo-447: Using classnames in requested spot * frontend-monorepo-447: Removed unnecessary 'asChild' prop on dropdown triggers * frontend-monorepo-447: Made use of the XPrimitive Radix naming convention * frontend-monorepo-447: Simplified types in 'getButtonClasses' * frontend-monorepo-447: Added 'asChild' to dropdown trigger to avoid nested buttons * frontend-monorepo-447: Moved input label and description into Formgroup component. Refactored based on tweaked structure * frontend-monorepo-447: Externally linked input label * frontend-monorepo-447: Adding correct text colours to Intent.None backgrounds * frontend-monorepo-447: Improved intent function name * frontend-monorepo-447: Removed new navbar until implementation ticket is picked up * frontend-monorepo-447: using testing-library/user-event for tab click unit tests * frontend-monorepo-447: Removed unused button import * frontend-monorepo-447: Little extra use of classnames in form-group.tsx * feat: make navbar pink for light mode * fix: problem with theme not switching when dependent in js on theme value * fix: bg of row hover * fix: dont use vega pink for sell red * fix: type error in generate orders func * fix: lint Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
175 lines
3.8 KiB
TypeScript
175 lines
3.8 KiB
TypeScript
import type { InputHTMLAttributes, ReactNode } from 'react';
|
|
import { forwardRef } from 'react';
|
|
import classNames from 'classnames';
|
|
import type { IconName } from '../icon';
|
|
import { Icon } from '../icon';
|
|
import { defaultFormElement } from '../../utils/shared';
|
|
|
|
type InputRootProps = InputHTMLAttributes<HTMLInputElement> & {
|
|
hasError?: boolean;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
};
|
|
|
|
type NoPrepend = {
|
|
prependIconName?: never;
|
|
prependIconDescription?: string;
|
|
prependElement?: never;
|
|
};
|
|
|
|
type NoAppend = {
|
|
appendIconName?: never;
|
|
appendIconDescription?: string;
|
|
appendElement?: never;
|
|
};
|
|
|
|
type InputPrepend = NoAppend &
|
|
(
|
|
| NoPrepend
|
|
| {
|
|
prependIconName: IconName;
|
|
prependIconDescription?: string;
|
|
prependElement?: never;
|
|
}
|
|
| {
|
|
prependIconName?: never;
|
|
prependIconDescription?: never;
|
|
prependElement: ReactNode;
|
|
}
|
|
);
|
|
|
|
type InputAppend = NoPrepend &
|
|
(
|
|
| NoAppend
|
|
| {
|
|
appendIconName: IconName;
|
|
appendIconDescription?: string;
|
|
appendElement?: never;
|
|
}
|
|
| {
|
|
appendIconName?: never;
|
|
appendIconDescription?: never;
|
|
appendElement: ReactNode;
|
|
}
|
|
);
|
|
|
|
type AffixProps = InputPrepend | InputAppend;
|
|
|
|
type InputProps = InputRootProps & AffixProps;
|
|
|
|
export const inputStyle = ({
|
|
style,
|
|
disabled,
|
|
}: {
|
|
style?: React.CSSProperties;
|
|
disabled?: boolean;
|
|
}) =>
|
|
disabled
|
|
? {
|
|
...style,
|
|
backgroundImage:
|
|
'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAAXNSR0IArs4c6QAAACNJREFUGFdjtLS0/M8ABcePH2eEsRlJl4BpBdHIuuFmEi0BABqjEQVjx/LTAAAAAElFTkSuQmCC)',
|
|
}
|
|
: style;
|
|
|
|
const getAffixElement = ({
|
|
prependElement,
|
|
prependIconName,
|
|
prependIconDescription,
|
|
appendElement,
|
|
appendIconName,
|
|
appendIconDescription,
|
|
}: Pick<InputProps, keyof AffixProps>) => {
|
|
const position = prependIconName || prependElement ? 'pre' : 'post';
|
|
|
|
const className = classNames(
|
|
['fill-black-60 dark:fill-white-60', 'absolute', 'z-10'],
|
|
{
|
|
'left-8': position === 'pre',
|
|
'right-8': position === 'post',
|
|
}
|
|
);
|
|
|
|
const element = prependElement || appendElement;
|
|
const iconName = prependIconName || appendIconName;
|
|
const iconDescription = prependIconDescription || appendIconDescription;
|
|
|
|
if (element) {
|
|
return <div className={className}>{element}</div>;
|
|
}
|
|
|
|
if (iconName) {
|
|
return (
|
|
<Icon
|
|
name={iconName}
|
|
className={className}
|
|
size={16}
|
|
aria-label={iconDescription}
|
|
aria-hidden={!iconDescription}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
export const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
(
|
|
{
|
|
prependIconName,
|
|
prependIconDescription,
|
|
appendIconName,
|
|
appendIconDescription,
|
|
prependElement,
|
|
appendElement,
|
|
className,
|
|
hasError,
|
|
...props
|
|
},
|
|
ref
|
|
) => {
|
|
const hasPrepended = !!(prependIconName || prependElement);
|
|
const hasAppended = !!(appendIconName || appendElement);
|
|
|
|
const inputClassName = classNames(
|
|
'appearance-none',
|
|
'h-28',
|
|
'dark:color-scheme-dark',
|
|
className,
|
|
{
|
|
'pl-28': hasPrepended,
|
|
'pr-28': hasAppended,
|
|
}
|
|
);
|
|
|
|
const input = (
|
|
<input
|
|
{...props}
|
|
ref={ref}
|
|
className={classNames(defaultFormElement(hasError), inputClassName)}
|
|
/>
|
|
);
|
|
|
|
const element = getAffixElement({
|
|
prependIconName,
|
|
prependIconDescription,
|
|
appendIconName,
|
|
appendIconDescription,
|
|
prependElement,
|
|
appendElement,
|
|
});
|
|
|
|
if (element) {
|
|
return (
|
|
<div className="flex items-center relative">
|
|
{hasPrepended && element}
|
|
{input}
|
|
{hasAppended && element}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return input;
|
|
}
|
|
);
|