-
Notifications
You must be signed in to change notification settings - Fork 356
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
feat(checkBox): updated PF4 checkBox component according to PF-next #717
Conversation
PatternFly-React preview: https://717-pr-patternfly-react-patternfly.surge.sh |
Pull Request Test Coverage Report for Build 2558
💛 - Coveralls |
}; | ||
|
||
const renderLabel = (label, checkId, isDisabled) => { | ||
if (typeof label === 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we are only applying PF styles when the label is a string. Can we apply style to this regardless of type? I am concerned that the labels may be unstyled, leading to inconsistencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with this. If we really need to support replacing the label component used here (for now just an html label) we should follow something like labelComponent={CustomLabel}
or compoents={{ Label: CustomLabel }}
that would then get passed the className, htmlFor, or an other props.
If a basic function is needed the prop should be renderLabel
and it should be passed the htmlFor and className prop to allow the user access to the styles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am concerned that the labels may be unstyled, leading to inconsistencies.
@tlabaj that is the point of these options. Reason why i wanted @rvsia to support different types of labels (nodes, function) is actually that you can have some other component (icons, pictures, w/e). If you want consistent/pf-styled label, then you should use the string option. Passing the styles to custom labels may actually break them. Whole reason of this approach is to give devs freedom. Yes they will have to be careful and style non-pf components on their own, but consistency of some app should a concern of the actual end user not the library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I don't understand but I can't see any difference between this and your solution except the amount of props.
If user wants to use a component with props instead of the label he can do something like
<Checkbox label={<Customcomponent className="..." htmlFor="..." />}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was more indicating that the function support should be removed. It does not add any value. It only complicates things. It should be node
(covers string, rendered element, number, etc) only. That would support the follow
<Checkbox label="<CustomLabel />" />
<Checkbox label="Label" />
const renderLabel =() => 'Some Label';
<Checkbox label={renderLabel()}
The only reason we would want to pass a function to label would be to pass the className and any a11y props to it
const renderLabel = ({ className, htmlFor }) => (
<label className={`${className} ${someCustomClass}` } htmlFor={htmlFor}>Label Text</label>
);
<Checkbox label={renderLabel}
Otherwise it is no differnet than the last example in the first block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with going with node
here and removing the function support.
|
||
export interface CheckboxProps | ||
extends Omit<HTMLProps<HTMLInputElement>, 'type' | 'onChange' | 'disabled'> { | ||
isDisabled?: boolean; | ||
isValid?: boolean; | ||
onChange?(checked: boolean, event: FormEvent<HTMLInputElement>): void; | ||
id?: string; | ||
'aria-label'?: string; | ||
label?: OneOf<typeof TextVariants, keyof typeof TextVariants>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more easily written as string | ReactNode | Function
. That being said I am curious why function is needed at all. Is there a usecase for it. I understand using render functions, but for a simple label is seems to add complications where they are not needed.
return null; | ||
}, | ||
/** Aria-label of the checkbox. */ | ||
'aria-label': props => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If using something like react-intl or react-i18next this will likely always error. I think we should just check for the existence of it since we are allowing nodes in addition to strings.
packages/patternfly-4/react-core/src/components/Checkbox/Checkbox.js
Outdated
Show resolved
Hide resolved
aria-invalid={!isValid} | ||
disabled={isDisabled} | ||
/> | ||
{label && renderLabel(label, props.id, isDisabled)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we get rid of the function (i think we should). Inlining the label down here would be easier to read and follow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it (with all of the conditions) would be too complex to put into JSX.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with getting rid of the function here to simplify this
}; | ||
|
||
const renderLabel = (label, checkId, isDisabled) => { | ||
if (typeof label === 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with this. If we really need to support replacing the label component used here (for now just an html label) we should follow something like labelComponent={CustomLabel}
or compoents={{ Label: CustomLabel }}
that would then get passed the className, htmlFor, or an other props.
If a basic function is needed the prop should be renderLabel
and it should be passed the htmlFor and className prop to allow the user access to the styles.
*would you mind formatting the commit semantically ? ... you can use |
131c55a
to
6cf7ff4
Compare
/** Label text of the checkbox. */ | ||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.func]), | ||
/** Id of the checkbox. */ | ||
id: props => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can just do id: PropTypes.string.isRequired
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this would simplify it and give the same error if not specified
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with others that we should probably simplify label prop and remove function
onChange: () => undefined | ||
onChange: () => undefined, | ||
label: undefined, | ||
id: null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is a string perhaps default to ''
packages/patternfly-4/react-core/src/components/Checkbox/Checkbox.test.js
Show resolved
Hide resolved
packages/patternfly-4/react-core/src/components/Checkbox/examples/UncontrolledCheckbox.js
Show resolved
Hide resolved
6763cbd
to
494e96a
Compare
disabled={isDisabled} | ||
/> | ||
{React.isValidElement(label) | ||
? label |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is still an issue in my mind, but maybe @amarie401 or @jschuler can weigh in on if it will cause them any problems. If someone provides
import { FormattedMessage } from 'react-intl';
const CustomCheckbox = (props) => (
<Checkbox
label={<FormattedMessage defaultMessage="Label Value" id="checkbox.label" />}
{...props}
/>
)
The label will go completely unstyled. There is also no way currently to use the label inside this as a component to make sure that I can wrap it any other way. to get around this I would have to do
import { injectIntl, defineMessages } from 'react-intl';
const messages = defineMessages({
label: {
defaultMessage: 'Label Value',
id: 'checkbox.label'
}
})
const CustomCheckbox = ({ intl, ...props }) => (
<Checkbox
label={intl.formatMessage(messages.label)}
{...props}
/>
)
const Wrapped = injectIntl(CustomCheckbox);
I propose that this return section is just changed to
<label
className={css(styles.checkLabel, isDisabled && styles.modifiers.disabled)}
htmlFor={props.id}
>
{label}
</label>
That removes the string and element checks and just passes the node into the label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Doug here. I think this leaves room for a label to be unstyled which could lead to an inconsistent user experience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
import { Omit } from '../../typeUtils'; | ||
|
||
export interface CheckboxProps | ||
extends Omit<HTMLProps<HTMLInputElement>, 'type' | 'onChange' | 'disabled'> { | ||
isDisabled?: boolean; | ||
isValid?: boolean; | ||
onChange?(checked: boolean, event: FormEvent<HTMLInputElement>): void; | ||
id: string; | ||
'aria-label': string; | ||
label?: string | ReactNode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReactNode includes string. This can just be label?: ReactNode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks for the contribution and work through the implementation with us.
Nice job @rvsia, thanks for your contribution! 🎉 |
Thanks everyone for helping me! 👍 |
What:
according to https://pf-next.com/components/Check/examples/
Link to storybook::
https://717-pr-patternfly-react-patternfly.surge.sh/patternfly-4/components/checkbox/
Additional issues:
How should the component handle different additional attributes for different parts of the component?
e. g. Should we let users to add styles for wrapperDiv, label, input separately?
Right now, a consumer can add props only to input.