Animate appearance of pinned documents

This commit is contained in:
Tom Moor
2023-05-17 20:13:09 -04:00
parent aff9413b0f
commit 9b257e9593
3 changed files with 184 additions and 150 deletions

View File

@@ -23,6 +23,7 @@ import breakpoint from "styled-components-breakpoint";
import Pin from "~/models/Pin"; import Pin from "~/models/Pin";
import DocumentCard from "~/components/DocumentCard"; import DocumentCard from "~/components/DocumentCard";
import useStores from "~/hooks/useStores"; import useStores from "~/hooks/useStores";
import { ResizingHeightContainer } from "./ResizingHeightContainer";
type Props = { type Props = {
/** Pins to display */ /** Pins to display */
@@ -98,27 +99,36 @@ function PinnedDocuments({ limit, pins, canUpdate, ...rest }: Props) {
collisionDetection={closestCenter} collisionDetection={closestCenter}
onDragEnd={handleDragEnd} onDragEnd={handleDragEnd}
> >
<SortableContext items={items} strategy={rectSortingStrategy}> <ResizingHeightContainer
<List> config={{
<AnimatePresence initial={false}> transition: {
{items.map((documentId) => { duration: 0.2,
const document = documents.get(documentId); ease: "easeInOut",
const pin = pins.find((pin) => pin.documentId === documentId); },
}}
>
<SortableContext items={items} strategy={rectSortingStrategy}>
<List>
<AnimatePresence initial={false}>
{items.map((documentId) => {
const document = documents.get(documentId);
const pin = pins.find((pin) => pin.documentId === documentId);
return document ? ( return document ? (
<DocumentCard <DocumentCard
key={documentId} key={documentId}
document={document} document={document}
canUpdatePin={canUpdate} canUpdatePin={canUpdate}
isDraggable={items.length > 1} isDraggable={items.length > 1}
pin={pin} pin={pin}
{...rest} {...rest}
/> />
) : null; ) : null;
})} })}
</AnimatePresence> </AnimatePresence>
</List> </List>
</SortableContext> </SortableContext>
</ResizingHeightContainer>
</DndContext> </DndContext>
); );
} }

View File

