ref(polls) Use new button component (#11918)
This commit is contained in:
parent
82b2e77747
commit
ffef8f78ea
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 } />}
|
||||
|
|
|
@ -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>
|
||||
);
|
|
@ -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>);
|
||||
|
|
@ -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>;
|
||||
};
|
Loading…
Reference in New Issue