Create and use stylised checkboxes

This commit is contained in:
Jorik Schellekens 2020-05-28 22:33:00 +01:00
parent 1ab6f27535
commit 66c0d53f3e
10 changed files with 153 additions and 33 deletions

View file

@ -116,6 +116,7 @@
@import "./views/elements/_RoomAliasField.scss"; @import "./views/elements/_RoomAliasField.scss";
@import "./views/elements/_Slider.scss"; @import "./views/elements/_Slider.scss";
@import "./views/elements/_Spinner.scss"; @import "./views/elements/_Spinner.scss";
@import "./views/elements/_StyledCheckbox.scss";
@import "./views/elements/_SyntaxHighlight.scss"; @import "./views/elements/_SyntaxHighlight.scss";
@import "./views/elements/_TextWithTooltip.scss"; @import "./views/elements/_TextWithTooltip.scss";
@import "./views/elements/_ToggleSwitch.scss"; @import "./views/elements/_ToggleSwitch.scss";

View file

@ -15,6 +15,7 @@ limitations under the License.
*/ */
$font-1px: 0.067rem; $font-1px: 0.067rem;
$font-1-5px: 0.100rem;
$font-2px: 0.133rem; $font-2px: 0.133rem;
$font-3px: 0.200rem; $font-3px: 0.200rem;
$font-4px: 0.267rem; $font-4px: 0.267rem;

View file

@ -18,8 +18,3 @@ limitations under the License.
margin-top: 10px; margin-top: 10px;
display: flex; display: flex;
} }
.mx_GroupAddressPicker_checkboxContainer input[type="checkbox"] {
/* Stop flex from shrinking the checkbox */
width: 20px;
}

View file

@ -0,0 +1,66 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_Checkbox {
$size: $font-16px;
$border-size: $font-1-5px;
$border-radius: $font-4px;
display: flex;
align-items: flex-start;
input[type=checkbox] {
display: none;
& + label {
display: flex;
align-items: center;
flex-grow: 1;
}
& + label > .mx_Checkbox_background {
display: inline-flex;
position: relative;
flex-shrink: 0;
height: $size;
width: $size;
size: 0.5rem;
border: $border-size solid rgba($muted-fg-color, 0.5);
box-sizing: border-box;
border-radius: $border-radius;
img {
height: 100%;
width: 100%;
filter: invert(100%);
}
}
&:checked + label > .mx_Checkbox_background {
background: $accent-color;
border-color: $accent-color;
}
& + label > *:not(.mx_Checkbox_background) {
margin-left: 10px;
}
}
}

View file

