Skip to content

Commit

Permalink
fix: Toolbar status messages fixes & support hiding editor (#145)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltaranto authored Apr 22, 2020
1 parent ebb796b commit 0ce6c2d
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 31 deletions.
60 changes: 59 additions & 1 deletion src/Playroom/Playroom.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
width: 100%;
height: 100%;
overflow: hidden;
background-color: @code-background;
background-color: @body;
}

:global(body) {
Expand All @@ -30,16 +30,74 @@
right: 0;
overflow: hidden;
box-shadow: @shadow-small;
transition: @transition-slow;
}

.resizeableContainer_isRight {
top: 0;
max-width: 90vw;

&.resizeableContainer_isHidden {
transform: translateX(100%);
}
}

.resizeableContainer_isBottom {
left: 0;
max-height: 90vh;

&.resizeableContainer_isHidden {
transform: translateY(100%);
}
}

.toggleEditorContainer {
position: absolute;
bottom: 0;
right: 0;
display: flex;
justify-content: center;

&.isBottom {
width: @toolbar-item-size;
}
}

.toggleEditorButton {
position: relative;
appearance: none;
background: none;
outline: none;
border: 0;
padding: 0;
border-radius: @radius-large;
min-width: @interaction-height;
width: 100%;
height: @interaction-height;
cursor: pointer;

&:not(:hover):not(:focus) {
opacity: @preview-inactive-label-opacity;
}

&:before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: currentColor;
border-radius: @radius-large;
opacity: 0;
transition: @transition-slow;
pointer-events: none;

:hover&,
:focus& {
opacity: 0.05;
}
}
}

