Skip to content

Commit

Permalink
Merge pull request #1120 from kadena-community/feat/form-focus-styles
Browse files Browse the repository at this point in the history
Feat/form focus styles
  • Loading branch information
ferreroltd authored Nov 8, 2023
2 parents 20bd7b0 + 967c38f commit 3febd50
Show file tree
Hide file tree
Showing 20 changed files with 120 additions and 168 deletions.
5 changes: 5 additions & 0 deletions .changeset/mighty-shoes-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@kadena/react-ui': patch
---

Added focus state and improved visuals for inputs
4 changes: 2 additions & 2 deletions packages/apps/tools/src/pages/faucet/new/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ICommandResult } from '@kadena/chainweb-node-client';
import type { InputWrapperStatus } from '@kadena/react-ui';
import type { FormFieldStatus } from '@kadena/react-ui';
import {
Box,
Breadcrumbs,
Expand Down Expand Up @@ -88,7 +88,7 @@ const NewAccountFaucetPage: FC = () => {
const [pubKeys, setPubKeys] = useState<string[]>([]);
const [currentKey, setCurrentKey] = useState<string>('');
const [validRequestKey, setValidRequestKey] = useState<
InputWrapperStatus | undefined
FormFieldStatus | undefined
>();

const { data: accountName } = useQuery({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@/services/transfer-tracker/get-transfer-status';
import { validateRequestKey } from '@/services/utils/utils';
import { zodResolver } from '@hookform/resolvers/zod';
import type { InputWrapperStatus } from '@kadena/react-ui';
import type { FormFieldStatus } from '@kadena/react-ui';
import {
Breadcrumbs,
Button,
Expand Down Expand Up @@ -62,7 +62,7 @@ const CrossChainTransferTracker: FC = () => {
const [txError, setTxError] = useState<string>('');
const [inputError, setInputError] = useState<string>('');
const [validRequestKey, setValidRequestKey] = useState<
InputWrapperStatus | undefined
FormFieldStatus | undefined
>();
const drawerPanelRef = useRef<HTMLElement | null>(null);

Expand Down
46 changes: 40 additions & 6 deletions packages/libs/react-ui/src/components/Form/Form.css.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,54 @@
import { colorPalette } from '@theme/colors';
import { sprinkles } from '@theme/sprinkles.css';
import { darkThemeClass, vars } from '@theme/vars.css';
import { style } from '@vanilla-extract/css';
import { createVar, fallbackVar, style } from '@vanilla-extract/css';

export type FormFieldStatus = 'disabled' | 'positive' | 'warning' | 'negative';
export const statusColor = createVar();
export const statusOutlineColor = createVar();

export const baseOutlinedClass = style([
{
outline: `2px solid ${fallbackVar(
statusOutlineColor,
vars.colors.$gray30,
)}`,
selectors: {
[`${darkThemeClass} &`]: {
outline: `2px solid ${fallbackVar(
statusOutlineColor,
vars.colors.$gray60,
)}`,
},
},
},
]);

export const baseContainerClass = style([
sprinkles({
alignItems: 'stretch',
borderRadius: '$sm',
display: 'flex',
color: '$foreground',
overflow: 'hidden',
lineHeight: '$lg',
bg: {
lightMode: '$white',
darkMode: '$gray100',
},
}),
{
outline: `2px solid ${vars.colors.$gray30}`,
outlineOffset: '1px',
position: 'relative',
boxShadow: `0px 1px 0 0 ${colorPalette.$gray30}`,
outlineOffset: '2px',
selectors: {
[`${darkThemeClass} &`]: {
outline: `2px solid ${vars.colors.$gray60}`,
boxShadow: `0px 1px 0 0 ${colorPalette.$gray60}`,
},
'&:focus-within': {
outline: `2px solid ${fallbackVar(statusColor, vars.colors.$blue60)}`,
outlineOffset: '2px',
},
},
},
]);

// base container class
42 changes: 1 addition & 41 deletions packages/libs/react-ui/src/components/Form/Input/Input.css.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,6 @@
import { sprinkles } from '@theme/sprinkles.css';
import { darkThemeClass, vars } from '@theme/vars.css';
import { fallbackVar, style, styleVariants } from '@vanilla-extract/css';
import { statusColor } from '../InputWrapper/InputWrapper.css';

export const containerClass = style([
// base container class
sprinkles({
alignItems: 'stretch',
borderRadius: '$sm',
display: 'flex',
color: '$foreground',
overflow: 'hidden',
lineHeight: '$lg',
bg: {
lightMode: '$white',
darkMode: '$gray100',
},
}),
{
position: 'relative',
borderBottom: `1px solid ${fallbackVar(statusColor, vars.colors.$gray30)}`,
selectors: {
[`${darkThemeClass} &`]: {
borderBottom: `1px solid ${fallbackVar(
statusColor,
vars.colors.$gray60,
)}`,
},
'.inputGroup &': {
borderRadius: 0,
},
'.inputGroup &:first-child': {
borderTopRightRadius: vars.radii.$sm,
borderTopLeftRadius: vars.radii.$sm,
},
'.inputGroup &:last-child': {
borderBottomRightRadius: vars.radii.$sm,
borderBottomLeftRadius: vars.radii.$sm,
},
},
},
]);
import { style, styleVariants } from '@vanilla-extract/css';

export const disabledClass = style([
sprinkles({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ export const Dynamic: Story = {
icon: undefined,
type: 'text',
rightIcon: undefined,
leadingText: '',
leadingTextWidth: undefined,
leadingText: '',
outlined: false,
},
render: ({
Expand All @@ -147,8 +147,8 @@ export const Dynamic: Story = {
rightIcon={rightIcon}
onChange={onChange}
placeholder="This is a placeholder"
leadingText={leadingText}
leadingTextWidth={leadingTextWidth}
leadingText={leadingText}
outlined={outlined}
disabled={disabled}
type={type}
Expand Down
21 changes: 13 additions & 8 deletions packages/libs/react-ui/src/components/Form/Input/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { SystemIcon } from '@components/Icon';
import type { vars } from '@theme/vars.css';
import classNames from 'classnames';
import type { FC, InputHTMLAttributes } from 'react';
import React, { forwardRef } from 'react';
import type { vars } from 'src/styles';
import { baseOutlinedClass } from '../Form.css';
import React, { forwardRef, useContext } from 'react';
import { baseContainerClass, baseOutlinedClass } from '../Form.css';
import { InputWrapperContext } from '../InputWrapper/InputWrapper.context';
import {
containerClass,
disabledClass,
inputClass,
inputContainerClass,
Expand All @@ -20,9 +20,9 @@ export interface IInputProps
'as' | 'disabled' | 'children' | 'className' | 'id'
> {
leadingText?: string;
leadingTextWidth?: keyof typeof vars.sizes;
icon?: keyof typeof SystemIcon;
rightIcon?: keyof typeof SystemIcon;
leadingTextWidth?: keyof typeof vars.sizes;
disabled?: boolean;
type?: React.HTMLInputTypeAttribute;
ref?: React.ForwardedRef<HTMLInputElement>;
Expand All @@ -35,21 +35,26 @@ export const Input: FC<IInputProps> = forwardRef<HTMLInputElement, IInputProps>(
{
outlined,
leadingText,
leadingTextWidth,
icon,
rightIcon,
leadingTextWidth: propLeadingTextWidth,
disabled = false,
...rest
},
ref,
) {
const { status, leadingTextWidth: wrapperLeadingTextWidth } =
useContext(InputWrapperContext);

const leadingTextWidth = propLeadingTextWidth || wrapperLeadingTextWidth;

const RightIcon = rightIcon && SystemIcon[rightIcon];
const Icon = icon && SystemIcon[icon];

return (
<div
className={classNames(containerClass, {
[baseOutlinedClass]: outlined,
className={classNames(baseContainerClass, {
[baseOutlinedClass]: outlined || status,
[disabledClass]: disabled,
})}
data-testid="kda-input"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { vars } from '@theme/vars.css';

import { createContext } from 'react';
import type { FormFieldStatus } from '../Form.css';

export type OpenSections = string[];

interface IInputWrapperContext {
status?: FormFieldStatus;
leadingTextWidth?: keyof typeof vars.sizes;
}

export const InputWrapperContext = createContext<IInputWrapperContext>({
status: undefined,
leadingTextWidth: undefined,
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { sprinkles } from '@theme/sprinkles.css';
import { vars } from '@theme/vars.css';
import { createVar, styleVariants } from '@vanilla-extract/css';
import { styleVariants } from '@vanilla-extract/css';
import type { FormFieldStatus } from '../Form.css';
import { statusColor, statusOutlineColor } from '../Form.css';
import {
helperIconColor,
helperTextColor,
} from './InputHelper/InputHelper.css';

export const statusColor = createVar();

export type Status = 'disabled' | 'positive' | 'warning' | 'negative';

const statusOptions: Record<Status, Status> = {
const statusOptions: Record<FormFieldStatus, FormFieldStatus> = {
disabled: 'disabled',
positive: 'positive',
warning: 'warning',
Expand All @@ -26,6 +24,8 @@ export const statusVariant = styleVariants(statusOptions, (status) => {
vars: {
[helperIconColor]: vars.colors[`$${status}Accent`],
[statusColor]: vars.colors[`$${status}Accent`],
// TODO update the color to match the new design system tokens
[statusOutlineColor]: vars.colors[`$${status}Surface`],
[helperTextColor]: vars.colors[`$${status}ContrastInverted`],
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import type { IInputProps } from '@components/Form';
import type { FC, FunctionComponentElement } from 'react';
import React from 'react';
import type { vars } from 'src/styles';
import type { FormFieldStatus } from '../Form.css';
import type { IInputHeaderProps } from './InputHeader/InputHeader';
import { InputHeader } from './InputHeader/InputHeader';
import { InputHelper } from './InputHelper/InputHelper';
import type { Status } from './InputWrapper.css';
import { InputWrapperContext } from './InputWrapper.context';
import { statusVariant } from './InputWrapper.css';

export interface IInputWrapperProps extends Omit<IInputHeaderProps, 'label'> {
children:
| FunctionComponentElement<IInputProps>
| FunctionComponentElement<IInputProps>[];
status?: Status;
status?: FormFieldStatus;
disabled?: boolean;
helperText?: string;
label?: string;
Expand All @@ -33,24 +34,14 @@ export const InputWrapper: FC<IInputWrapperProps> = ({
const statusVal = disabled === true ? 'disabled' : status;

return (
<div className={statusVal ? statusVariant[statusVal] : undefined}>
{label !== undefined && (
<InputHeader htmlFor={htmlFor} label={label} tag={tag} info={info} />
)}
<div className="inputGroup">
{leadingTextWidth
? React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return null;
const props = {
...child.props,
leadingTextWidth,
};

return React.cloneElement(child, props);
})
: children}
<InputWrapperContext.Provider value={{ status, leadingTextWidth }}>
<div className={statusVal ? statusVariant[statusVal] : undefined}>
{label !== undefined && (
<InputHeader htmlFor={htmlFor} label={label} tag={tag} info={info} />
)}
<div className="inputGroup">{children}</div>
{Boolean(helperText) && <InputHelper>{helperText}</InputHelper>}
</div>
{Boolean(helperText) && <InputHelper>{helperText}</InputHelper>}
</div>
</InputWrapperContext.Provider>
);
};
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { InputWrapper, type IInputWrapperProps } from './InputWrapper';
export { type Status as InputWrapperStatus } from './InputWrapper.css';
27 changes: 3 additions & 24 deletions packages/libs/react-ui/src/components/Form/Select/Select.css.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,20 @@
import { statusColor } from '@components/Form/InputWrapper/InputWrapper.css';
import { sprinkles } from '@theme/sprinkles.css';
import { darkThemeClass, vars } from '@theme/vars.css';
import { fallbackVar, style } from '@vanilla-extract/css';
import { style } from '@vanilla-extract/css';
import { baseContainerClass } from '../Form.css';

export const containerClass = style([
baseContainerClass,
sprinkles({
alignItems: 'stretch',
backgroundColor: {
lightMode: '$white',
darkMode: '$background',
},
borderColor: {
lightMode: '$white',
darkMode: '$gray60',
},
borderRadius: '$sm',
color: '$foreground',
display: 'flex',
flexGrow: 1,
gap: '$2',
lineHeight: '$lg',
overflow: 'hidden',
paddingLeft: '$4',
paddingRight: '$2',
position: 'relative',
}),
{
borderBottom: `1px solid ${fallbackVar(statusColor, vars.colors.$gray30)}`,
selectors: {
[`${darkThemeClass} &`]: {
borderBottom: `1px solid ${fallbackVar(
statusColor,
vars.colors.$gray60,
)}`,
},
},
},
]);

export const containerClassDisabled = style([
Expand Down
Loading

2 comments on commit 3febd50

@vercel
Copy link

@vercel vercel bot commented on 3febd50 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

tools – ./packages/apps/tools

kadena-js-transfer.vercel.app
tools-kadena-js.vercel.app
tools-git-main-kadena-js.vercel.app
tools.kadena.io

@vercel
Copy link

@vercel vercel bot commented on 3febd50 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-ui – ./packages/libs/react-ui

react-ui-kadena-js.vercel.app
react-ui-git-main-kadena-js.vercel.app
react-ui-delta.vercel.app
react-ui.kadena.io

Please sign in to comment.