Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Polls: Creation form & start event (#7001)
Browse files Browse the repository at this point in the history
* PSFD-423: Permission check for polls dialog

* PSFD-423: Implement compound scrollable dialog and skeleton create poll

* PSFD-325: Ask the question

* PSFD-328: Ask for options

* PSFD-423: Ensure form submission semantics work for dialogs

* PSFD-328: Option semantics

* Can delete all option to end up with zero
* Minimum 2 to submit the form

* PSFD-316: Send poll start event

* Appease the linter

* PSFD-328: Reduce padding between options to account for field size

* Iterate per design

* Fix submission
  • Loading branch information
turt2live authored Nov 2, 2021
1 parent 5202c0a commit 73731cc
Show file tree
Hide file tree
Showing 13 changed files with 546 additions and 23 deletions.
35 changes: 27 additions & 8 deletions res/css/_common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,10 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
* We should go through and have one consistent set of styles for buttons throughout the app.
* For now, I am duplicating the selectors here for mx_Dialog and mx_DialogButtons.
*/
.mx_Dialog button, .mx_Dialog input[type="submit"], .mx_Dialog_buttons button, .mx_Dialog_buttons input[type="submit"] {
.mx_Dialog button:not(.mx_Dialog_nonDialogButton),
.mx_Dialog input[type="submit"],
.mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton),
.mx_Dialog_buttons input[type="submit"] {
@mixin mx_DialogButton;
margin-left: 0px;
margin-right: 8px;
Expand All @@ -417,36 +420,52 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
font-family: inherit;
}

.mx_Dialog button:last-child {
.mx_Dialog button:not(.mx_Dialog_nonDialogButton):last-child {
margin-right: 0px;
}

.mx_Dialog button:hover, .mx_Dialog input[type="submit"]:hover, .mx_Dialog_buttons button:hover, .mx_Dialog_buttons input[type="submit"]:hover {
.mx_Dialog button:not(.mx_Dialog_nonDialogButton):hover,
.mx_Dialog input[type="submit"]:hover,
.mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton):hover,
.mx_Dialog_buttons input[type="submit"]:hover {
@mixin mx_DialogButton_hover;
}

.mx_Dialog button:focus, .mx_Dialog input[type="submit"]:focus, .mx_Dialog_buttons button:focus, .mx_Dialog_buttons input[type="submit"]:focus {
.mx_Dialog button:not(.mx_Dialog_nonDialogButton):focus,
.mx_Dialog input[type="submit"]:focus,
.mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton):focus,
.mx_Dialog_buttons input[type="submit"]:focus {
filter: brightness($focus-brightness);
}

.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary, .mx_Dialog_buttons button.mx_Dialog_primary, .mx_Dialog_buttons input[type="submit"].mx_Dialog_primary {
.mx_Dialog button.mx_Dialog_primary,
.mx_Dialog input[type="submit"].mx_Dialog_primary,
.mx_Dialog_buttons button.mx_Dialog_primary,
.mx_Dialog_buttons input[type="submit"].mx_Dialog_primary {
color: $accent-fg-color;
background-color: $accent-color;
min-width: 156px;
}

.mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger, .mx_Dialog_buttons button.danger, .mx_Dialog_buttons input[type="submit"].danger {
.mx_Dialog button.danger,
.mx_Dialog input[type="submit"].danger,
.mx_Dialog_buttons button.danger,
.mx_Dialog_buttons input[type="submit"].danger {
background-color: $warning-color;
border: solid 1px $warning-color;
color: $accent-fg-color;
}

.mx_Dialog button.warning, .mx_Dialog input[type="submit"].warning {
.mx_Dialog button.warning,
.mx_Dialog input[type="submit"].warning {
border: solid 1px $warning-color;
color: $warning-color;
}

.mx_Dialog button:disabled, .mx_Dialog input[type="submit"]:disabled, .mx_Dialog_buttons button:disabled, .mx_Dialog_buttons input[type="submit"]:disabled {
.mx_Dialog button:not(.mx_Dialog_nonDialogButton):disabled,
.mx_Dialog input[type="submit"]:disabled,
.mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton):disabled,
.mx_Dialog_buttons input[type="submit"]:disabled {
background-color: $light-fg-color;
border: solid 1px $light-fg-color;
opacity: 0.7;
Expand Down
2 changes: 2 additions & 0 deletions res/css/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
@import "./views/dialogs/_ChangelogDialog.scss";
@import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss";
@import "./views/dialogs/_CommunityPrototypeInviteDialog.scss";
@import "./views/dialogs/_CompoundDialog.scss";
@import "./views/dialogs/_ConfirmSpaceUserActionDialog.scss";
@import "./views/dialogs/_ConfirmUserActionDialog.scss";
@import "./views/dialogs/_CreateCommunityPrototypeDialog.scss";
Expand All @@ -99,6 +100,7 @@
@import "./views/dialogs/_MessageEditHistoryDialog.scss";
@import "./views/dialogs/_ModalWidgetDialog.scss";
@import "./views/dialogs/_NewSessionReviewDialog.scss";
@import "./views/dialogs/_PollCreateDialog.scss";
@import "./views/dialogs/_RegistrationEmailPromptDialog.scss";
@import "./views/dialogs/_RoomSettingsDialog.scss";
@import "./views/dialogs/_RoomSettingsDialogBridges.scss";
Expand Down
87 changes: 87 additions & 0 deletions res/css/views/dialogs/_CompoundDialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
Copyright 2021 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.
*/

// --------------------------------------------------------------------------------
// DEV NOTE: This stylesheet covers dialogs listed by the compound, including
// over multiple React components. The actual inner contents of the dialog should
// be in their respective stylesheets.
// --------------------------------------------------------------------------------

// Override legacy/default styles for dialogs
.mx_Dialog_wrapper.mx_CompoundDialog > .mx_Dialog {
padding: 0; // we'll manage it ourselves
color: $primary-content;
}

.mx_CompoundDialog {
.mx_CompoundDialog_header {
padding: 32px 32px 16px 32px;

h1 {
display: inline-block;
font-weight: 600;
font-size: $font-24px;
margin: 0; // managed by header class
}

.mx_CompoundDialog_cancelButton {
mask: url('$(res)/img/feather-customised/cancel.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: cover;
width: 20px;
height: 20px;
background-color: $dialog-close-fg-color;
cursor: pointer;

// Align with middle of title, 34px from right edge
position: absolute;
top: 34px;
right: 34px;
}
}

.mx_CompoundDialog_content {
overflow: auto;
padding: 8px 32px;
}

.mx_CompoundDialog_footer {
padding: 20px 32px;
text-align: right;
position: absolute;
bottom: 0;
left: 0;
right: 0;

.mx_AccessibleButton {
margin-left: 24px;
}
}
}

.mx_ScrollableBaseDialog {
width: 544px; // fixed
height: 516px; // fixed

.mx_CompoundDialog_content {
height: 349px; // dialogHeight - header - footer
}

.mx_CompoundDialog_footer {
box-shadow: 0px -4px 4px rgba(0, 0, 0, 0.05); // hardcoded colour for both themes
}
}
70 changes: 70 additions & 0 deletions res/css/views/dialogs/_PollCreateDialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright 2021 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_PollCreateDialog {
h2 {
font-weight: 600;
font-size: $font-15px;
line-height: $font-24px;
margin-top: 0;
margin-bottom: 8px;

&:nth-child(n + 2) {
margin-top: 20px;
}
}

.mx_PollCreateDialog_option {
display: flex;
align-items: center;
margin-top: 11px;
margin-bottom: 16px; // 11px from the top will collapse, so this creates a 16px gap between options

.mx_Field {
flex: 1;
margin: 0;
}

.mx_PollCreateDialog_removeOption {
margin-left: 12px;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: $quinary-content;
cursor: pointer;
position: relative;

&::before {
content: "";
mask: url('$(res)/img/element-icons/x-8px.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: cover;
width: 8px;
height: 8px;
position: absolute;
top: 6px;
left: 6px;
background-color: $secondary-content;
}
}
}

.mx_PollCreateDialog_addOption {
padding: 0;
margin-bottom: 40px; // arbitrary to create scrollable area under the poll
}
}
2 changes: 2 additions & 0 deletions res/css/views/elements/_AccessibleButton.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ limitations under the License.
align-items: center;
justify-content: center;
font-size: $font-14px;
border: none; // override default <button /> styles
}

.mx_AccessibleButton_kind_primary {
color: $button-primary-fg-color;
background-color: $button-primary-bg-color;
border: 1px solid $button-primary-bg-color; // account for size loss of no border
font-weight: 600;
}

Expand Down
3 changes: 2 additions & 1 deletion res/css/views/elements/_Field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ limitations under the License.
}

.mx_Field input:placeholder-shown:focus::placeholder,
.mx_Field textarea:placeholder-shown:focus::placeholder {
.mx_Field textarea:placeholder-shown:focus::placeholder,
.mx_Field.mx_Field_placeholderIsHint input::placeholder {
transition: color 0.25s ease-in 0.1s;
color: $greyed-fg-color;
}
Expand Down
4 changes: 4 additions & 0 deletions res/img/element-icons/x-8px.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 116 additions & 0 deletions src/components/views/dialogs/ScrollableBaseModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
Copyright 2021 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, { FormEvent } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { Key } from "../../../Keyboard";
import { IDialogProps } from "./IDialogProps";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import FocusLock from "react-focus-lock";
import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";

export interface IScrollableBaseState {
canSubmit: boolean;
title: string;
actionLabel: string;
}

/**
* Scrollable dialog base from Compound (Web Components).
*/
export default abstract class ScrollableBaseModal<TProps extends IDialogProps, TState extends IScrollableBaseState>
extends React.PureComponent<TProps, TState> {
protected constructor(props: TProps) {
super(props);
}

protected get matrixClient(): MatrixClient {
return MatrixClientPeg.get();
}

private onKeyDown = (e: KeyboardEvent | React.KeyboardEvent): void => {
if (e.key === Key.ESCAPE) {
e.stopPropagation();
e.preventDefault();
this.cancel();
}
};

private onCancel = () => {
this.cancel();
};

private onSubmit = (e: MouseEvent | FormEvent) => {
e.stopPropagation();
e.preventDefault();
if (!this.state.canSubmit) return; // pretend the submit button was disabled
this.submit();
};

protected abstract cancel(): void;
protected abstract submit(): void;
protected abstract renderContent(): React.ReactNode;

public render(): JSX.Element {
return (
<MatrixClientContext.Provider value={this.matrixClient}>
<FocusLock
returnFocus={true}
lockProps={{
onKeyDown: this.onKeyDown,
role: "dialog",
["aria-labelledby"]: "mx_CompoundDialog_title",

// Like BaseDialog, we'll just point this at the whole content
["aria-describedby"]: "mx_CompoundDialog_content",
}}
className="mx_CompoundDialog mx_ScrollableBaseDialog"
>
<div className="mx_CompoundDialog_header">
<h1>{ this.state.title }</h1>
<AccessibleButton
onClick={this.onCancel}
className="mx_CompoundDialog_cancelButton"
aria-label={_t("Close dialog")}
/>
</div>
<form onSubmit={this.onSubmit}>
<div className="mx_CompoundDialog_content">
{ this.renderContent() }
</div>
<div className="mx_CompoundDialog_footer">
<AccessibleButton onClick={this.onCancel} kind="primary_outline">
{ _t("Cancel") }
</AccessibleButton>
<AccessibleButton
onClick={this.onSubmit}
kind="primary"
disabled={!this.state.canSubmit}
type="submit"
element="button"
className="mx_Dialog_nonDialogButton"
>
{ this.state.actionLabel }
</AccessibleButton>
</div>
</form>
</FocusLock>
</MatrixClientContext.Provider>
);
}
}
Loading

0 comments on commit 73731cc

Please sign in to comment.