.editorContainer {
Expand Down
47 changes: 41 additions & 6 deletions src/Playroom/Playroom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import WindowPortal from './WindowPortal';
import { Snippets } from '../../utils';
import componentsToHints from '../utils/componentsToHints';
import Toolbar from './Toolbar/Toolbar';
import ChevronSvg from './Toolbar/icons/ChevronSvg';
import { StoreContext, EditorPosition } from '../StoreContext/StoreContext';

// @ts-ignore
Expand Down Expand Up @@ -53,6 +54,17 @@ const resizableConfig = (position: EditorPosition = 'bottom') => ({
topLeft: false
});

const resolveDirection = (
editorPosition: EditorPosition,
editorHidden: boolean
) => {
if (editorPosition === 'right') {
return editorHidden ? 'left' : 'right';
}

return editorHidden ? 'up' : 'down';
};

export interface PlayroomProps {
components: Record<string, ComponentType>;
themes: string[];
Expand All @@ -66,6 +78,7 @@ export default ({ components, themes, widths, snippets }: PlayroomProps) => {
editorPosition,
editorHeight,
editorWidth,
editorHidden,
visibleThemes,
visibleWidths,
code,
Expand Down Expand Up @@ -142,7 +155,8 @@ export default ({ components, themes, widths, snippets }: PlayroomProps) => {
<Resizable
className={classnames(styles.resizeableContainer, {
[styles.resizeableContainer_isRight]: isVerticalEditor,
[styles.resizeableContainer_isBottom]: isHorizontalEditor
[styles.resizeableContainer_isBottom]: isHorizontalEditor,
[styles.resizeableContainer_isHidden]: editorHidden
})}
defaultSize={sizeStyles}
size={sizeStyles}
Expand All @@ -162,11 +176,13 @@ export default ({ components, themes, widths, snippets }: PlayroomProps) => {
<div
className={styles.previewContainer}
style={
{
right: { right: editorWidth },
bottom: { bottom: editorHeight },
undocked: undefined
}[editorPosition]
editorHidden
? undefined
: {
right: { right: editorWidth },
bottom: { bottom: editorHeight },
undocked: undefined
}[editorPosition]
}
>
<Preview
Expand All @@ -178,6 +194,25 @@ export default ({ components, themes, widths, snippets }: PlayroomProps) => {
visibleWidths && visibleWidths.length > 0 ? visibleWidths : widths
}
/>
<div
className={classnames(styles.toggleEditorContainer, {
[styles.isBottom]: isHorizontalEditor
})}
>
<button
className={styles.toggleEditorButton}
title={`${editorHidden ? 'Show' : 'Hide'} the editor`}
onClick={() =>
dispatch({ type: editorHidden ? 'showEditor' : 'hideEditor' })
}
>
<ChevronSvg
height={16}
width={16}
direction={resolveDirection(editorPosition, editorHidden)}
/>
</button>
</div>
</div>
{editorContainer}
</div>
Expand Down
3 changes: 1 addition & 2 deletions src/Playroom/Preview/Preview.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
@frame-name-height: 30px;

.root {
background-color: @preview-background;
box-sizing: border-box;
width: 100%;
height: 100%;
Expand Down Expand Up @@ -50,7 +49,7 @@
transition: @transition-medium;

.frameContainer:not(:hover) & {
opacity: 0.3;
opacity: @preview-inactive-label-opacity;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Playroom/Toolbar/Toolbar.less
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
display: flex;
flex-direction: row-reverse;
color: @toolbar-foregound;
overflow: hidden;

&.isOpen {
width: 100vw;
Expand All @@ -26,6 +25,7 @@
pointer-events: none;
height: 100%;
flex-direction: row-reverse;
overflow: hidden;
}

.topButtons {
Expand Down
52 changes: 32 additions & 20 deletions src/Playroom/Toolbar/Toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useContext, ReactChild, useEffect, useState } from 'react';
import React, { useContext, ReactChild, useState, useCallback } from 'react';
import { useTimeoutFn } from 'react-use';
import copy from 'copy-to-clipboard';
import classnames from 'classnames';
import { PlayroomProps } from '../Playroom';
Expand Down Expand Up @@ -54,13 +55,19 @@ export default ({ themes: allThemes, widths: allWidths, snippets }: Props) => {
dispatch
] = useContext(StoreContext);
const [copying, setCopying] = useState(false);
const [isReady, cancel, reset] = useTimeoutFn(() => setCopying(false), 2000);

useEffect(() => {
if (copying) {
copy(window.location.href);
setTimeout(() => setCopying(false), 2000);
const copyHandler = useCallback(() => {
copy(window.location.href);
dispatch({ type: 'closeToolbar' });
setCopying(true);

if (isReady() === false) {
cancel();
}
}, [copying]);

reset();
}, [cancel, dispatch, isReady, reset]);

const isSnippetsOpen = activeToolbarPanel === 'snippets';
const isThemeOpen = activeToolbarPanel === 'themes';
Expand Down Expand Up @@ -97,16 +104,19 @@ export default ({ themes: allThemes, widths: allWidths, snippets }: Props) => {
title={`Insert snippet (${
navigator.platform.match('Mac') ? '\u2318' : 'Ctrl + '
}K)`}
showStatus={!validCursorPosition}
showStatus={
!copying && !validCursorPosition && !activeToolbarPanel
}
statusMessage="Can't insert snippet at cursor"
statusMessageTone="critical"
data-testid="toggleSnippets"
onClick={() =>
onClick={() => {
setCopying(false);
dispatch({
type: 'toggleToolbar',
payload: { panel: 'snippets' }
})
}
});
}}
>
<AddSvg />
</ToolbarItem>
Expand All @@ -120,12 +130,13 @@ export default ({ themes: allThemes, widths: allWidths, snippets }: Props) => {
? `Showing ${visibleThemes.length} of ${allThemes.length} themes`
: 'Configure themes'
}
onClick={() =>
onClick={() => {
setCopying(false);
dispatch({
type: 'toggleToolbar',
payload: { panel: 'themes' }
})
}
});
}}
>
<ThemesSvg />
</ToolbarItem>
Expand All @@ -138,24 +149,25 @@ export default ({ themes: allThemes, widths: allWidths, snippets }: Props) => {
? `Showing ${visibleWidths.length} of ${allWidths.length} widths`
: 'Configure widths'
}
onClick={() =>
onClick={() => {
setCopying(false);
dispatch({
type: 'toggleToolbar',
payload: { panel: 'widths' }
})
}
});
}}
data-testid="toggleWidths"
>
<WidthsSvg />
</ToolbarItem>

<ToolbarItem
active={copying}
active={copying && !activeToolbarPanel}
title="Copy link to clipboard"
statusMessage="Link copied to clipboard"
statusMessageTone="positive"
showStatus={copying}
onClick={() => setCopying(true)}
showStatus={copying && !activeToolbarPanel}
onClick={copyHandler}
data-testid="copyToClipboard"
>
<ShareSvg />
Expand Down Expand Up @@ -185,7 +197,7 @@ export default ({ themes: allThemes, widths: allWidths, snippets }: Props) => {
.filter(pos => pos !== editorPosition)
.map(pos => {
const position = pos as EditorPosition;
return (
return position === 'undocked' ? null : (
<div
key={position}
hidden={isPositionOpen ? undefined : true}
Expand Down
15 changes: 15 additions & 0 deletions src/Playroom/Toolbar/icons/ChevronSvg.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@import (reference) '../../variables.less';

.root {
transition: @transition-medium;
transform-origin: 50% 50%;
}
.left {
transform: rotate(90deg);
}
.up {
transform: rotate(180deg);
}
.right {
transform: rotate(270deg);
}
27 changes: 27 additions & 0 deletions src/Playroom/Toolbar/icons/ChevronSvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { SVGProps } from 'react';
import classnames from 'classnames';

// @ts-ignore
import styles from './ChevronSvg.less';

interface ChevronSvgProps extends SVGProps<SVGSVGElement> {
direction?: 'down' | 'up' | 'left' | 'right';
}

export default ({ direction = 'down', ...props }: ChevronSvgProps) => (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
focusable="false"
fill="currentColor"
className={classnames(styles.root, {
[styles.up]: direction === 'up',
[styles.left]: direction === 'left',
[styles.right]: direction === 'right'
})}
{...props}
>
<path d="M20.7 7.3c-.4-.4-1-.4-1.4 0L12 14.6 4.7 7.3c-.4-.4-1-.4-1.4 0s-.4 1 0 1.4l8 8c.2.2.5.3.7.3s.5-.1.7-.3l8-8c.4-.4.4-1 0-1.4z" />
</svg>
);
5 changes: 4 additions & 1 deletion src/Playroom/variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@
@transition-slow: opacity @transition-speed-slow ease,
transform @transition-speed-slow ease;

// Playroom
@body: @gray-1;

// Preview
@preview-padding: @gutter-width;
@preview-background: @gray-1;
@preview-foregound: @gray-4;
@preview-inactive-label-opacity: 0.3;

// Code Editor
@code-background: @white;
Expand Down
Loading

0 comments on commit 0ce6c2d

Please sign in to comment.