Ui changes feedback changes

This commit is contained in:
Maksym Bykovskyy 2020-02-26 17:50:59 +00:00 committed by Jev Björsell
parent f39ff186d6
commit a0d0da3a42
7 changed files with 131 additions and 154 deletions

View File

@ -1,10 +1,6 @@
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import { Tooltip } from './tooltip';
const Container = styled.div` const Container = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
@ -32,34 +28,27 @@ const Input = styled.input<{ visible?: boolean }>`
`; `;
const Label = styled.div<{ visible?: boolean }>` const Label = styled.div<{ visible?: boolean }>`
display: flex;
align-items: center;
color: var(--blue); color: var(--blue);
opacity: 0; opacity: 0;
padding-left: 0.5em;
${props =>
props.visible &&
css`
opacity: 1;
`}
`;
const PencilIcon = ({ ...props }) => (
<FontAwesomeIcon {...props} icon={faPencilAlt} size="sm"></FontAwesomeIcon>
);
const Pencil = styled(PencilIcon)<{ visible: boolean }>`
margin-left: 10px;
cursor: pointer;
color: var(--label_foreground);
opacity: 0;
:hover { :hover {
opacity: 1; position: absolute;
background-color: white;
border-radius: var(--border_radius);
height: 2em;
border: none;
outline: none;
width: 15em;
} }
${props => ${props =>
props.visible && props.visible &&
css` css`
opacity: 0.5; opacity: 1;
`} `}
`; `;
@ -102,20 +91,18 @@ export const EditableTitleComponent = (props: {
} }
}} }}
></Input> ></Input>
<Label visible={!showInput}>{newTitle ? newTitle : 'Untitled'}</Label> <Label
<div> visible={!showInput}
<Pencil onClick={() => {
visible={!showInput} if (inputEl.current) {
onClick={() => { inputEl.current.select();
if (inputEl.current) { inputEl.current.setSelectionRange(0, 99999);
inputEl.current.select(); setShowInput(true);
inputEl.current.setSelectionRange(0, 99999); }
setShowInput(true); }}
} >
}} {newTitle ? newTitle : 'Untitled'}
></Pencil> </Label>
<Tooltip>Rename</Tooltip>
</div>
</Container> </Container>
); );
}; };

View File

