Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
feat: make sidebars resizeable (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
marionebl authored and Markus Ölhafen committed Jun 12, 2018
1 parent 9a6ebf5 commit 5c25262
Show file tree
Hide file tree
Showing 12 changed files with 3,273 additions and 3,444 deletions.
6,353 changes: 3,160 additions & 3,193 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
"mobx-react": "4.4.3",
"object-path": "0.11.4",
"query-string": "6.0.0",
"re-resizable": "4.4.8",
"react": "16.3.1",
"react-docgen": "2.20.1",
"react-docgen-typescript": "1.5.0",
Expand Down
2 changes: 2 additions & 0 deletions src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export interface LayoutProps {
const StyledLayout = styled.div`
display: flex;
width: 100%;
box-sizing: border-box;
flex-direction: ${(props: LayoutProps) =>
props.direction === LayoutDirection.Column ? 'column' : 'row'};
flex-wrap: ${(props: LayoutProps) => (props.wrap === LayoutWrap.Wrap ? 'wrap' : 'nowrap')};
Expand Down Expand Up @@ -84,6 +85,7 @@ const StyledMainArea = styled(StyledLayout)`

const StyledSideBar = styled(StyledLayout)`
flex-basis: 240px;
height: 100%;
overflow-y: hidden;
`;

Expand Down
16 changes: 0 additions & 16 deletions src/components/panes/element-pane/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { colors } from '../../colors';
import * as React from 'react';
import { getSpace, SpaceSize } from '../../space';
import styled from 'styled-components';
Expand All @@ -9,21 +8,6 @@ const StyledElementPane = styled.div`
overflow: scroll;
padding-top: ${getSpace(SpaceSize.M)}px;
padding-bottom: ${getSpace(SpaceSize.XL)}px;
&::after {
content: '';
position: sticky;
bottom: 0;
display: block;
width: 100%;
height: ${getSpace(SpaceSize.XXXL)}px;
background: linear-gradient(
to bottom,
${colors.grey97.toString('rgb', { alpha: 0 })},
${colors.grey97.toString('rgb', { alpha: 1 })}
);
z-index: 15;
}
`;

export const ElementPane: React.StatelessComponent = props => (
Expand Down
117 changes: 23 additions & 94 deletions src/components/panes/preview-pane/index.tsx
Original file line number Diff line number Diff line change
@@ -1,129 +1,58 @@
import { colors } from '../../colors';
import { remote } from 'electron';
import * as React from 'react';
import styled from 'styled-components';

export interface PreviewPaneProps {
id?: string;
onMouseDownLeft?: React.MouseEventHandler<HTMLElement>;
onMouseDownRight?: React.MouseEventHandler<HTMLElement>;
onMouseMove?: React.MouseEventHandler<HTMLElement>;
onMouseUp?: React.MouseEventHandler<HTMLElement>;
previewFrame?: string;
width?: number;
onPreviewWidthUpdate?(previewWidth: number): void;
}

const StyledPreviewWrapper = styled.div`
display: inline-flex;
justify-content: center;
flex-grow: 1;
flex-shrink: 0;
`;

const StyledPreviewResizer = styled.div`
position: absolute;
top: 0;
left: 0;
width: 11px;
height: 100%;
cursor: ew-resize;
background-color: ${colors.blackAlpha13.toString()};
opacity: 0;
transition: opacity 0.15s ease-in-out;
&::after {
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
height: 36px;
width: 3px;
margin: 4px;
border-radius: 2px;
background: ${colors.grey80.toString()};
}
&:hover {
opacity: 1;
&::after {
background: ${colors.grey60.toString()};
}
}
&:active {
opacity: 1;
&::after {
background: ${colors.white.toString()};
}
}
&:last-of-type {
right: 0;
left: auto;
}
`;

const BaseStyledPreviewPane = styled.div`
const StyledPreviewPane = styled.div`
position: relative;
flex-grow: 1;
overflow: hidden;
background: ${colors.white.toString()};
`;

const StyledPreviewPane = BaseStyledPreviewPane.extend.attrs({
style: (props: PreviewPaneProps) => ({
maxWidth: `${props.width}px` || 'none'
})
})`${(props: PreviewPaneProps) => ({})}`;

const StyledPreviewFrame = styled('iframe')`
const StyledFrame = styled.iframe`
position: ${(props: PreviewFrameProps) => (props.offCanvas ? 'absolute' : 'static')};
top: ${(props: PreviewFrameProps) => (props.offCanvas ? '100vh' : 'auto')};
width: 100%;
height: 100%;
border: none;
overflow: hidden;
border: none;
`;

class PreviewPane extends React.Component<PreviewPaneProps> {
private onResize: () => void;
private previewPane: HTMLElement;

public componentDidMount(): void {
this.updatePreviewWidth();
export interface PreviewFrameProps {
offCanvas: boolean;
src: string;
}

this.onResize = () => this.updatePreviewWidth();
remote.getCurrentWindow().addListener('resize', this.onResize);
}
const PreviewFrame: React.SFC<PreviewFrameProps> = props => <StyledFrame {...props} />;

public componentWillUnmount(): void {
remote.getCurrentWindow().removeListener('resize', this.onResize);
}
export interface PreviewPaneProps {
id?: string;
onMouseDownLeft?: React.MouseEventHandler<HTMLElement>;
onMouseDownRight?: React.MouseEventHandler<HTMLElement>;
onMouseMove?: React.MouseEventHandler<HTMLElement>;
onMouseUp?: React.MouseEventHandler<HTMLElement>;
width?: number;
onPreviewWidthUpdate?(previewWidth: number): void;
}

class PreviewPane extends React.Component<PreviewPaneProps> {
public render(): JSX.Element {
const props = this.props;

return (
<StyledPreviewWrapper
innerRef={(ref: HTMLElement) => (this.previewPane = ref)}
onMouseMove={props.onMouseMove}
onMouseUp={props.onMouseUp}
>
<StyledPreviewPane width={props.width}>
<StyledPreviewResizer onMouseDown={props.onMouseDownLeft} />
<StyledPreviewFrame src={props.previewFrame} />
<StyledPreviewResizer onMouseDown={props.onMouseDownRight} />
</StyledPreviewPane>
<StyledPreviewWrapper>
<StyledPreviewPane>{props.children}</StyledPreviewPane>
</StyledPreviewWrapper>
);
}

private updatePreviewWidth(): void {
if (!this.props.onPreviewWidthUpdate) {
return;
}

const previewWidth = this.previewPane.offsetWidth;
this.props.onPreviewWidthUpdate(previewWidth);
}
}

export default PreviewPane;
export { PreviewPane };
export { PreviewPane, PreviewFrame };
94 changes: 55 additions & 39 deletions src/container/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { ViewStore } from '../store';
import * as Types from '../model/types';
import * as uuid from 'uuid';

const Resizeable = require('re-resizable');

globalStyles();

@MobxReact.observer
Expand Down Expand Up @@ -106,51 +108,65 @@ export class App extends React.Component {
)}
{store.getActiveView() === Types.AlvaView.PageDetail && (
<React.Fragment>
<SideBar
side={LayoutSide.Left}
direction={LayoutDirection.Column}
onClick={() => store.unsetSelectedElement()}
border={LayoutBorder.Side}
<Resizeable
handleStyles={{ right: { zIndex: 1 } }}
defaultSize={{ width: 240, height: '100%' }}
enable={{ right: true }}
minWidth={240}
>
<ElementPane>
<ElementList />
</ElementPane>
<AddButton
active={store.getRightPane() === Types.RightPane.Patterns}
label="Add Elements"
onClick={e => {
e.stopPropagation();
store.setRightPane(Types.RightPane.Patterns);
store.unsetSelectedElement();
}}
/>
</SideBar>
<SideBar
side={LayoutSide.Left}
direction={LayoutDirection.Column}
onClick={() => store.unsetSelectedElement()}
border={LayoutBorder.Side}
>
<ElementPane>
<ElementList />
</ElementPane>
<AddButton
active={store.getRightPane() === Types.RightPane.Patterns}
label="Add Elements"
onClick={e => {
e.stopPropagation();
store.setRightPane(Types.RightPane.Patterns);
store.unsetSelectedElement();
}}
/>
</SideBar>
</Resizeable>
<PreviewPaneWrapper
key="center"
id="preview"
previewFrame={`http://localhost:${store.getServerPort()}/preview.html`}
/>
<SideBar
side={LayoutSide.Right}
direction={LayoutDirection.Column}
border={LayoutBorder.Side}
<Resizeable
handleStyles={{ left: { zIndex: 1 } }}
defaultSize={{ width: 240, height: '100%' }}
enable={{ left: true }}
minWidth={240}
>
{store.getPatternLibraryState() === Types.PatternLibraryState.Pristine && (
<ConnectPaneContainer
onPrimaryButtonClick={() => store.connectPatternLibrary()}
/>
)}
{store.getRightPane() === Types.RightPane.Properties && (
<PropertyPane>
<PropertyListContainer />
</PropertyPane>
)}
{store.getRightPane() === Types.RightPane.Patterns && (
<PatternsPane>
<PatternListContainer />
</PatternsPane>
)}
</SideBar>
<SideBar
side={LayoutSide.Right}
direction={LayoutDirection.Column}
border={LayoutBorder.Side}
>
{store.getPatternLibraryState() ===
Types.PatternLibraryState.Pristine && (
<ConnectPaneContainer
onPrimaryButtonClick={() => store.connectPatternLibrary()}
/>
)}
{store.getRightPane() === Types.RightPane.Properties && (
<PropertyPane>
<PropertyListContainer />
</PropertyPane>
)}
{store.getRightPane() === Types.RightPane.Patterns && (
<PatternsPane>
<PatternListContainer />
</PatternsPane>
)}
</SideBar>
</Resizeable>
</React.Fragment>
)}
</MainArea>
Expand Down
Loading

0 comments on commit 5c25262

Please sign in to comment.