Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap CheckBoxInput in InputWrapper to provide visual feedback #2423

Merged
merged 8 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions css/index.styl
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,14 @@ loadingSize = 30px
span
display block
margin-left 20px
.auth0-lock-input-wrap
background #ffffff
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are needed otherwise we inherit the grey background/border from the InputWrap which is not desired

border 1px solid #ffffff
.auth0-lock-input-checkbox.auth0-lock-error
.auth0-lock-input-wrap span.no-hint
color red
.auth0-lock-error-invalid-hint
margin-left 20px

// Social

Expand Down
146 changes: 115 additions & 31 deletions src/__tests__/field/__snapshots__/custom_input.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,129 @@

exports[`CustomInput when type == checkbox and when placeholderHTML is set renders correctly as a CheckBoxInput 1`] = `
<div
className="auth0-lock-input-checkbox"
className="auth0-lock-input-block auth0-lock-input-custom_input auth0-lock-input-checkbox"
>
<label>
<input
aria-label="Custom Input"
checked={false}
id="1-custom_input"
name="custom_input"
onChange={[Function]}
type="checkbox"
/>
<span
dangerouslySetInnerHTML={
{
"__html": "<b>Placeholder</b>",
<div
className="auth0-lock-input-wrap"
>
<label>
<input
aria-invalid={false}
aria-label="Custom Input"
checked={false}
id="1-custom_input"
name="custom_input"
onChange={[Function]}
type="checkbox"
/>
<span
className=""
dangerouslySetInnerHTML={
{
"__html": "<b>Placeholder</b>",
}
}
}
/>
</label>
/>
</label>
</div>
</div>
`;

exports[`CustomInput when type == checkbox highlights placeholder text when no invalid hint is provided 1`] = `
<div
className="auth0-lock-input-block auth0-lock-input-custom_input auth0-lock-error auth0-lock-input-checkbox"
>
<div
className="auth0-lock-input-wrap"
>
<label>
<input
aria-invalid={true}
aria-label="Custom Input"
checked={false}
id="1-custom_input"
name="custom_input"
onChange={[Function]}
type="checkbox"
/>
<span
className="no-hint"
dangerouslySetInnerHTML={
{
"__html": "<b>Placeholder</b>",
}
}
/>
</label>
</div>
</div>
`;

exports[`CustomInput when type == checkbox renders correctly as a CheckBoxInput 1`] = `
<div
className="auth0-lock-input-checkbox"
className="auth0-lock-input-block auth0-lock-input-custom_input auth0-lock-input-checkbox"
>
<label>
<input
aria-label="Custom Input"
checked={false}
id="1-custom_input"
name="custom_input"
onChange={[Function]}
type="checkbox"
/>
<span>
placeholder
</span>
</label>
<div
className="auth0-lock-input-wrap"
>
<label>
<input
aria-invalid={false}
aria-label="Custom Input"
checked={false}
id="1-custom_input"
name="custom_input"
onChange={[Function]}
type="checkbox"
/>
<span
className=""
>
placeholder
</span>
</label>
</div>
</div>
`;

exports[`CustomInput when type == checkbox shows an error when value is incorrect 1`] = `
<div
className="auth0-lock-input-block auth0-lock-input-custom_input auth0-lock-error auth0-lock-input-checkbox"
>
<div
className="auth0-lock-input-wrap"
>
<label>
<input
aria-invalid={true}
aria-label="Custom Input"
checked={false}
id="1-custom_input"
name="custom_input"
onChange={[Function]}
type="checkbox"
/>
<span
className=""
dangerouslySetInnerHTML={
{
"__html": "<b>Placeholder</b>",
}
}
/>
</label>
</div>
<div
className="auth0-lock-error-msg"
id="auth0-lock-error-msg-custom_input"
role="alert"
>
<div
className="auth0-lock-error-invalid-hint"
>
invalid-hint-custom_input
</div>
</div>
</div>
`;