@ -14,16 +14,6 @@ const Container = styled.div`
`; `;
const Header = styled.div` const Header = styled.div`
flex: 1;
display: flex;
justify-content: flex-start;
align-items: center;
min-height: 2.5em;
border-bottom: 5px solid var(--blue_trans1);
`;
const Subheader = styled.div`
flex: 1; flex: 1;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -31,10 +21,17 @@ const Subheader = styled.div`
background: var(--blue_trans1); background: var(--blue_trans1);
border: 5px solid rgba(0, 0, 0, 0); border: 5px solid rgba(0, 0, 0, 0);
border-top: none;
padding: 0 10px; padding: 0 10px;
`; `;
const LeftActions = styled.div`
display: flex;
`;
const StyledEditableTitleComponent = styled(EditableTitleComponent)`
margin-left: 20px;
`;
export const EditorComponent = () => { export const EditorComponent = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const title = useSelector<AppState, string>(state => state.editor.title); const title = useSelector<AppState, string>(state => state.editor.title);
@ -42,18 +39,18 @@ export const EditorComponent = () => {
return ( return (
<Container> <Container>
<Header> <Header>
<ShareComponent></ShareComponent> <LeftActions>
</Header> <ShareComponent></ShareComponent>
<Subheader> <StyledEditableTitleComponent
<EditableTitleComponent id="editor-title"
id="editor-title" title={title}
title={title} onChanged={value => {
onChanged={value => { dispatch({ ...new ChangeTitleAction(value) });
dispatch({ ...new ChangeTitleAction(value) }); }}
}} ></StyledEditableTitleComponent>
></EditableTitleComponent> </LeftActions>
<SyntaxSelectComponent></SyntaxSelectComponent> <SyntaxSelectComponent></SyntaxSelectComponent>
</Subheader> </Header>
<MonacoComponent></MonacoComponent> <MonacoComponent></MonacoComponent>
</Container> </Container>
); );

View File

@ -19,7 +19,7 @@ const Container = styled.div`
const MenuItem = styled.div<{ selected?: boolean }>` const MenuItem = styled.div<{ selected?: boolean }>`
padding: ${verticalPadding} 0 ${verticalPadding} 1em; padding: ${verticalPadding} 0 ${verticalPadding} 1em;
height: 1.5em; height: 1em;
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;

View File

@ -13,6 +13,7 @@ export const HGroup = styled.div`
export const Label = styled.label` export const Label = styled.label`
font-size: 1em; font-size: 1em;
color: var(--label_foreground); color: var(--label_foreground);
user-select: none;
`; `;
export const Input = styled.input` export const Input = styled.input`

View File

@ -1,6 +1,7 @@
import { faCopy } from '@fortawesome/free-solid-svg-icons'; import { faCopy, faLink } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import OutsideClickHandler from 'react-outside-click-handler';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
@ -16,84 +17,66 @@ const Container = styled.div`
align-items: center; align-items: center;
`; `;
const Icon = styled(FontAwesomeIcon)`
pointer-events: none;
`;
const Button = styled.div<{ clicked?: boolean }>` const Button = styled.div<{ clicked?: boolean }>`
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
z-index: 3;
z-index: 1;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 2em; width: 1.5em;
width: 6em; height: 1.5em;
color: var(--blue); border-radius: 50%;
background-color: white;
border-radius: 1em; background-color: #aaa;
transition: width 0.3s ease-in; color: var(--blue_opaque1);
&:hover {
background-color: white;
color: var(--blue);
opacity: 1;
}
${props => ${props =>
props.clicked && props.clicked &&
css` css`
width: 2em;
background-color: white; background-color: white;
`} color: var(--blue);
opacity: 1;
&:hover {
background-color: var(--blue_opaque1);
}
`;
const Label = styled.span<{ visible?: boolean }>`
pointer-events: none;
opacity: 1;
transition: opacity 0.3s ease-in;
${props =>
!props.visible &&
css`
opacity: 0;
`}
`;
const CopyIcon = ({ visible, ...props }: { visible: boolean }) => (
<FontAwesomeIcon {...props} icon={faCopy}></FontAwesomeIcon>
);
const Copy = styled(CopyIcon)`
position: absolute;
pointer-events: none;
opacity: 1;
transition: opacity 0.3s ease-in;
${props =>
!props.visible &&
css`
opacity: 0;
`} `}
`; `;
const Input = styled.input<{ visible?: boolean }>` const Input = styled.input<{ visible?: boolean }>`
position: absolute; position: absolute;
background-color: var(--blue);
border-radius: 1em;
opacity: 0;
height: 2em;
width: 2em;
transform: translateX(0.3em);
border: none; border: none;
padding-left: 2em; outline: none;
border-radius: 1em;
z-index: 2;
padding-left: 1.5em;
transform: translateX(0.3em);
font-size: 1em; font-size: 1em;
color: white; color: white;
background-color: var(--blue);
width: 2em;
height: 1.5em;
opacity: 0;
transition: width 0.1s ease-in-out, opacity 0s 0.1s;
transition: width 0.3s ease-in;
outline: none;
${props => ${props =>
props.visible && props.visible &&
css` css`
opacity: 1;
width: 25em; width: 25em;
opacity: 1;
transition: width 0.3s ease-in-out;
`} `}
`; `;
@ -118,59 +101,68 @@ export const ShareComponent = () => {
const shareLink = useSelector<AppState, ShareState['link']>( const shareLink = useSelector<AppState, ShareState['link']>(
state => state.share.link state => state.share.link
); );
const [clicked, setClicked] = useState(false);
const SHARE_TOOLTIP = 'Share code'; const SHARE_TOOLTIP = 'Share code';
const COPY_TOOLTIP = 'Copy link'; const COPY_TOOLTIP = 'Copy link';
const COPIED_TOOLTIP = 'Copied!'; const COPIED_TOOLTIP = 'Copied!';
const [tooltipMessage, setTooltipMessage] = useState(SHARE_TOOLTIP); const [tooltipMessage, setTooltipMessage] = useState(SHARE_TOOLTIP);
const [clicked, setClicked] = useState(false);
const [icon, setIcon] = useState(faLink);
const setInitialState = () => {
setClicked(false);
setIcon(faLink);
setTooltipMessage(SHARE_TOOLTIP);
};
const setClickedState = () => {
setClicked(true);
setIcon(faCopy);
setTooltipMessage(COPY_TOOLTIP);
};
useEffect(() => { useEffect(() => {
if (shareLink) { if (shareLink) {
if (inputEl.current && copy(inputEl.current)) { if (inputEl.current && copy(inputEl.current)) {
setTooltipMessage(COPIED_TOOLTIP); setTooltipMessage(COPIED_TOOLTIP);
} else {
setClicked(true);
setTooltipMessage(COPY_TOOLTIP);
} }
} else { } else {
setClicked(false); setInitialState();
setTooltipMessage(SHARE_TOOLTIP);
} }
}, [shareLink]); }, [shareLink]);
return ( return (
<Container> <OutsideClickHandler onOutsideClick={() => setInitialState()}>
<Input <Container>
id="share-link" <Input
visible={!!shareLink} id="share-link"
readOnly visible={!!shareLink && clicked}
ref={inputEl} readOnly
value={shareLink ? `${window.location.origin}/p/${shareLink}` : ''} ref={inputEl}
></Input> value={shareLink ? `${window.location.origin}/p/${shareLink}` : ''}
<Button ></Input>
id="share" <Button
clicked={clicked} id="share"
onMouseOver={() => { clicked={clicked}
if (tooltipMessage === COPIED_TOOLTIP) { onClick={() => {
setTooltipMessage(COPY_TOOLTIP); if (!clicked) {
} dispatch(shareAction());
}} setClickedState();
onClick={() => { } else if (inputEl.current) {
if (!shareLink) { copy(inputEl.current);
dispatch(shareAction()); setTooltipMessage(COPIED_TOOLTIP);
setClicked(true); }
setTooltipMessage(COPY_TOOLTIP); }}
} else if (inputEl.current) { onMouseOver={() => {
copy(inputEl.current); if (tooltipMessage === COPIED_TOOLTIP) {
setTooltipMessage(COPIED_TOOLTIP); setTooltipMessage(COPY_TOOLTIP);
} }
}} }}
> >
<Label visible={!clicked}>Share</Label> <Icon icon={icon}></Icon>
<Copy visible={clicked}></Copy> <Tooltip>{tooltipMessage}</Tooltip>
<Tooltip>{tooltipMessage}</Tooltip> </Button>
</Button> </Container>
</Container> </OutsideClickHandler>
); );
}; };

View File

@ -48,7 +48,7 @@
--font_ghost_weight: 700; --font_ghost_weight: 700;
--font_ghost_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */ --font_ghost_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */
--content_height: 80vh; --content_height: 85vh;
--tooltip_foreground: white; --tooltip_foreground: white;
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/; --tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;

View File

@ -1,7 +1,7 @@
import latestSchema from '../../src/schemas/share-latest'; import latestSchema from '../../src/schemas/share-latest';
describe('Latest Share Schema Migration', () => { describe('Latest Share Schema Migration', () => {
it('should be v1', () => { it('should be v2', () => {
expect(latestSchema.VERSION).toEqual('v1'); expect(latestSchema.VERSION).toEqual('v2');
}); });
}); });