Skip to content
This repository has been archived by the owner on May 17, 2023. It is now read-only.

Commit

Permalink
[DXDP-1437] Update read-only checkbox and select styles (#1727)
Browse files Browse the repository at this point in the history
* [DXDP-1437] Update read-only checkbox and select styles

* Update snapshot

* Placeholder and checkbox updates

* Only apply placeholder styles if set

* No hover for disabled checkboxes

* Do not adjust readonly text for masked inputs

* Sync radio and checkbox styles

* Sync read only checkbox styles

* Remove box shadow for read-only
  • Loading branch information
pdillon authored Sep 21, 2020
1 parent 54dd5df commit 28b59aa
Show file tree
Hide file tree
Showing 7 changed files with 515 additions and 549 deletions.
25 changes: 13 additions & 12 deletions core/components/atoms/_simple-select/simple-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ import { StyledInput } from "../_styled-input";
import Icon from "../icon";
import { ISelectOptions } from "../select/interfaces";

const selectOpacity = {
default: 1,
disabled: 0.5
};

const PLACEHOLDER_VALUE = "0";

const valueIsUndefined = (value) => value === undefined || value === null;
Expand Down Expand Up @@ -69,10 +64,15 @@ const SimpleSelect = ({ options, ...props }: ISimpleSelectProps) => {

return (
<SimpleSelect.Wrapper>
<SimpleSelect.ArrowIcon name="dropdown-fill" size="14" color="default" />
<SimpleSelect.ArrowIcon name="dropdown-fill" size="14" color={props.disabled ? colors.input.icon : "default"} />
<Form.Field.ContextConsumer>
{(context) => (
<SimpleSelect.Element id={props.id || context.formFieldId} {...Automation("select")} {...props}>
<SimpleSelect.Element
id={props.id || context.formFieldId}
isUsingPlaceholder={!!props.placeholder && shouldUsePlaceholder}
{...Automation("select")}
{...props}
>
{/* First option will be selected if there is no value passed as a prop */}
{props.placeholder && (
<option disabled={true} value={PLACEHOLDER_VALUE} {...Automation("select.option")}>
Expand All @@ -89,14 +89,15 @@ const SimpleSelect = ({ options, ...props }: ISimpleSelectProps) => {
};

SimpleSelect.Element = styled(StyledInput).attrs({ as: "select" })`
cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
appearance: none;
padding-right: ${spacing.large};
height: ${misc.input.default.height};
opacity: ${(props) => (props.disabled ? selectOpacity.disabled : selectOpacity.default)};
background-color: ${(props) => (props.disabled ? colors.input.backgroundReadOnly : colors.input.background)};
color: ${(props) => (props.isUsingPlaceholder ? colors.input.placeholder : colors.input.text)};
&:disabled {
opacity: 1;
color: ${(props) => (props.isUsingPlaceholder ? colors.input.placeholderReadOnly : colors.input.text)};
}
`;

SimpleSelect.Wrapper = styled.div`
Expand Down
42 changes: 24 additions & 18 deletions core/components/atoms/_styled-input/styled-input.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
import styled from '../../styled'

import { colors, fonts, spacing, misc } from '../../tokens'
import containerStyles from '../../_helpers/container-styles'
import containerStyles from "../../_helpers/container-styles";
import styled from "../../styled";
import { colors, fonts, misc, spacing } from "../../tokens";

const config = {
basic: {
background: colors.input.background,
border: colors.input.border,
hoverBorder: colors.input.borderHover,
focusBorder: colors.input.borderFocus,
placeholder: colors.input.placeholder
placeholder: colors.input.placeholder,
cursor: "auto"
},
readOnly: {
background: colors.input.backgroundReadOnly,
border: colors.input.border,
hoverBorder: colors.input.border,
focusBorder: colors.input.border,
placeholder: colors.input.placeholderReadOnly
placeholder: colors.input.placeholderReadOnly,
cursor: "not-allowed"
},
error: {
background: colors.input.background,
border: colors.input.borderError,
hoverBorder: colors.input.borderError,
focusBorder: colors.input.borderError,
placeholder: colors.input.placeholder
placeholder: colors.input.placeholder,
cursor: "auto"
}
}
};

const getAttributes = (props) => {
if (props.readOnly) { return config.readOnly }
else if (props.hasError || props.error) { return config.error }
else { return config.basic }
}
if (props.readOnly || props.disabled) {
return config.readOnly;
} else if (props.hasError || props.error) {
return config.error;
} else {
return config.basic;
}
};

const StyledInput = styled.input`
${containerStyles};
Expand All @@ -43,13 +49,13 @@ const StyledInput = styled.input`
border-color: ${(props) => getAttributes(props).border};
border-radius: ${misc.radius};
font-family: ${(props) => (props.code ? fonts.family.code : 'inherit')};
font-size: ${(props) => (props.code ? '13px' : 'inherit')};
font-family: ${(props) => (props.code ? fonts.family.code : "inherit")};
font-size: ${(props) => (props.code ? "13px" : "inherit")};
color: ${colors.text.inputs};
padding: ${misc.inputs.padding} ${spacing.small};
cursor: ${(props) => (props.readOnly ? 'not-allowed' : 'auto')};
cursor: ${(props) => getAttributes(props).cursor};
transition: border-color ${misc.animationDuration}, box-shadow ${misc.animationDuration};
&:hover {
Expand All @@ -61,8 +67,8 @@ const StyledInput = styled.input`
outline: none;
}
&::-webkit-input-placeholder {
color: ${(props) => getAttributes(props).placeholder};
color: ${(props) => (props.masked ? colors.text.inputs : getAttributes(props).placeholder)};
}
`
`;

export { StyledInput }
export { StyledInput };
109 changes: 53 additions & 56 deletions core/components/atoms/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ import Form from "../../molecules/form";
import styled from "../../styled";
import { colors, fonts, spacing } from "../../tokens";

const CheckMark = styled.span``
const Label = styled.div``
const CheckMark = styled.span``;
const Label = styled.div``;

const justifyContent = {
horizontal: `margin-right: ${spacing.medium}`,
vertical: `margin-bottom: ${spacing.xsmall}`
}
};

export interface ICheckboxProps {
/** HTML ID of the checkbox */
id?: string
id?: string;
/** The name of the checkbox */
name: string
name: string;
/** The value of the currently-selected option */
selected?: string[]
selected?: string[];
/** If true, all options in the group will be disabled */
readOnly?: boolean
readOnly?: boolean;
/** Callback function which is called when the user selects an option */
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
/** Label */
children?: JSX.Element | JSX.Element[] | string
defaultChecked?: boolean
checked?: boolean
value?: any
align?: 'vertical' | 'horizontal'
children?: JSX.Element | JSX.Element[] | string;
defaultChecked?: boolean;
checked?: boolean;
value?: any;
align?: "vertical" | "horizontal";
}

const Checkbox = (props: ICheckboxProps) => (
<Checkbox.Option readOnly={props.readOnly} {...Automation('checkbox')}>
<Checkbox.Option readOnly={props.readOnly} {...Automation("checkbox")}>
<Form.Field.ContextConsumer>
{(context) => (
<input
Expand All @@ -44,23 +44,24 @@ const Checkbox = (props: ICheckboxProps) => (
value={props.value}
checked={props.checked}
defaultChecked={props.defaultChecked}
onChange={props.onChange}
onChange={!props.readOnly ? props.onChange : undefined}
readOnly={true}
{...Automation('checkbox.input')}
disabled={props.readOnly}
{...Automation("checkbox.input")}
/>
)}
</Form.Field.ContextConsumer>
<CheckMark />
<Label>{props.children}</Label>
</Checkbox.Option>
)
);

Checkbox.Option = styled.label`
${containerStyles};
cursor: ${(props) => (props.readOnly ? "not-allowed" : "pointer")};
display: flex;
position: relative;
cursor: pointer;
margin-bottom: 0;
font-weight: ${fonts.weight.normal};
padding-left: ${spacing.medium};
Expand All @@ -69,16 +70,10 @@ Checkbox.Option = styled.label`
-ms-user-select: none;
user-select: none;
vertical-align: middle;
pointer-events: ${(props) => (props.readOnly ? 'none' : null)};
input {
position: absolute;
opacity: 0;
cursor: pointer;
}
${Label} {
opacity: ${(props) => (props.readOnly ? 0.5 : null)};
}
${CheckMark} {
Expand All @@ -88,28 +83,27 @@ Checkbox.Option = styled.label`
transform: translateY(20%);
height: 16px;
width: 16px;
opacity: ${(props) => (props.readOnly ? 0.5 : null)};
background-color: ${colors.radio.background};
border: 1px solid ${colors.radio.border};
box-shadow: inset 0 1px 2px 0 ${colors.radio.shadow};
background-color: ${(props) => (props.readOnly ? colors.radio.backgroundDisabled : colors.radio.background)};
border: 1px solid ${(props) => (props.readOnly ? colors.radio.borderDisabled : colors.radio.border)};
box-shadow: ${(props) => (props.readOnly ? `none` : `inset 0 1px 2px 0 ${colors.radio.shadow}`)};
border-radius: 2px;
}
&:hover input ~ ${CheckMark} {
box-shadow: inset 0 1px 4px 0 ${colors.radio.shadow};
box-shadow: ${(props) => (props.readOnly ? `none` : `inset 0 1px 4px 0 ${colors.radio.shadow}`)};
}
input:checked ~ ${CheckMark} {
background-color: ${colors.radio.backgroundSelected};
border: 1px solid ${colors.radio.borderSelected};
background-color: ${(props) => (props.readOnly ? colors.base.gray : colors.radio.backgroundSelected)};
border: 1px solid ${(props) => (props.readOnly ? colors.base.gray : colors.radio.borderSelected)};
}
input:focus ~ ${CheckMark} {
box-shadow: inset 0 1px 4px 0 ${colors.radio.shadow}, 0 0 0 2px ${colors.base.blue};
}
${CheckMark}:after {
content: '';
content: "";
position: absolute;
display: none;
}
Expand All @@ -128,56 +122,59 @@ Checkbox.Option = styled.label`
left: 20%;
top: 50%;
}
`
`;

Checkbox.Element = styled.div`
${Checkbox.Option} {
display: ${(props) => (props.align === 'horizontal' ? 'inline-block' : 'table')};
display: ${(props) => (props.align === "horizontal" ? "inline-block" : "table")};
${(props) => justifyContent[props.align]};
&:last-child {
margin: 0;
}
}
`
`;

export interface ICheckboxGroupProps {
/** The direction in which the options should be laid out */
align?: 'horizontal' | 'vertical'
children?: JSX.Element | JSX.Element[]
name?: string
selected?: any[]
checked?: boolean
readOnly?: boolean
onChange?: Function
align?: "horizontal" | "vertical";
children?: JSX.Element | JSX.Element[];
name?: string;
selected?: any[];
checked?: boolean;
readOnly?: boolean;
onChange?: Function;
}

const CheckboxGroup = (props: ICheckboxGroupProps) => (
<Checkbox.Element {...props} {...Automation('checkbox.group')}>
<Checkbox.Element {...props} {...Automation("checkbox.group")}>
{React.Children.map(props.children, (child) => {
if (!child) {
return null
return null;
}

const isReadOnly = props.readOnly || child.props.readOnly;

return React.cloneElement(child, {
name: props.name,
defaultChecked: props.selected.indexOf(child.props.value) > -1,
checked: props.checked,
readOnly: props.readOnly || child.props.readOnly,
onChange: props.onChange
})
readOnly: isReadOnly,
onChange: !isReadOnly ? props.onChange : undefined
});
})}
</Checkbox.Element>
)
);

Checkbox.Group = CheckboxGroup
Checkbox.Group = CheckboxGroup;

// Backwards compatibility (will be removed in 1.0)
const StyledCheckbox = Checkbox.Element
const StyledCheckboxOption = Checkbox.Option
const StyledCheckbox = Checkbox.Element;
const StyledCheckboxOption = Checkbox.Option;

CheckboxGroup.defaultProps = {
align: 'vertical'
}
align: "vertical"
};

export default Checkbox
export { StyledCheckbox, StyledCheckboxOption }
export default Checkbox;
export { StyledCheckbox, StyledCheckboxOption };
Loading

0 comments on commit 28b59aa

Please sign in to comment.