Expand Down
21 changes: 21 additions & 0 deletions src/__tests__/field/custom_input.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,41 @@ describe('CustomInput', () => {
describe('when type == checkbox', () => {
beforeEach(() => (defaultProps.type = 'checkbox'));
it('renders correctly as a CheckBoxInput', () => {
require('field/index').isFieldVisiblyInvalid = () => false;
const CustomInput = getComponent();

expectComponent(<CustomInput {...defaultProps} />).toMatchSnapshot();
});

describe('and when placeholderHTML is set', () => {
it('renders correctly as a CheckBoxInput', () => {
require('field/index').isFieldVisiblyInvalid = () => false;

const CustomInput = getComponent();

expectComponent(
<CustomInput {...defaultProps} placeholderHTML={'<b>Placeholder</b>'} />
).toMatchSnapshot();
});
});

it('shows an error when value is incorrect', () => {
const CustomInput = getComponent();

expectComponent(
<CustomInput {...defaultProps} placeholderHTML={'<b>Placeholder</b>'} />
).toMatchSnapshot();
});

it('highlights placeholder text when no invalid hint is provided', () => {
require('field/index').getFieldInvalidHint = () => undefined;

const CustomInput = getComponent();

expectComponent(
<CustomInput {...defaultProps} placeholderHTML={'<b>Placeholder</b>'} />
).toMatchSnapshot();
});
});
describe('when type == hidden', () => {
beforeEach(() => {
Expand Down
1 change: 1 addition & 0 deletions src/field/custom_input.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const CustomInput = ({
return (
<CheckboxInput
lockId={l.id(model)}
invalidHint={getFieldInvalidHint(model, name)}
onChange={e => changeField(l.id(model), name, `${e.target.checked}`, validator)}
checked={getFieldValue(model, name)}
placeholderHTML={placeholderHTML}
Expand Down
29 changes: 24 additions & 5 deletions src/ui/input/checkbox_input.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import React from 'react';
import InputWrap from './input_wrap';

export default class CheckboxInput extends React.Component {
render() {
const { lockId, name, ariaLabel, placeholder, checked, placeholderHTML } = this.props;
const {
lockId,
name,
ariaLabel,
placeholder,
checked,
placeholderHTML,
isValid,
invalidHint
} = this.props;

const spanClass = invalidHint ? '' : 'no-hint'

return (
<div className="auth0-lock-input-checkbox">
<InputWrap
invalidHint={invalidHint}
isValid={isValid}
name={name}
className="auth0-lock-input-checkbox"
>
<label>
<input
id={`${lockId}-${name}`}
Expand All @@ -13,16 +31,17 @@ export default class CheckboxInput extends React.Component {
onChange={::this.handleOnChange}
name={name}
aria-label={ariaLabel || name}
aria-invalid={!isValid}
/>
{placeholderHTML ? (
// placeholderHTML allows raw HTML
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: placeholderHTML }} />
<span className={spanClass} dangerouslySetInnerHTML={{ __html: placeholderHTML }} />
) : (
<span>{placeholder}</span>
<span className={spanClass}>{placeholder}</span>
)}
</label>
</div>
</InputWrap>
);
}

Expand Down
6 changes: 5 additions & 1 deletion src/ui/input/input_wrap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import React from 'react';

export default class InputWrap extends React.Component {
render() {
const { after, focused, invalidHint, isValid, name, icon } = this.props;
const { after, focused, invalidHint, isValid, name, icon, className } = this.props;
let blockClassName = `auth0-lock-input-block auth0-lock-input-${name}`;
if (!isValid) {
blockClassName += ' auth0-lock-error';
}

if (className) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Needed a way to maintain the CSS for the CheckBoxInput so added this className proper to allow that

blockClassName += ` ${className}`;
}

let wrapClassName = 'auth0-lock-input-wrap';
if (focused && isValid) {
wrapClassName += ' auth0-lock-focused';
Expand Down
12 changes: 11 additions & 1 deletion support/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,17 @@ <h1 class="navbar-brand">
validator: function () {
return true;
}
}
},
{
type: 'checkbox',
name: 'newsletter',
prefill: 'false',
placeholder: 'I hereby agree that I want to receive marketing emails from your company',
validator: (value) => ({
valid: value === 'true',
hint: 'This is a mandatory field',
}),
},
],
hooks: {
loggingIn: function (context, done) {
Expand Down