mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 21:27:05 +00:00
Checkbox ui component reimplemented
This commit is contained in:
parent
8bd6acf0c7
commit
a450ffc25f
4 changed files with 78 additions and 65 deletions
|
|
@ -1,18 +1,11 @@
|
|||
import React, { Component } from 'react';
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import Icon from 'stremio-icons/dom';
|
||||
import { withFocusable } from 'stremio-common';
|
||||
import { Input } from 'stremio-common';
|
||||
import styles from './styles';
|
||||
|
||||
class Checkbox extends Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return nextProps.focusable !== this.props.focusable ||
|
||||
nextProps.checked !== this.props.checked ||
|
||||
nextProps.disabled !== this.props.disabled ||
|
||||
nextProps.className !== this.props.className;
|
||||
}
|
||||
|
||||
class Checkbox extends PureComponent {
|
||||
onClick = (event) => {
|
||||
event.preventDefault();
|
||||
if (typeof this.props.onClick === 'function') {
|
||||
|
|
@ -20,32 +13,48 @@ class Checkbox extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
onDrag = (event) => {
|
||||
if (typeof this.props.onDrag === 'function') {
|
||||
this.props.onDrag(event);
|
||||
}
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
this.props.forwardedRef.current.blur();
|
||||
}
|
||||
}
|
||||
|
||||
onMouseOut = (event) => {
|
||||
if (typeof this.props.onMouseOut === 'function') {
|
||||
this.props.onMouseOut(event);
|
||||
}
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
this.props.forwardedRef.current.blur();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={classnames(this.props.className, styles['checkbox-container'], { 'checked': this.props.checked }, { 'disabled': this.props.disabled })}>
|
||||
<Icon
|
||||
className={styles['icon']}
|
||||
icon={this.props.checked ? 'ic_check' : 'ic_box_empty'}
|
||||
/>
|
||||
<input
|
||||
<label className={classnames(this.props.className, styles['checkbox-container'], { 'checked': this.props.checked }, { 'disabled': this.props.disabled })} onClick={this.onClick} onDrag={this.onDrag} onMouseOut={this.onMouseOut}>
|
||||
<Input
|
||||
ref={this.props.forwardedRef}
|
||||
className={styles['native-checkbox']}
|
||||
type={'checkbox'}
|
||||
tabIndex={this.props.focusable ? 0 : -1}
|
||||
disabled={this.props.disabled}
|
||||
defaultChecked={this.props.checked}
|
||||
onClick={this.onClick}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles['icon-container']}>
|
||||
<Icon className={styles['icon']} icon={this.props.checked ? 'ic_check' : 'ic_box_empty'} />
|
||||
</div>
|
||||
{React.Children.only(this.props.children)}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Checkbox.propTypes = {
|
||||
className: PropTypes.string,
|
||||
disabled: PropTypes.bool.isRequired,
|
||||
checked: PropTypes.bool.isRequired,
|
||||
onClick: PropTypes.func
|
||||
checked: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
Checkbox.defaultProps = {
|
||||
|
|
@ -53,12 +62,8 @@ Checkbox.defaultProps = {
|
|||
checked: false
|
||||
};
|
||||
|
||||
const CheckboxWithFocusable = withFocusable(Checkbox);
|
||||
|
||||
CheckboxWithFocusable.displayName = 'CheckboxWithFocusable';
|
||||
|
||||
const CheckboxWithForwardedRef = React.forwardRef((props, ref) => (
|
||||
<CheckboxWithFocusable {...props} forwardedRef={ref} />
|
||||
<Checkbox {...props} forwardedRef={ref} />
|
||||
));
|
||||
|
||||
CheckboxWithForwardedRef.displayName = 'CheckboxWithForwardedRef';
|
||||
|
|
|
|||
|
|
@ -1,28 +1,34 @@
|
|||
.checkbox-container {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--background-color);
|
||||
|
||||
.icon {
|
||||
height: 100%;
|
||||
fill: var(--icon-color);
|
||||
.icon-container {
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: var(--icon-color);
|
||||
background-color: var(--icon-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.native-checkbox {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
width: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&:global(.checked) {
|
||||
.icon {
|
||||
padding: 10%;
|
||||
.icon-container {
|
||||
.icon {
|
||||
padding: 10%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,14 +4,17 @@ import classnames from 'classnames';
|
|||
import { Checkbox } from 'stremio-common';
|
||||
import styles from './styles';
|
||||
|
||||
const linkOnClick = (event) => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
const ConsentCheckbox = React.forwardRef(({ className, label, link, href, checked, onClick }, ref) => (
|
||||
<label className={classnames(styles['consent-checkbox-container'], className)}>
|
||||
<Checkbox ref={ref} className={styles['checkbox']} checked={checked} onClick={onClick} />
|
||||
<Checkbox ref={ref} className={classnames(styles['consent-checkbox-container'], className)} checked={checked} onClick={onClick}>
|
||||
<div className={styles['label']}>
|
||||
{label}
|
||||
{link && href ? <a className={styles['link']} href={href} target={'_blank'} tabIndex={'-1'}> {link}</a> : null}
|
||||
{link && href ? <a className={styles['link']} href={href} target={'_blank'} tabIndex={'-1'} onClick={linkOnClick}> {link}</a> : null}
|
||||
</div>
|
||||
</label>
|
||||
</Checkbox>
|
||||
));
|
||||
|
||||
ConsentCheckbox.displayName = 'ConsentCheckbox';
|
||||
|
|
|
|||
|
|
@ -1,42 +1,41 @@
|
|||
.consent-checkbox-container {
|
||||
--icon-size: 1.2em;
|
||||
--icon-color: var(--color-surface);
|
||||
--icon-background-color: transparent;
|
||||
|
||||
padding: calc(var(--spacing) * 0.5);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
.checkbox {
|
||||
--icon-color: var(--color-surface);
|
||||
margin-right: calc(var(--spacing) * 0.5);
|
||||
width: 1.3em;
|
||||
height: 1.3em;
|
||||
.label {
|
||||
flex: 1;
|
||||
margin-left: calc(var(--spacing) * 0.5);
|
||||
line-height: 1.2em;
|
||||
color: var(--color-surface);
|
||||
|
||||
&:global(.checked) {
|
||||
--icon-color: var(--color-surfacelight);
|
||||
background-color: var(--color-primary);
|
||||
.link {
|
||||
line-height: 1.2em;
|
||||
color: var(--color-surfacelight);
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
line-height: 1.2em;
|
||||
color: var(--color-surface);
|
||||
}
|
||||
|
||||
.link {
|
||||
line-height: 1.2em;
|
||||
color: var(--color-surfacelight);
|
||||
&:global(.checked) {
|
||||
--icon-color: var(--color-surfacelight);
|
||||
--icon-background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&:focus-within, &:hover {
|
||||
.checkbox {
|
||||
--icon-color: var(--color-surfacelighter);
|
||||
}
|
||||
--icon-color: var(--color-surfacelighter);
|
||||
|
||||
.label {
|
||||
color: var(--color-surfacelight);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: var(--color-surfacelighter);
|
||||
.link {
|
||||
color: var(--color-surfacelighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue