chore: Move collection sort control (#1762)
* feat: Move collection sort menu * fix: Improve accessibility * fix: Dedupe outline-icons (temporary until rme is next merged)
This commit is contained in:
@@ -27,9 +27,7 @@ const DropdownMenuItem = ({
|
||||
>
|
||||
{selected !== undefined && (
|
||||
<>
|
||||
<CheckmarkIcon
|
||||
color={selected === false ? "transparent" : undefined}
|
||||
/>
|
||||
{selected ? <CheckmarkIcon /> : <Spacer />}
|
||||
|
||||
</>
|
||||
)}
|
||||
@@ -38,6 +36,11 @@ const DropdownMenuItem = ({
|
||||
);
|
||||
};
|
||||
|
||||
const Spacer = styled.div`
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
`;
|
||||
|
||||
const MenuItem = styled.a`
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { useDrop } from "react-dnd";
|
||||
import styled from "styled-components";
|
||||
import UiStore from "stores/UiStore";
|
||||
import Collection from "models/Collection";
|
||||
import Document from "models/Document";
|
||||
@@ -13,6 +14,7 @@ import EditableTitle from "./EditableTitle";
|
||||
import SidebarLink from "./SidebarLink";
|
||||
import useStores from "hooks/useStores";
|
||||
import CollectionMenu from "menus/CollectionMenu";
|
||||
import CollectionSortMenu from "menus/CollectionSortMenu";
|
||||
|
||||
type Props = {|
|
||||
collection: Collection,
|
||||
@@ -41,6 +43,7 @@ function CollectionLink({
|
||||
const { documents, policies } = useStores();
|
||||
const expanded = collection.id === ui.activeCollectionId;
|
||||
const manualSort = collection.sort.field === "index";
|
||||
const can = policies.abilities(collection.id);
|
||||
|
||||
// Drop to re-parent
|
||||
const [{ isOver, canDrop }, drop] = useDrop({
|
||||
@@ -83,7 +86,7 @@ function CollectionLink({
|
||||
}
|
||||
iconColor={collection.color}
|
||||
expanded={expanded}
|
||||
menuOpen={menuOpen}
|
||||
showActions={menuOpen || expanded}
|
||||
isActiveDrop={isOver && canDrop}
|
||||
label={
|
||||
<EditableTitle
|
||||
@@ -94,12 +97,22 @@ function CollectionLink({
|
||||
}
|
||||
exact={false}
|
||||
menu={
|
||||
<CollectionMenu
|
||||
position="right"
|
||||
collection={collection}
|
||||
onOpen={() => setMenuOpen(true)}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
/>
|
||||
<>
|
||||
{can.update && (
|
||||
<CollectionSortMenuWithMargin
|
||||
position="right"
|
||||
collection={collection}
|
||||
onOpen={() => setMenuOpen(true)}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
/>
|
||||
)}
|
||||
<CollectionMenu
|
||||
position="right"
|
||||
collection={collection}
|
||||
onOpen={() => setMenuOpen(true)}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
></SidebarLink>
|
||||
</DropToImport>
|
||||
@@ -125,4 +138,8 @@ function CollectionLink({
|
||||
);
|
||||
}
|
||||
|
||||
const CollectionSortMenuWithMargin = styled(CollectionSortMenu)`
|
||||
margin-right: 4px;
|
||||
`;
|
||||
|
||||
export default observer(CollectionLink);
|
||||
|
||||
@@ -237,7 +237,7 @@ function DocumentLink({
|
||||
isActiveDrop={isOverReparent && canDropToReparent}
|
||||
depth={depth}
|
||||
exact={false}
|
||||
menuOpen={menuOpen}
|
||||
showActions={menuOpen}
|
||||
menu={
|
||||
document && !isMoving ? (
|
||||
<Fade>
|
||||
|
||||
@@ -14,7 +14,7 @@ type Props = {
|
||||
icon?: React.Node,
|
||||
label?: React.Node,
|
||||
menu?: React.Node,
|
||||
menuOpen?: boolean,
|
||||
showActions?: boolean,
|
||||
iconColor?: string,
|
||||
active?: boolean,
|
||||
isActiveDrop?: boolean,
|
||||
@@ -33,7 +33,7 @@ function SidebarLink({
|
||||
active,
|
||||
isActiveDrop,
|
||||
menu,
|
||||
menuOpen,
|
||||
showActions,
|
||||
theme,
|
||||
exact,
|
||||
href,
|
||||
@@ -73,7 +73,7 @@ function SidebarLink({
|
||||
>
|
||||
{icon && <IconWrapper>{icon}</IconWrapper>}
|
||||
<Label>{label}</Label>
|
||||
{menu && <Action menuOpen={menuOpen}>{menu}</Action>}
|
||||
{menu && <Actions showActions={showActions}>{menu}</Actions>}
|
||||
</StyledNavLink>
|
||||
);
|
||||
}
|
||||
@@ -85,12 +85,14 @@ const IconWrapper = styled.span`
|
||||
height: 24px;
|
||||
`;
|
||||
|
||||
const Action = styled.span`
|
||||
display: ${(props) => (props.menuOpen ? "inline" : "none")};
|
||||
const Actions = styled.span`
|
||||
display: ${(props) => (props.showActions ? "inline-flex" : "none")};
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
color: ${(props) => props.theme.textTertiary};
|
||||
opacity: 0.75;
|
||||
transition: opacity 50ms;
|
||||
|
||||
svg {
|
||||
opacity: 0.75;
|
||||
@@ -133,9 +135,11 @@ const StyledNavLink = styled(NavLink)`
|
||||
background: ${(props) => props.theme.black05};
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> ${Action} {
|
||||
display: inline;
|
||||
&:hover,
|
||||
&:active {
|
||||
> ${Actions} {
|
||||
opacity: 1;
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -26,7 +26,6 @@ type Props = {
|
||||
documents: DocumentsStore,
|
||||
collection: Collection,
|
||||
history: RouterHistory,
|
||||
showSort?: boolean,
|
||||
onOpen?: () => void,
|
||||
onClose?: () => void,
|
||||
t: TFunction,
|
||||
@@ -71,15 +70,6 @@ class CollectionMenu extends React.Component<Props> {
|
||||
}
|
||||
};
|
||||
|
||||
handleChangeSort = (field: string) => {
|
||||
return this.props.collection.save({
|
||||
sort: {
|
||||
field,
|
||||
direction: "asc",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
handleEditCollectionOpen = (ev: SyntheticEvent<>) => {
|
||||
ev.preventDefault();
|
||||
this.showCollectionEdit = true;
|
||||
@@ -122,7 +112,6 @@ class CollectionMenu extends React.Component<Props> {
|
||||
documents,
|
||||
collection,
|
||||
position,
|
||||
showSort,
|
||||
onOpen,
|
||||
onClose,
|
||||
t,
|
||||
@@ -187,28 +176,6 @@ class CollectionMenu extends React.Component<Props> {
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
title: t("Sort in sidebar"),
|
||||
visible: can.update && showSort,
|
||||
hover: true,
|
||||
style: {
|
||||
left: 170,
|
||||
position: "relative",
|
||||
top: -40,
|
||||
},
|
||||
items: [
|
||||
{
|
||||
title: t("Alphabetical"),
|
||||
onClick: () => this.handleChangeSort("title"),
|
||||
selected: collection.sort.field === "title",
|
||||
},
|
||||
{
|
||||
title: t("Manual sort"),
|
||||
onClick: () => this.handleChangeSort("index"),
|
||||
selected: collection.sort.field === "index",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
|
||||
71
app/menus/CollectionSortMenu.js
Normal file
71
app/menus/CollectionSortMenu.js
Normal file
@@ -0,0 +1,71 @@
|
||||
// @flow
|
||||
import { observer } from "mobx-react";
|
||||
import { AlphabeticSortIcon, ManualSortIcon } from "outline-icons";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Collection from "models/Collection";
|
||||
import { DropdownMenu } from "components/DropdownMenu";
|
||||
import DropdownMenuItems from "components/DropdownMenu/DropdownMenuItems";
|
||||
import NudeButton from "components/NudeButton";
|
||||
|
||||
type Props = {
|
||||
position?: "left" | "right" | "center",
|
||||
collection: Collection,
|
||||
onOpen?: () => void,
|
||||
onClose?: () => void,
|
||||
};
|
||||
|
||||
function CollectionSortMenu({
|
||||
collection,
|
||||
position,
|
||||
onOpen,
|
||||
onClose,
|
||||
...rest
|
||||
}: Props) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangeSort = React.useCallback(
|
||||
(field: string) => {
|
||||
return collection.save({
|
||||
sort: {
|
||||
field,
|
||||
direction: "asc",
|
||||
},
|
||||
});
|
||||
},
|
||||
[collection]
|
||||
);
|
||||
|
||||
const alphabeticalSort = collection.sort.field === "title";
|
||||
|
||||
return (
|
||||
<DropdownMenu
|
||||
onOpen={onOpen}
|
||||
onClose={onClose}
|
||||
label={
|
||||
<NudeButton aria-label={t("Sidebar sort")} aria-haspopup="true">
|
||||
{alphabeticalSort ? <AlphabeticSortIcon /> : <ManualSortIcon />}
|
||||
</NudeButton>
|
||||
}
|
||||
position={position}
|
||||
{...rest}
|
||||
>
|
||||
<DropdownMenuItems
|
||||
items={[
|
||||
{
|
||||
title: t("Alphabetical sort"),
|
||||
onClick: () => handleChangeSort("title"),
|
||||
selected: alphabeticalSort,
|
||||
},
|
||||
{
|
||||
title: t("Manual sort"),
|
||||
onClick: () => handleChangeSort("index"),
|
||||
selected: !alphabeticalSort,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
|
||||
export default observer(CollectionSortMenu);
|
||||
@@ -164,7 +164,7 @@ class CollectionScene extends React.Component<Props> {
|
||||
</>
|
||||
)}
|
||||
<Action>
|
||||
<CollectionMenu collection={this.collection} showSort={false} />
|
||||
<CollectionMenu collection={this.collection} />
|
||||
</Action>
|
||||
</Actions>
|
||||
);
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
"mobx-react": "^6.2.5",
|
||||
"natural-sort": "^1.0.0",
|
||||
"nodemailer": "^4.4.0",
|
||||
"outline-icons": "^1.21.0",
|
||||
"outline-icons": "^1.23.0-1",
|
||||
"oy-vey": "^0.10.0",
|
||||
"pg": "^8.5.1",
|
||||
"pg-hstore": "^2.3.3",
|
||||
@@ -205,6 +205,7 @@
|
||||
"webpack-manifest-plugin": "^2.2.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"outline-icons": "1.23.0-1",
|
||||
"dot-prop": "^5.2.0",
|
||||
"js-yaml": "^3.13.1"
|
||||
},
|
||||
|
||||
@@ -8861,10 +8861,10 @@ os-tmpdir@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
|
||||
outline-icons@^1.21.0:
|
||||
version "1.21.0"
|
||||
resolved "https://registry.yarnpkg.com/outline-icons/-/outline-icons-1.21.0.tgz#3e85b7959d0864adbf9a0362ded8fb64bcdcb10f"
|
||||
integrity sha512-EHLv1cpIKzFiGdavSbn5VD3MQRTKpHINFQktm4ZZL42Me2cDj30WMBeMmXjHqOZls0WJNuhCQSYfa7E5ECKR+g==
|
||||
outline-icons@1.23.0-1, outline-icons@^1.21.0, outline-icons@^1.23.0-1:
|
||||
version "1.23.0-1"
|
||||
resolved "https://registry.yarnpkg.com/outline-icons/-/outline-icons-1.23.0-1.tgz#40811d54d55d43751128853ee87babafb0ae42ee"
|
||||
integrity sha512-E/XYmLj/2AS7iR+CtD8IAMIeQPaZoiFLNYGXuKbJIYzjmkmdxWUAIHoWJ8lzBs8rWT4FMmEsv8VOWnmPjH5eig==
|
||||
|
||||
oy-vey@^0.10.0:
|
||||
version "0.10.0"
|
||||
|
||||
Reference in New Issue
Block a user