chore: Loading placeholders (#2322)
* Improve visual of loading mask * Normalize placeholder naming * Remove unused file
This commit is contained in:
@ -15,7 +15,7 @@ import RevisionsStore from "stores/RevisionsStore";
|
|||||||
|
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
import PlaceholderList from "components/List/Placeholder";
|
||||||
import Revision from "./components/Revision";
|
import Revision from "./components/Revision";
|
||||||
import { documentHistoryUrl, documentUrl } from "utils/routeHelpers";
|
import { documentHistoryUrl, documentUrl } from "utils/routeHelpers";
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ class DocumentHistory extends React.Component<Props> {
|
|||||||
</Header>
|
</Header>
|
||||||
{showLoading ? (
|
{showLoading ? (
|
||||||
<Loading>
|
<Loading>
|
||||||
<ListPlaceholder count={5} />
|
<PlaceholderList count={5} />
|
||||||
</Loading>
|
</Loading>
|
||||||
) : (
|
) : (
|
||||||
<ArrowKeyNavigation
|
<ArrowKeyNavigation
|
||||||
|
@ -45,7 +45,7 @@ const Container = styled.div`
|
|||||||
align-items: ${({ align }) => align};
|
align-items: ${({ align }) => align};
|
||||||
justify-content: ${({ justify }) => justify};
|
justify-content: ${({ justify }) => justify};
|
||||||
flex-shrink: ${({ shrink }) => (shrink ? 1 : "initial")};
|
flex-shrink: ${({ shrink }) => (shrink ? 1 : "initial")};
|
||||||
gap: ${({ gap }) => `${gap}px` || "initial"};
|
gap: ${({ gap }) => (gap ? `${gap}px` : "initial")};
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
`;
|
`;
|
||||||
|
@ -4,18 +4,19 @@ import * as React from "react";
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import Fade from "components/Fade";
|
import Fade from "components/Fade";
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Mask from "components/Mask";
|
import PlaceholderText from "components/PlaceholderText";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number,
|
count?: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Placeholder = ({ count }: Props) => {
|
const ListPlaceHolder = ({ count }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Fade>
|
<Fade>
|
||||||
{times(count || 2, (index) => (
|
{times(count || 2, (index) => (
|
||||||
<Item key={index} column auto>
|
<Item key={index} column auto>
|
||||||
<Mask />
|
<PlaceholderText header delay={0.2 * index} />
|
||||||
|
<PlaceholderText delay={0.2 * index} />
|
||||||
</Item>
|
</Item>
|
||||||
))}
|
))}
|
||||||
</Fade>
|
</Fade>
|
||||||
@ -23,7 +24,7 @@ const Placeholder = ({ count }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Item = styled(Flex)`
|
const Item = styled(Flex)`
|
||||||
padding: 15px 0 16px;
|
padding: 10px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Placeholder;
|
export default ListPlaceHolder;
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import { times } from "lodash";
|
|
||||||
import * as React from "react";
|
|
||||||
import styled from "styled-components";
|
|
||||||
import Fade from "components/Fade";
|
|
||||||
import Flex from "components/Flex";
|
|
||||||
import Mask from "components/Mask";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
count?: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ListPlaceHolder = ({ count }: Props) => {
|
|
||||||
return (
|
|
||||||
<Fade>
|
|
||||||
{times(count || 2, (index) => (
|
|
||||||
<Item key={index} column auto>
|
|
||||||
<Mask header />
|
|
||||||
<Mask />
|
|
||||||
</Item>
|
|
||||||
))}
|
|
||||||
</Fade>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Item = styled(Flex)`
|
|
||||||
padding: 10px 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default ListPlaceHolder;
|
|
@ -1,6 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import ListPlaceholder from "./ListPlaceholder";
|
|
||||||
import LoadingPlaceholder from "./LoadingPlaceholder";
|
|
||||||
|
|
||||||
export default LoadingPlaceholder;
|
|
||||||
export { ListPlaceholder };
|
|
@ -7,7 +7,7 @@ import * as React from "react";
|
|||||||
import { Waypoint } from "react-waypoint";
|
import { Waypoint } from "react-waypoint";
|
||||||
import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
|
import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
|
||||||
import DelayedMount from "components/DelayedMount";
|
import DelayedMount from "components/DelayedMount";
|
||||||
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
import PlaceholderList from "components/List/Placeholder";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
fetch?: (options: ?Object) => Promise<void>,
|
fetch?: (options: ?Object) => Promise<void>,
|
||||||
@ -128,7 +128,7 @@ class PaginatedList extends React.Component<Props> {
|
|||||||
)}
|
)}
|
||||||
{showLoading && (
|
{showLoading && (
|
||||||
<DelayedMount>
|
<DelayedMount>
|
||||||
<ListPlaceholder count={5} />
|
<PlaceholderList count={5} />
|
||||||
</DelayedMount>
|
</DelayedMount>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -4,18 +4,19 @@ import styled from "styled-components";
|
|||||||
import DelayedMount from "components/DelayedMount";
|
import DelayedMount from "components/DelayedMount";
|
||||||
import Fade from "components/Fade";
|
import Fade from "components/Fade";
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Mask from "components/Mask";
|
import PlaceholderText from "components/PlaceholderText";
|
||||||
|
|
||||||
export default function LoadingPlaceholder(props: Object) {
|
export default function PlaceholderDocument(props: Object) {
|
||||||
return (
|
return (
|
||||||
<DelayedMount>
|
<DelayedMount>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Flex column auto {...props}>
|
<Flex column auto {...props}>
|
||||||
<Mask height={34} />
|
<PlaceholderText height={34} maxWidth={70} />
|
||||||
|
<PlaceholderText delay={0.2} maxWidth={40} />
|
||||||
<br />
|
<br />
|
||||||
<Mask />
|
<PlaceholderText delay={0.2} />
|
||||||
<Mask />
|
<PlaceholderText delay={0.4} />
|
||||||
<Mask />
|
<PlaceholderText delay={0.6} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
</DelayedMount>
|
</DelayedMount>
|
@ -10,36 +10,40 @@ type Props = {|
|
|||||||
height?: number,
|
height?: number,
|
||||||
minWidth?: number,
|
minWidth?: number,
|
||||||
maxWidth?: number,
|
maxWidth?: number,
|
||||||
|
delay?: number,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
class Mask extends React.Component<Props> {
|
class PlaceholderText extends React.Component<Props> {
|
||||||
width: number;
|
width = randomInteger(this.props.minWidth || 75, this.props.maxWidth || 100);
|
||||||
|
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: Props) {
|
|
||||||
super();
|
|
||||||
this.width = randomInteger(props.minWidth || 75, props.maxWidth || 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <Redacted width={this.width} height={this.props.height} />;
|
return (
|
||||||
|
<Mask
|
||||||
|
width={this.width}
|
||||||
|
height={this.props.height}
|
||||||
|
delay={this.props.delay}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Redacted = styled(Flex)`
|
const Mask = styled(Flex)`
|
||||||
width: ${(props) => (props.header ? props.width / 2 : props.width)}%;
|
width: ${(props) => (props.header ? props.width / 2 : props.width)}%;
|
||||||
height: ${(props) =>
|
height: ${(props) =>
|
||||||
props.height ? props.height : props.header ? 24 : 18}px;
|
props.height ? props.height : props.header ? 24 : 18}px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
background-color: ${(props) => props.theme.divider};
|
background-color: ${(props) => props.theme.divider};
|
||||||
animation: ${pulsate} 1.3s infinite;
|
animation: ${pulsate} 2s infinite;
|
||||||
|
animation-delay: ${(props) => props.delay || 0}s;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Mask;
|
export default PlaceholderText;
|
@ -9,9 +9,9 @@ import Fade from "components/Fade";
|
|||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import useStores from "../../../hooks/useStores";
|
import useStores from "../../../hooks/useStores";
|
||||||
import CollectionLink from "./CollectionLink";
|
import CollectionLink from "./CollectionLink";
|
||||||
import CollectionsLoading from "./CollectionsLoading";
|
|
||||||
import DropCursor from "./DropCursor";
|
import DropCursor from "./DropCursor";
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
|
import PlaceholderCollections from "./PlaceholderCollections";
|
||||||
import SidebarLink from "./SidebarLink";
|
import SidebarLink from "./SidebarLink";
|
||||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -105,7 +105,7 @@ function Collections({ onCreateCollection }: Props) {
|
|||||||
return (
|
return (
|
||||||
<Flex column>
|
<Flex column>
|
||||||
<Header>{t("Collections")}</Header>
|
<Header>{t("Collections")}</Header>
|
||||||
<CollectionsLoading />
|
<PlaceholderCollections />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
// @flow
|
|
||||||
import * as React from "react";
|
|
||||||
import styled from "styled-components";
|
|
||||||
import Mask from "components/Mask";
|
|
||||||
|
|
||||||
function CollectionsLoading() {
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<Mask />
|
|
||||||
<Mask />
|
|
||||||
<Mask />
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
margin: 4px 16px;
|
|
||||||
width: 75%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default CollectionsLoading;
|
|
21
app/components/Sidebar/components/PlaceholderCollections.js
Normal file
21
app/components/Sidebar/components/PlaceholderCollections.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// @flow
|
||||||
|
import * as React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import PlaceholderText from "components/PlaceholderText";
|
||||||
|
|
||||||
|
function PlaceholderCollections() {
|
||||||
|
return (
|
||||||
|
<Wrapper>
|
||||||
|
<PlaceholderText />
|
||||||
|
<PlaceholderText delay={0.2} />
|
||||||
|
<PlaceholderText delay={0.4} />
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
margin: 4px 16px;
|
||||||
|
width: 75%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default PlaceholderCollections;
|
@ -8,7 +8,7 @@ import styled from "styled-components";
|
|||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Empty from "components/Empty";
|
import Empty from "components/Empty";
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import Mask from "components/Mask";
|
import PlaceholderText from "components/PlaceholderText";
|
||||||
|
|
||||||
export type Props = {|
|
export type Props = {|
|
||||||
data: any[],
|
data: any[],
|
||||||
@ -170,7 +170,7 @@ export const Placeholder = ({
|
|||||||
<Row key={row}>
|
<Row key={row}>
|
||||||
{new Array(columns).fill().map((_, col) => (
|
{new Array(columns).fill().map((_, col) => (
|
||||||
<Cell key={col}>
|
<Cell key={col}>
|
||||||
<Mask minWidth={25} maxWidth={75} />
|
<PlaceholderText minWidth={25} maxWidth={75} />
|
||||||
</Cell>
|
</Cell>
|
||||||
))}
|
))}
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -14,7 +14,7 @@ import Trash from "scenes/Trash";
|
|||||||
|
|
||||||
import CenteredContent from "components/CenteredContent";
|
import CenteredContent from "components/CenteredContent";
|
||||||
import Layout from "components/Layout";
|
import Layout from "components/Layout";
|
||||||
import LoadingPlaceholder from "components/LoadingPlaceholder";
|
import PlaceholderDocument from "components/PlaceholderDocument";
|
||||||
import Route from "components/ProfiledRoute";
|
import Route from "components/ProfiledRoute";
|
||||||
import SocketProvider from "components/SocketProvider";
|
import SocketProvider from "components/SocketProvider";
|
||||||
import { matchDocumentSlug as slug } from "utils/routeHelpers";
|
import { matchDocumentSlug as slug } from "utils/routeHelpers";
|
||||||
@ -43,7 +43,7 @@ export default function AuthenticatedRoutes() {
|
|||||||
<React.Suspense
|
<React.Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
<LoadingPlaceholder />
|
<PlaceholderDocument />
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -27,11 +27,11 @@ import Flex from "components/Flex";
|
|||||||
import Heading from "components/Heading";
|
import Heading from "components/Heading";
|
||||||
import HelpText from "components/HelpText";
|
import HelpText from "components/HelpText";
|
||||||
import InputSearchPage from "components/InputSearchPage";
|
import InputSearchPage from "components/InputSearchPage";
|
||||||
|
import PlaceholderList from "components/List/Placeholder";
|
||||||
import LoadingIndicator from "components/LoadingIndicator";
|
import LoadingIndicator from "components/LoadingIndicator";
|
||||||
import { ListPlaceholder } from "components/LoadingPlaceholder";
|
|
||||||
import Mask from "components/Mask";
|
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import PaginatedDocumentList from "components/PaginatedDocumentList";
|
import PaginatedDocumentList from "components/PaginatedDocumentList";
|
||||||
|
import PlaceholderText from "components/PlaceholderText";
|
||||||
import Scene from "components/Scene";
|
import Scene from "components/Scene";
|
||||||
import Subheading from "components/Subheading";
|
import Subheading from "components/Subheading";
|
||||||
import Tab from "components/Tab";
|
import Tab from "components/Tab";
|
||||||
@ -376,9 +376,9 @@ function CollectionScene() {
|
|||||||
) : (
|
) : (
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
<Heading>
|
<Heading>
|
||||||
<Mask height={35} />
|
<PlaceholderText height={35} />
|
||||||
</Heading>
|
</Heading>
|
||||||
<ListPlaceholder count={5} />
|
<PlaceholderList count={5} />
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,10 @@ import Branding from "components/Branding";
|
|||||||
import ErrorBoundary from "components/ErrorBoundary";
|
import ErrorBoundary from "components/ErrorBoundary";
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import LoadingIndicator from "components/LoadingIndicator";
|
import LoadingIndicator from "components/LoadingIndicator";
|
||||||
import LoadingPlaceholder from "components/LoadingPlaceholder";
|
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import Notice from "components/Notice";
|
import Notice from "components/Notice";
|
||||||
import PageTitle from "components/PageTitle";
|
import PageTitle from "components/PageTitle";
|
||||||
|
import PlaceholderDocument from "components/PlaceholderDocument";
|
||||||
import Time from "components/Time";
|
import Time from "components/Time";
|
||||||
import Container from "./Container";
|
import Container from "./Container";
|
||||||
import Contents from "./Contents";
|
import Contents from "./Contents";
|
||||||
@ -410,7 +410,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
)}
|
)}
|
||||||
</Notice>
|
</Notice>
|
||||||
)}
|
)}
|
||||||
<React.Suspense fallback={<LoadingPlaceholder />}>
|
<React.Suspense fallback={<PlaceholderDocument />}>
|
||||||
<Flex auto={!readOnly}>
|
<Flex auto={!readOnly}>
|
||||||
{showContents && <Contents headings={headings} />}
|
{showContents && <Contents headings={headings} />}
|
||||||
<Editor
|
<Editor
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import CenteredContent from "components/CenteredContent";
|
||||||
import LoadingPlaceholder from "components/LoadingPlaceholder";
|
|
||||||
import PageTitle from "components/PageTitle";
|
import PageTitle from "components/PageTitle";
|
||||||
|
import PlaceholderDocument from "components/PlaceholderDocument";
|
||||||
import Container from "./Container";
|
import Container from "./Container";
|
||||||
import type { LocationWithState } from "types";
|
import type { LocationWithState } from "types";
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export default function Loading({ location }: Props) {
|
|||||||
title={location.state ? location.state.title : t("Untitled")}
|
title={location.state ? location.state.title : t("Untitled")}
|
||||||
/>
|
/>
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
<LoadingPlaceholder />
|
<PlaceholderDocument />
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useHistory, useLocation, useRouteMatch } from "react-router-dom";
|
import { useHistory, useLocation, useRouteMatch } from "react-router-dom";
|
||||||
import CenteredContent from "components/CenteredContent";
|
import CenteredContent from "components/CenteredContent";
|
||||||
import Flex from "components/Flex";
|
import Flex from "components/Flex";
|
||||||
import LoadingPlaceholder from "components/LoadingPlaceholder";
|
import PlaceholderDocument from "components/PlaceholderDocument";
|
||||||
import useStores from "hooks/useStores";
|
import useStores from "hooks/useStores";
|
||||||
import { editDocumentUrl } from "utils/routeHelpers";
|
import { editDocumentUrl } from "utils/routeHelpers";
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ function DocumentNew() {
|
|||||||
return (
|
return (
|
||||||
<Flex column auto>
|
<Flex column auto>
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
<LoadingPlaceholder />
|
<PlaceholderDocument />
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user