@ -22,6 +22,7 @@ import { _t } from './languageHandler';
import {MatrixClientPeg} from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import GroupStore from './stores/GroupStore'; import GroupStore from './stores/GroupStore';
import {allSettled} from "./utils/promise"; import {allSettled} from "./utils/promise";
import StyledCheckbox from './components/views/elements/StyledCheckbox';
export function showGroupInviteDialog(groupId) { export function showGroupInviteDialog(groupId) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -61,12 +62,12 @@ export function showGroupAddRoomDialog(groupId) {
<div>{ _t("Which rooms would you like to add to this community?") }</div> <div>{ _t("Which rooms would you like to add to this community?") }</div>
</div>; </div>;
const checkboxContainer = <label className="mx_GroupAddressPicker_checkboxContainer"> const checkboxContainer = <StyledCheckbox
<input type="checkbox" onChange={onCheckboxClicked} /> className="mx_GroupAddressPicker_checkboxContainer"
<div> onChange={onCheckboxClicked}
>
{ _t("Show these rooms to non-members on the community page and room list?") } { _t("Show these rooms to non-members on the community page and room list?") }
</div> </StyledCheckbox>;
</label>;
const AddressPickerDialog = sdk.getComponent("dialogs.AddressPickerDialog"); const AddressPickerDialog = sdk.getComponent("dialogs.AddressPickerDialog");
Modal.createTrackedDialog('Add Rooms to Group', '', AddressPickerDialog, { Modal.createTrackedDialog('Add Rooms to Group', '', AddressPickerDialog, {

View file

@ -355,6 +355,7 @@ export const TermsAuthEntry = createReactClass({
allChecked = allChecked && checked; allChecked = allChecked && checked;
checkboxes.push( checkboxes.push(
// XXX: replace with StyledCheckbox
<label key={"policy_checkbox_" + policy.id} className="mx_InteractiveAuthEntryComponents_termsPolicy"> <label key={"policy_checkbox_" + policy.id} className="mx_InteractiveAuthEntryComponents_termsPolicy">
<input type="checkbox" onChange={() => this._togglePolicy(policy.id)} checked={checked} /> <input type="checkbox" onChange={() => this._togglePolicy(policy.id)} checked={checked} />
<a href={policy.url} target="_blank" rel="noreferrer noopener">{ policy.name }</a> <a href={policy.url} target="_blank" rel="noreferrer noopener">{ policy.name }</a>

View file

@ -25,6 +25,7 @@ import * as Lifecycle from '../../../Lifecycle';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import InteractiveAuth, {ERROR_USER_CANCELLED} from "../../structures/InteractiveAuth"; import InteractiveAuth, {ERROR_USER_CANCELLED} from "../../structures/InteractiveAuth";
import {DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents"; import {DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents";
import StyledCheckbox from "../elements/StyledCheckbox";
export default class DeactivateAccountDialog extends React.Component { export default class DeactivateAccountDialog extends React.Component {
constructor(props) { constructor(props) {
@ -209,13 +210,10 @@ export default class DeactivateAccountDialog extends React.Component {
<div className="mx_DeactivateAccountDialog_input_section"> <div className="mx_DeactivateAccountDialog_input_section">
<p> <p>
<label htmlFor="mx_DeactivateAccountDialog_erase_account_input"> <StyledCheckbox
<input
id="mx_DeactivateAccountDialog_erase_account_input"
type="checkbox"
checked={this.state.shouldErase} checked={this.state.shouldErase}
onChange={this._onEraseFieldChange} onChange={this._onEraseFieldChange}
/> >
{_t( {_t(
"Please forget all messages I have sent when my account is deactivated " + "Please forget all messages I have sent when my account is deactivated " +
"(<b>Warning:</b> this will cause future users to see an incomplete view " + "(<b>Warning:</b> this will cause future users to see an incomplete view " +
@ -223,7 +221,7 @@ export default class DeactivateAccountDialog extends React.Component {
{}, {},
{ b: (sub) => <b>{ sub }</b> }, { b: (sub) => <b>{ sub }</b> },
)} )}
</label> </StyledCheckbox>
</p> </p>
{error} {error}

View file

@ -29,6 +29,7 @@ import {RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink} from "../..
import * as ContextMenu from "../../structures/ContextMenu"; import * as ContextMenu from "../../structures/ContextMenu";
import {toRightOf} from "../../structures/ContextMenu"; import {toRightOf} from "../../structures/ContextMenu";
import {copyPlaintext, selectText} from "../../../utils/strings"; import {copyPlaintext, selectText} from "../../../utils/strings";
import StyledCheckbox from '../elements/StyledCheckbox';
const socials = [ const socials = [
{ {
@ -168,13 +169,12 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
const events = this.props.target.getLiveTimeline().getEvents(); const events = this.props.target.getLiveTimeline().getEvents();
if (events.length > 0) { if (events.length > 0) {
checkbox = <div> checkbox = <div>
<input type="checkbox" <StyledCheckbox
id="mx_ShareDialog_checkbox"
checked={this.state.linkSpecificEvent} checked={this.state.linkSpecificEvent}
onChange={this.onLinkSpecificEventCheckboxClick} /> onChange={this.onLinkSpecificEventCheckboxClick}
<label htmlFor="mx_ShareDialog_checkbox"> >
{ _t('Link to most recent message') } { _t('Link to most recent message') }
</label> </StyledCheckbox>
</div>; </div>;
} }
} else if (this.props.target instanceof User || this.props.target instanceof RoomMember) { } else if (this.props.target instanceof User || this.props.target instanceof RoomMember) {
@ -184,13 +184,12 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
} else if (this.props.target instanceof MatrixEvent) { } else if (this.props.target instanceof MatrixEvent) {
title = _t('Share Room Message'); title = _t('Share Room Message');
checkbox = <div> checkbox = <div>
<input type="checkbox" <StyledCheckbox
id="mx_ShareDialog_checkbox"
checked={this.state.linkSpecificEvent} checked={this.state.linkSpecificEvent}
onClick={this.onLinkSpecificEventCheckboxClick} /> onClick={this.onLinkSpecificEventCheckboxClick}
<label htmlFor="mx_ShareDialog_checkbox"> >
{ _t('Link to selected message') } { _t('Link to selected message') }
</label> </StyledCheckbox>
</div>; </div>;
} }

View file

@ -0,0 +1,57 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import { randomString } from "matrix-js-sdk/src/randomstring";
const CHECK_BOX_SVG = require("../../../../res/img/feather-customised/check.svg");
interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
}
interface IState {
}
export default class StyledCheckbox extends React.PureComponent<IProps, IState> {
public static readonly defaultProps = {
className: "",
}
constructor(props: IProps) {
super(props);
}
public render() {
const { children, className, ...otherProps } = this.props;
// 56^10 so unlikely chance of collision.
const id = "checkbox_" + randomString(10);
return [
<span className={"mx_Checkbox " + className}>
<input id={id} {...otherProps} type="checkbox" />
<label htmlFor={id}>
{/* Using the div to center the image */}
<div className="mx_Checkbox_background">
<img src={CHECK_BOX_SVG}/>
</div>
<div>
{ this.props.children }
</div>
</label>
</span>
]
}
}

View file

@ -21,6 +21,7 @@ import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {MatrixClientPeg} from '../../../MatrixClientPeg';
import {formatDate} from '../../../DateUtils'; import {formatDate} from '../../../DateUtils';
import StyledCheckbox from '../elements/StyledCheckbox';
export default class DevicesPanelEntry extends React.Component { export default class DevicesPanelEntry extends React.Component {
constructor(props) { constructor(props) {
@ -81,7 +82,7 @@ export default class DevicesPanelEntry extends React.Component {
{ lastSeen } { lastSeen }
</div> </div>
<div className="mx_DevicesPanel_deviceButtons"> <div className="mx_DevicesPanel_deviceButtons">
<input type="checkbox" onChange={this.onDeviceToggled} checked={this.props.selected} /> <StyledCheckbox onChange={this.onDeviceToggled} checked={this.props.selected} />
</div> </div>
</div> </div>
); );