diff --git a/app/components/Guide.js b/app/components/Guide.js
new file mode 100644
index 00000000..fea2a7e2
--- /dev/null
+++ b/app/components/Guide.js
@@ -0,0 +1,112 @@
+// @flow
+import { observer } from "mobx-react";
+import * as React from "react";
+import { Dialog, DialogBackdrop, useDialogState } from "reakit/Dialog";
+import styled from "styled-components";
+import Scrollable from "components/Scrollable";
+import usePrevious from "hooks/usePrevious";
+
+type Props = {|
+ children?: React.Node,
+ isOpen: boolean,
+ title?: string,
+ onRequestClose: () => void,
+|};
+
+const Guide = ({
+ children,
+ isOpen,
+ title = "Untitled",
+ onRequestClose,
+ ...rest
+}: Props) => {
+ const dialog = useDialogState({ animated: 250 });
+ const wasOpen = usePrevious(isOpen);
+
+ React.useEffect(() => {
+ if (!wasOpen && isOpen) {
+ dialog.show();
+ }
+ if (wasOpen && !isOpen) {
+ dialog.hide();
+ }
+ }, [dialog, wasOpen, isOpen]);
+
+ return (
+
+ {(props) => (
+
+
+
+ )}
+
+ );
+};
+
+const Header = styled.h1`
+ font-size: 18px;
+ margin-top: 0;
+ margin-bottom: 1em;
+`;
+
+const Backdrop = styled.div`
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: ${(props) => props.theme.backdrop} !important;
+ z-index: ${(props) => props.theme.depths.modalOverlay};
+ transition: opacity 200ms ease-in-out;
+ opacity: 0;
+
+ &[data-enter] {
+ opacity: 1;
+ }
+`;
+
+const Scene = styled.div`
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ margin: 12px;
+ z-index: ${(props) => props.theme.depths.modal};
+ display: flex;
+ justify-content: center;
+ align-items: flex-start;
+ width: 350px;
+ background: ${(props) => props.theme.background};
+ transition: ${(props) => props.theme.backgroundTransition};
+ border-radius: 8px;
+ outline: none;
+ opacity: 0;
+ transform: translateX(16px);
+ transition: transform 250ms ease, opacity 250ms ease;
+
+ &[data-enter] {
+ opacity: 1;
+ transform: translateX(0px);
+ }
+`;
+
+const Content = styled(Scrollable)`
+ width: 100%;
+ padding: 16px;
+`;
+
+export default observer(Guide);
diff --git a/app/components/Input.js b/app/components/Input.js
index f279af69..135c879f 100644
--- a/app/components/Input.js
+++ b/app/components/Input.js
@@ -35,6 +35,10 @@ const RealInput = styled.input`
color: ${(props) => props.theme.placeholder};
}
+ &::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+ }
+
${breakpoint("mobile", "tablet")`
font-size: 16px;
`};
diff --git a/app/components/InputSearch.js b/app/components/InputSearch.js
index c5db89b7..8cc696b5 100644
--- a/app/components/InputSearch.js
+++ b/app/components/InputSearch.js
@@ -20,6 +20,9 @@ type Props = {
label?: string,
labelHidden?: boolean,
collectionId?: string,
+ redirectDisabled?: boolean,
+ maxWidth?: string,
+ onChange: (event: SyntheticInputEvent<>) => mixed,
t: TFunction,
};
@@ -56,7 +59,7 @@ class InputSearch extends React.Component {
};
render() {
- const { t } = this.props;
+ const { t, redirectDisabled, onChange } = this.props;
const { theme, placeholder = `${t("Search")}…` } = this.props;
return (
@@ -64,7 +67,8 @@ class InputSearch extends React.Component {
ref={(ref) => (this.input = ref)}
type="search"
placeholder={placeholder}
- onInput={this.handleSearchInput}
+ onInput={redirectDisabled ? undefined : this.handleSearchInput}
+ onChange={onChange}
icon={
{
}
label={this.props.label}
labelHidden={this.props.labelHidden}
+ maxWidth={this.props.maxWidth}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
margin={0}
@@ -81,7 +86,7 @@ class InputSearch extends React.Component {
}
const InputMaxWidth = styled(Input)`
- max-width: 30vw;
+ max-width: ${(props) => props.maxWidth};
`;
export default withTranslation()(
diff --git a/app/components/Layout.js b/app/components/Layout.js
index 5bda5222..69200995 100644
--- a/app/components/Layout.js
+++ b/app/components/Layout.js
@@ -24,8 +24,8 @@ import KeyboardShortcuts from "scenes/KeyboardShortcuts";
import Button from "components/Button";
import DocumentHistory from "components/DocumentHistory";
import Flex from "components/Flex";
+import Guide from "components/Guide";
import { LoadingIndicatorBar } from "components/LoadingIndicator";
-import Modal from "components/Modal";
import Sidebar from "components/Sidebar";
import SettingsSidebar from "components/Sidebar/Settings";
import SkipNavContent from "components/SkipNavContent";
@@ -161,13 +161,13 @@ class Layout extends React.Component {
/>
-
-
+
);
}
diff --git a/app/menus/AccountMenu.js b/app/menus/AccountMenu.js
index 9085fd6a..2768191b 100644
--- a/app/menus/AccountMenu.js
+++ b/app/menus/AccountMenu.js
@@ -18,7 +18,7 @@ import ContextMenu from "components/ContextMenu";
import MenuItem, { MenuAnchor } from "components/ContextMenu/MenuItem";
import Separator from "components/ContextMenu/Separator";
import Flex from "components/Flex";
-import Modal from "components/Modal";
+import Guide from "components/Guide";
import usePrevious from "hooks/usePrevious";
import useStores from "hooks/useStores";
@@ -90,13 +90,13 @@ function AccountMenu(props: Props) {
return (
<>
- setKeyboardShortcutsOpen(false)}
title={t("Keyboard shortcuts")}
>
-
+
{props.children}