ref(polls) Use new button component (#11918)

This commit is contained in:
Robert Pintilii 2022-07-28 16:45:32 +03:00 committed by GitHub
parent 82b2e77747
commit ffef8f78ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 125 additions and 164 deletions

View File

@ -291,6 +291,10 @@ ol.poll-result-list {
h1, strong ,span {
color: #fff;
}
button > span {
color: inherit;
}
}
.poll-create-label {
@ -363,82 +367,3 @@ ol.poll-result-list {
.poll-answer-footer {
padding: 8px 0 0 0;
}
.poll-button {
align-items: center;
border: 0;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
display: flex;
justify-content: center;
min-height: 40px;
width: 100%;
&:disabled {
cursor: initial;
}
@media (max-width: 580px) {
min-height: 48px;
}
}
.poll-button-primary {
background-color: #0056E0;
&:hover {
background-color: #246FE5;
}
&:active {
background-color: #0045B3;
}
&:focus {
background-color: #0045B3;
border: 3px solid #99BBF3;
}
&:disabled {
background-color: #00225A;
color: #858585;
}
}
.poll-button-secondary {
background-color: #3D3D3D;
&:hover {
background-color: #525252;
}
&:active {
background-color: #292929;
}
&:focus {
background-color: #292929;
border: 3px solid #858585;
}
&:disabled {
background-color: #141414;
color: #858585;
}
}
.poll-button-short {
max-width: 132px;
}
.poll-button-shortest {
max-width: 117px;
}
.poll-button-short,
.poll-button-shortest {
@media (max-width: 580px) {
min-width: 49%;
}
}

View File

@ -26,10 +26,15 @@ interface IButtonProps extends ButtonProps {
*/
id?: string;
/**
* Whether or not the button is a submit form button.
*/
isSubmit?: boolean;
/**
* Click callback.
*/
onClick: (e?: React.MouseEvent<HTMLButtonElement>) => void;
onClick?: (e?: React.MouseEvent<HTMLButtonElement>) => void;
/**
* Which size the button should be.
@ -178,8 +183,9 @@ const Button = ({
fullWidth,
icon,
id,
isSubmit,
label,
onClick,
onClick = () => null,
size = 'medium',
testId,
type = BUTTON_TYPES.PRIMARY
@ -197,7 +203,7 @@ const Button = ({
disabled = { disabled }
{ ...(id ? { id } : {}) }
onClick = { onClick }
type = 'button'>
type = { isSubmit ? 'submit' : 'button' }>
{icon && <Icon
size = { 20 }
src = { icon } />}

View File

@ -1,24 +1,38 @@
// @flow
/* eslint-disable lines-around-comment */
import { Checkbox } from '@atlaskit/checkbox';
import { makeStyles } from '@material-ui/styles';
import React from 'react';
import Button from '../../../base/ui/components/web/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants';
import { Theme } from '../../../base/ui/types';
// @ts-ignore
import { isSubmitAnswerDisabled } from '../../functions';
// @ts-ignore
import AbstractPollAnswer from '../AbstractPollAnswer';
// @ts-ignore
import type { AbstractProps } from '../AbstractPollAnswer';
const PollAnswer = (props: AbstractProps) => {
const {
creatorName,
checkBoxStates,
poll,
setCheckbox,
skipAnswer,
skipChangeVote,
submitAnswer,
t
} = props;
const useStyles = makeStyles((theme: Theme) => {
return {
buttonMargin: {
marginRight: `${theme.spacing(2)}px`
}
};
});
const PollAnswer = ({
creatorName,
checkBoxStates,
poll,
setCheckbox,
skipAnswer,
skipChangeVote,
submitAnswer,
t
}: AbstractProps) => {
const { changingVote } = poll;
const styles = useStyles();
return (
<div className = 'poll-answer'>
@ -32,7 +46,7 @@ const PollAnswer = (props: AbstractProps) => {
</div>
<ol className = 'poll-answer-list'>
{
poll.answers.map((answer, index) => (
poll.answers.map((answer: any, index: number) => (
<li
className = 'poll-answer-container'
key = { index }>
@ -48,19 +62,19 @@ const PollAnswer = (props: AbstractProps) => {
}
</ol>
<div className = 'poll-footer poll-answer-footer' >
<button
aria-label = { t('polls.answer.skip') }
className = 'poll-button poll-button-secondary poll-button-shortest'
onClick = { changingVote ? skipChangeVote : skipAnswer } >
<span>{t('polls.answer.skip')}</span>
</button>
<button
aria-label = { t('polls.answer.submit') }
className = 'poll-button poll-button-primary poll-button-shortest'
<Button
accessibilityLabel = { t('polls.answer.skip') }
className = { styles.buttonMargin }
fullWidth = { true }
label = { t('polls.answer.skip') }
onClick = { changingVote ? skipChangeVote : skipAnswer }
type = { BUTTON_TYPES.SECONDARY } />
<Button
accessibilityLabel = { t('polls.answer.submit') }
disabled = { isSubmitAnswerDisabled(checkBoxStates) }
onClick = { submitAnswer }>
<span>{t('polls.answer.submit')}</span>
</button>
fullWidth = { true }
label = { t('polls.answer.submit') }
onClick = { submitAnswer } />
</div>
</div>
);

View File

@ -1,35 +1,49 @@
// @flow
/* eslint-disable lines-around-comment */
import { makeStyles } from '@material-ui/core';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Icon, IconMenu } from '../../../base/icons';
import Icon from '../../../base/icons/components/Icon';
import { IconMenu } from '../../../base/icons/svg/index';
// @ts-ignore
import { Tooltip } from '../../../base/tooltip';
import Button from '../../../base/ui/components/web/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants';
import { Theme } from '../../../base/ui/types';
// @ts-ignore
import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants';
// @ts-ignore
import AbstractPollCreate from '../AbstractPollCreate';
// @ts-ignore
import type { AbstractProps } from '../AbstractPollCreate';
const PollCreate = (props: AbstractProps) => {
const useStyles = makeStyles((theme: Theme) => {
return {
buttonMargin: {
marginRight: `${theme.spacing(2)}px`
}
};
});
const {
addAnswer,
answers,
isSubmitDisabled,
moveAnswer,
onSubmit,
question,
removeAnswer,
setAnswer,
setCreateMode,
setQuestion,
t
} = props;
const PollCreate = ({
addAnswer,
answers,
isSubmitDisabled,
moveAnswer,
onSubmit,
question,
removeAnswer,
setAnswer,
setCreateMode,
setQuestion,
t
}: AbstractProps) => {
const styles = useStyles();
/*
* This ref stores the Array of answer input fields, allowing us to focus on them.
* This array is maintained by registerfieldRef and the useEffect below.
*/
const answerInputs = useRef([]);
const answerInputs = useRef<Array<HTMLInputElement>>([]);
const registerFieldRef = useCallback((i, r) => {
if (r === null) {
return;
@ -45,7 +59,7 @@ const PollCreate = (props: AbstractProps) => {
* This state allows us to requestFocus asynchronously, without having to worry
* about whether a newly created input field has been rendered yet or not.
*/
const [ lastFocus, requestFocus ] = useState(null);
const [ lastFocus, requestFocus ] = useState<number|null>(null);
useEffect(() => {
if (lastFocus === null) {
@ -82,7 +96,7 @@ const PollCreate = (props: AbstractProps) => {
if (ev.ctrlKey || ev.metaKey || ev.altKey || ev.shiftKey) {
return;
}
});
}, []);
const onQuestionKeyDown = useCallback(ev => {
if (checkModifiers(ev)) {
@ -93,7 +107,7 @@ const PollCreate = (props: AbstractProps) => {
requestFocus(0);
ev.preventDefault();
}
});
}, []);
// Called on keypress in answer fields
const onAnswerKeyDown = useCallback((i, ev) => {
@ -132,7 +146,7 @@ const PollCreate = (props: AbstractProps) => {
const [ grabbing, setGrabbing ] = useState(null);
const interchangeHeights = (i, j) => {
const interchangeHeights = (i: number, j: number) => {
const h = answerInputs.current[i].scrollHeight;
answerInputs.current[i].style.height = `${answerInputs.current[j].scrollHeight}px`;
@ -151,16 +165,17 @@ const PollCreate = (props: AbstractProps) => {
return null;
});
}, { once: true });
});
}, []);
const onMouseOver = useCallback(i => {
if (grabbing !== null && grabbing !== i) {
interchangeHeights(i, grabbing);
moveAnswer(grabbing, i);
setGrabbing(i);
}
});
}, []);
const autogrow = ev => {
const autogrow = (ev: React.ChangeEvent<HTMLTextAreaElement>) => {
const el = ev.target;
el.style.height = '1px';
@ -188,11 +203,11 @@ const PollCreate = (props: AbstractProps) => {
onKeyDown = { onQuestionKeyDown }
placeholder = { t('polls.create.questionPlaceholder') }
required = { true }
row = '1'
rows = { 1 }
value = { question } />
</div>
<ol className = 'poll-answer-field-list'>
{answers.map((answer, i) =>
{answers.map((answer: any, i: number) =>
(<li
className = { `poll-answer-field${grabbing === i ? ' poll-dragged' : ''}` }
key = { i }
@ -210,12 +225,12 @@ const PollCreate = (props: AbstractProps) => {
placeholder = { t('polls.create.answerPlaceholder', { index: i + 1 }) }
ref = { r => registerFieldRef(i, r) }
required = { true }
row = { 1 }
rows = { 1 }
value = { answer } />
<button
className = 'poll-drag-handle'
onMouseDown = { ev => onGrab(i, ev) }
tabIndex = '-1'
tabIndex = { -1 }
type = 'button'>
<Icon src = { IconMenu } />
</button>
@ -234,34 +249,32 @@ const PollCreate = (props: AbstractProps) => {
)}
</ol>
<div className = 'poll-add-button'>
<button
aria-label = { 'Add option' }
className = 'poll-button poll-button-secondary'
<Button
accessibilityLabel = { t('polls.create.addOption') }
disabled = { answers.length >= ANSWERS_LIMIT }
fullWidth = { true }
label = { t('polls.create.addOption') }
onClick = { () => {
addAnswer();
requestFocus(answers.length);
} }
type = 'button' >
<span>{t('polls.create.addOption')}</span>
</button>
type = { BUTTON_TYPES.SECONDARY } />
</div>
</div>
<div className = 'poll-footer poll-create-footer'>
<button
aria-label = { t('polls.create.cancel') }
className = 'poll-button poll-button-secondary poll-button-short'
<Button
accessibilityLabel = { t('polls.create.cancel') }
className = { styles.buttonMargin }
fullWidth = { true }
label = { t('polls.create.cancel') }
onClick = { () => setCreateMode(false) }
type = 'button' >
<span>{t('polls.create.cancel')}</span>
</button>
<button
aria-label = { t('polls.create.send') }
className = 'poll-button poll-button-primary poll-button-short'
type = { BUTTON_TYPES.SECONDARY } />
<Button
accessibilityLabel = { t('polls.create.send') }
disabled = { isSubmitDisabled }
type = 'submit' >
<span>{t('polls.create.send')}</span>
</button>
fullWidth = { true }
isSubmit = { true }
label = { t('polls.create.send') } />
</div>
</form>);

View File

@ -1,11 +1,15 @@
// @flow
/* eslint-disable lines-around-comment */
import React from 'react';
import Button from '../../../base/ui/components/web/Button';
// @ts-ignore
import AbstractPollsPane from '../AbstractPollsPane';
// @ts-ignore
import type { AbstractProps } from '../AbstractPollsPane';
// @ts-ignore
import PollCreate from './PollCreate';
// @ts-ignore
import PollsList from './PollsList';
@ -19,13 +23,12 @@ const PollsPane = (props: AbstractProps) => {
<PollsList />
</div>
<div className = 'poll-footer poll-create-footer'>
<button
aria-label = { t('polls.create.create') }
className = 'poll-button poll-button-primary'
<Button
accessibilityLabel = { t('polls.create.create') }
fullWidth = { true }
label = { t('polls.create.create') }
// eslint-disable-next-line react/jsx-no-bind
onClick = { onCreate } >
<span>{t('polls.create.create')}</span>
</button>
onClick = { onCreate } />
</div>
</div>;
};