@@ -12,6 +12,7 @@ import {
} from "react-router-dom"; } from "react-router-dom";
import styled from "styled-components"; import styled from "styled-components";
import breakpoint from "styled-components-breakpoint"; import breakpoint from "styled-components-breakpoint";
import { s } from "@shared/styles";
import Collection from "~/models/Collection"; import Collection from "~/models/Collection";
import Search from "~/scenes/Search"; import Search from "~/scenes/Search";
import Badge from "~/components/Badge"; import Badge from "~/components/Badge";
@@ -178,90 +179,97 @@ function CollectionScene() {
canUpdate={can.update} canUpdate={can.update}
/> />
<Tabs> <Documents>
<Tab to={collectionPath(collection.url)} exact> <Tabs>
{t("Documents")} <Tab to={collectionPath(collection.url)} exact>
</Tab> {t("Documents")}
<Tab to={collectionPath(collection.url, "updated")} exact> </Tab>
{t("Recently updated")} <Tab to={collectionPath(collection.url, "updated")} exact>
</Tab> {t("Recently updated")}
<Tab to={collectionPath(collection.url, "published")} exact> </Tab>
{t("Recently published")} <Tab to={collectionPath(collection.url, "published")} exact>
</Tab> {t("Recently published")}
<Tab to={collectionPath(collection.url, "old")} exact> </Tab>
{t("Least recently updated")} <Tab to={collectionPath(collection.url, "old")} exact>
</Tab> {t("Least recently updated")}
<Tab to={collectionPath(collection.url, "alphabetical")} exact> </Tab>
{t("AZ")} <Tab
</Tab> to={collectionPath(collection.url, "alphabetical")}
</Tabs> exact
<Switch> >
<Route path={collectionPath(collection.url, "alphabetical")}> {t("AZ")}
<PaginatedDocumentList </Tab>
key="alphabetical" </Tabs>
documents={documents.alphabeticalInCollection( <Switch>
collection.id <Route path={collectionPath(collection.url, "alphabetical")}>
)} <PaginatedDocumentList
fetch={documents.fetchAlphabetical} key="alphabetical"
options={{ documents={documents.alphabeticalInCollection(
collectionId: collection.id, collection.id
}} )}
/> fetch={documents.fetchAlphabetical}
</Route> options={{
<Route path={collectionPath(collection.url, "old")}> collectionId: collection.id,
<PaginatedDocumentList }}
key="old" />
documents={documents.leastRecentlyUpdatedInCollection( </Route>
collection.id <Route path={collectionPath(collection.url, "old")}>
)} <PaginatedDocumentList
fetch={documents.fetchLeastRecentlyUpdated} key="old"
options={{ documents={documents.leastRecentlyUpdatedInCollection(
collectionId: collection.id, collection.id
}} )}
/> fetch={documents.fetchLeastRecentlyUpdated}
</Route> options={{
<Route path={collectionPath(collection.url, "recent")}> collectionId: collection.id,
<Redirect to={collectionPath(collection.url, "published")} /> }}
</Route> />
<Route path={collectionPath(collection.url, "published")}> </Route>
<PaginatedDocumentList <Route path={collectionPath(collection.url, "recent")}>
key="published" <Redirect
documents={documents.recentlyPublishedInCollection( to={collectionPath(collection.url, "published")}
collection.id />
)} </Route>
fetch={documents.fetchRecentlyPublished} <Route path={collectionPath(collection.url, "published")}>
options={{ <PaginatedDocumentList
collectionId: collection.id, key="published"
}} documents={documents.recentlyPublishedInCollection(
showPublished collection.id
/> )}
</Route> fetch={documents.fetchRecentlyPublished}
<Route path={collectionPath(collection.url, "updated")}> options={{
<PaginatedDocumentList collectionId: collection.id,
key="updated" }}
documents={documents.recentlyUpdatedInCollection( showPublished
collection.id />
)} </Route>
fetch={documents.fetchRecentlyUpdated} <Route path={collectionPath(collection.url, "updated")}>
options={{ <PaginatedDocumentList
collectionId: collection.id, key="updated"
}} documents={documents.recentlyUpdatedInCollection(
/> collection.id
</Route> )}
<Route path={collectionPath(collection.url)} exact> fetch={documents.fetchRecentlyUpdated}
<PaginatedDocumentList options={{
documents={documents.rootInCollection(collection.id)} collectionId: collection.id,
fetch={documents.fetchPage} }}
options={{ />
collectionId: collection.id, </Route>
parentDocumentId: null, <Route path={collectionPath(collection.url)} exact>
sort: collection.sort.field, <PaginatedDocumentList
direction: collection.sort.direction, documents={documents.rootInCollection(collection.id)}
}} fetch={documents.fetchPage}
showParentDocuments options={{
/> collectionId: collection.id,
</Route> parentDocumentId: null,
</Switch> sort: collection.sort.field,
direction: collection.sort.direction,
}}
showParentDocuments
/>
</Route>
</Switch>
</Documents>
</> </>
)} )}
</CenteredContent> </CenteredContent>
@@ -290,6 +298,11 @@ const StarButton = styled(Star)`
} }
`; `;
const Documents = styled.div`
position: relative;
background: ${s("background")};
`;
const HeadingWithIcon = styled(Heading)<{ $isStarred: boolean }>` const HeadingWithIcon = styled(Heading)<{ $isStarred: boolean }>`
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -3,6 +3,8 @@ import { HomeIcon } from "outline-icons";
import * as React from "react"; import * as React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Switch, Route } from "react-router-dom"; import { Switch, Route } from "react-router-dom";
import styled from "styled-components";
import { s } from "@shared/styles";
import { Action } from "~/components/Actions"; import { Action } from "~/components/Actions";
import Empty from "~/components/Empty"; import Empty from "~/components/Empty";
import Heading from "~/components/Heading"; import Heading from "~/components/Heading";
@@ -48,54 +50,63 @@ function Home() {
{!ui.languagePromptDismissed && <LanguagePrompt />} {!ui.languagePromptDismissed && <LanguagePrompt />}
<Heading>{t("Home")}</Heading> <Heading>{t("Home")}</Heading>
<PinnedDocuments pins={pins.home} canUpdate={canManageTeam} /> <PinnedDocuments pins={pins.home} canUpdate={canManageTeam} />
<Tabs> <Documents>
<Tab to="/home" exact> <Tabs>
{t("Recently viewed")} <Tab to="/home" exact>
</Tab> {t("Recently viewed")}
<Tab to="/home/recent" exact> </Tab>
{t("Recently updated")} <Tab to="/home/recent" exact>
</Tab> {t("Recently updated")}
<Tab to="/home/created">{t("Created by me")}</Tab> </Tab>
</Tabs> <Tab to="/home/created">{t("Created by me")}</Tab>
<Switch> </Tabs>
<Route path="/home/recent"> <Switch>
<PaginatedDocumentList <Route path="/home/recent">
documents={documents.recentlyUpdated} <PaginatedDocumentList
fetch={documents.fetchRecentlyUpdated} documents={documents.recentlyUpdated}
empty={<Empty>{t("Weird, this shouldnt ever be empty")}</Empty>} fetch={documents.fetchRecentlyUpdated}
showCollection empty={<Empty>{t("Weird, this shouldnt ever be empty")}</Empty>}
/> showCollection
</Route> />
<Route path="/home/created"> </Route>
<PaginatedDocumentList <Route path="/home/created">
key="created" <PaginatedDocumentList
documents={documents.createdByUser(userId)} key="created"
fetch={documents.fetchOwned} documents={documents.createdByUser(userId)}
options={{ fetch={documents.fetchOwned}
user: userId, options={{
}} user: userId,
empty={<Empty>{t("You havent created any documents yet")}</Empty>} }}
showCollection empty={
/> <Empty>{t("You havent created any documents yet")}</Empty>
</Route> }
<Route path="/home"> showCollection
<PaginatedDocumentList />
key="recent" </Route>
documents={documents.recentlyViewed} <Route path="/home">
fetch={documents.fetchRecentlyViewed} <PaginatedDocumentList
empty={ key="recent"
<Empty> documents={documents.recentlyViewed}
{t( fetch={documents.fetchRecentlyViewed}
"Documents youve recently viewed will be here for easy access" empty={
)} <Empty>
</Empty> {t(
} "Documents youve recently viewed will be here for easy access"
showCollection )}
/> </Empty>
</Route> }
</Switch> showCollection
/>
</Route>
</Switch>
</Documents>
</Scene> </Scene>
); );
} }
const Documents = styled.div`
position: relative;
background: ${s("background")};
`;
export default observer(Home); export default observer(Home);