feat: mobile view

This commit is contained in:
boojack 2022-06-19 10:36:58 +08:00
parent 1db7e7745f
commit 819fcf7ffe
22 changed files with 128 additions and 119 deletions

View File

@ -33,6 +33,5 @@
"tailwindcss": "^3.0.18",
"typescript": "^4.3.2",
"vite": "^2.9.0"
},
"license": "MIT"
}
}

View File

@ -150,11 +150,11 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
{linkMemos.length > 0 ? (
<div className="linked-memos-wrapper">
<p className="normal-text">{linkMemos.length} related MEMO</p>
{linkMemos.map((m) => {
const rawtext = parseHtmlToRawText(formatMemoContent(m.content)).replaceAll("\n", " ");
{linkMemos.map((memo, index) => {
const rawtext = parseHtmlToRawText(formatMemoContent(memo.content)).replaceAll("\n", " ");
return (
<div className="linked-memo-container" key={m.id} onClick={() => handleLinkedMemoClick(m)}>
<span className="time-text">{m.dateStr} </span>
<div className="linked-memo-container" key={`${index}-${memo.id}`} onClick={() => handleLinkedMemoClick(memo)}>
<span className="time-text">{memo.dateStr} </span>
{rawtext}
</div>
);
@ -164,11 +164,11 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
{linkedMemos.length > 0 ? (
<div className="linked-memos-wrapper">
<p className="normal-text">{linkedMemos.length} linked MEMO</p>
{linkedMemos.map((m) => {
const rawtext = parseHtmlToRawText(formatMemoContent(m.content)).replaceAll("\n", " ");
{linkedMemos.map((memo, index) => {
const rawtext = parseHtmlToRawText(formatMemoContent(memo.content)).replaceAll("\n", " ");
return (
<div className="linked-memo-container" key={m.id} onClick={() => handleLinkedMemoClick(m)}>
<span className="time-text">{m.dateStr} </span>
<div className="linked-memo-container" key={`${index}-${memo.id}`} onClick={() => handleLinkedMemoClick(memo)}>
<span className="time-text">{memo.dateStr} </span>
{rawtext}
</div>
);

View File

@ -294,7 +294,7 @@ const MemoEditor: React.FC<Props> = () => {
/>
<div
ref={tagSeletorRef}
className={`tag-list ${isTagSeletorShown && tags.length > 0 ? "" : "hidden"}`}
className={`tag-list ${isTagSeletorShown && tags.length > 0 ? "" : "!hidden"}`}
onClick={handleTagSeletorClick}
>
{tags.map((t) => {

View File

@ -1,7 +1,8 @@
import { useCallback, useEffect, useState } from "react";
import { memoService, shortcutService } from "../services";
import { useAppSelector } from "../store";
import SearchBar from "./SearchBar";
import { memoService, shortcutService } from "../services";
import { toggleSiderbar } from "./Sidebar";
import "../less/memos-header.less";
let prevRequestTimestamp = Date.now();
@ -25,7 +26,7 @@ const MemosHeader: React.FC<Props> = () => {
}
}, [query, shortcuts]);
const handleMemoTextClick = useCallback(() => {
const handleTitleTextClick = useCallback(() => {
const now = Date.now();
if (now - prevRequestTimestamp > 10 * 1000) {
prevRequestTimestamp = now;
@ -37,8 +38,13 @@ const MemosHeader: React.FC<Props> = () => {
return (
<div className="section-header-container memos-header-container">
<div className="title-text" onClick={handleMemoTextClick}>
<span className="normal-text">{titleText}</span>
<div className="title-container">
<div className="action-btn" onClick={toggleSiderbar}>
<img src="/icons/menu.svg" className="icon-img" alt="" />
</div>
<span className="title-text" onClick={handleTitleTextClick}>
{titleText}
</span>
</div>
<SearchBar />
</div>

View File

@ -34,27 +34,31 @@ const SettingDialog: React.FC<Props> = (props: Props) => {
</button>
<div className="section-selector-container">
<span className="section-title">Basic</span>
<span
onClick={() => handleSectionSelectorItemClick("my-account")}
className={`section-item ${state.selectedSection === "my-account" ? "selected" : ""}`}
>
My account
</span>
<span
onClick={() => handleSectionSelectorItemClick("preferences")}
className={`section-item ${state.selectedSection === "preferences" ? "selected" : ""}`}
>
Preferences
</span>
<div className="section-items-container">
<span
onClick={() => handleSectionSelectorItemClick("my-account")}
className={`section-item ${state.selectedSection === "my-account" ? "selected" : ""}`}
>
My account
</span>
<span
onClick={() => handleSectionSelectorItemClick("preferences")}
className={`section-item ${state.selectedSection === "preferences" ? "selected" : ""}`}
>
Preferences
</span>
</div>
{user?.role === "OWNER" ? (
<>
<span className="section-title">Admin</span>
<span
onClick={() => handleSectionSelectorItemClick("member")}
className={`section-item ${state.selectedSection === "member" ? "selected" : ""}`}
>
Member
</span>
<div className="section-items-container">
<span
onClick={() => handleSectionSelectorItemClick("member")}
className={`section-item ${state.selectedSection === "member" ? "selected" : ""}`}
>
Member
</span>
</div>
</>
) : null}
</div>

View File

@ -27,6 +27,11 @@ const Sidebar: React.FC<Props> = () => {
return (
<aside className="sidebar-wrapper">
<div className="close-container">
<span className="action-btn" onClick={toggleSiderbar}>
<img src="/icons/close.svg" className="icon-img" alt="" />
</span>
</div>
<UserBanner />
<div className="status-text-container">
<div className="status-text memos-text">
@ -57,4 +62,14 @@ const Sidebar: React.FC<Props> = () => {
);
};
export const toggleSiderbar = () => {
const sidebarEl = document.body.querySelector(".sidebar-wrapper") as HTMLDivElement;
const display = window.getComputedStyle(sidebarEl).display;
if (display === "none") {
sidebarEl.style.display = "flex";
} else {
sidebarEl.style.display = "none";
}
};
export default Sidebar;

View File

@ -1,5 +1,7 @@
import axios from "axios";
axios.defaults.withCredentials = true;
type ResponseObject<T> = {
data: T;
error?: string;

View File

@ -1,6 +1,4 @@
@import "./mixin.less";
#root {
.flex(row, flex-start, flex-start);
@apply w-full h-full;
}

View File

@ -1,31 +1,13 @@
@import "./mixin.less";
* {
@apply m-0 p-0 box-border;
color: @text-black;
-webkit-tap-highlight-color: transparent;
}
body,
html {
@apply w-screen h-screen overflow-hidden text-base;
@apply text-base;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Noto Sans", "Noto Sans CJK SC", "Microsoft YaHei UI", "Microsoft YaHei",
"WenQuanYi Micro Hei", sans-serif, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
}
code {
@apply bg-pink-600 p-1 rounded font-mono;
}
pre {
@apply font-mono;
* {
@apply font-mono;
}
}
label,
button,
img {
@ -57,17 +39,10 @@ li {
}
a {
@apply cursor-pointer text-blue-600 underline underline-offset-2;
&:hover {
@apply opacity-80;
}
@apply cursor-pointer text-blue-600 underline underline-offset-2 hover:opacity-80;
}
.btn {
@apply select-none cursor-pointer text-center;
}
.hidden {
display: none !important;
}

View File

@ -1,15 +1,19 @@
@import "./mixin.less";
@import "./memos-header.less";
#root {
.page-wrapper.home {
@apply relative top-0 w-full h-screen overflow-y-auto;
background-color: #f6f5f4;
}
#page-wrapper {
@apply w-full h-full m-auto grid max-w-4xl mx-auto;
grid-template-columns: min-content 1fr;
> .page-container {
@apply relative w-full min-h-screen mx-auto flex flex-row justify-center items-start;
.memos-wrapper {
@apply w-full h-full overflow-x-hidden flex flex-col justify-start items-start px-4 pr-10;
>.sidebar-wrapper{
@apply flex-shrink-0;
}
> .memos-wrapper {
@apply relative w-full max-w-2xl min-h-full overflow-x-hidden flex flex-col justify-start items-start px-4 sm:pr-6;
}
}
}

View File

@ -1,12 +1,10 @@
@import "./mixin.less";
.dialog-wrapper.memo-card-dialog {
> .dialog-container {
@apply p-0 bg-transparent;
@apply px-4;
> * {
@apply shrink-0;
}
> .dialog-container {
@apply w-full p-0 bg-transparent flex flex-col justify-start items-center;
> .memo-card-container {
.flex(column, flex-start, flex-start);

View File

@ -1,7 +1,8 @@
@import "./mixin.less";
@import "./memos-header.less";
.memo-trash-dialog {
@apply px-4;
> .dialog-container {
@apply w-128 max-w-full mb-8;

View File

@ -5,20 +5,22 @@
.flex(row, space-between, center);
@apply w-full h-10 flex-nowrap mt-4 mb-2 shrink-0;
> .title-text {
.flex(row, flex-start, center);
@apply font-bold text-lg leading-10 mr-2 text-ellipsis shrink-0 cursor-pointer overflow-hidden;
color: @text-black;
> .title-container {
@apply flex flex-row justify-start items-center mr-2 shrink-0 overflow-hidden;
> .action-btn {
.flex(row, center, center);
@apply w-6 h-6 mr-1 shrink-0;
@apply flex sm:hidden flex-row justify-center items-center w-6 h-6 mr-1 shrink-0;
background-color: unset;
> .icon-img {
@apply w-4 h-auto;
@apply w-5 h-auto;
}
}
> .title-text {
@apply font-bold text-lg leading-10 mr-2 text-ellipsis shrink-0 cursor-pointer overflow-hidden;
color: @text-black;
}
}
> .btns-container {

View File

@ -2,22 +2,14 @@
.menu-btns-popup {
.flex(column, flex-start, flex-start);
@apply absolute mt-1 ml-24 p-1 w-44 rounded-lg z-10 shadow bg-white;
&:hover {
display: flex;
}
@apply absolute right-0 top-0 mt-1 p-1 w-36 rounded-lg z-10 shadow bg-white;
> .btn {
.flex(row, flex-start, center);
@apply w-full py-2 px-3 text-base rounded text-left;
@apply w-full py-2 px-3 text-base rounded text-left hover:bg-gray-100;
> .icon {
@apply block w-6 text-center mr-2 text-base;
}
&:hover {
background-color: @bg-whitegray;
}
}
}

View File

@ -15,10 +15,6 @@
@bg-light-blue: #eef3fe;
@bg-paper-yellow: #fbf4de;
.mono-font-family {
font-family: SFMono-Regular, Menlo, Consolas, "PT Mono", "Liberation Mono", Courier, monospace;
}
.hide-scroll-bar {
.pretty-scroll-bar(0, 0);

View File

@ -23,8 +23,7 @@
}
> .quickly-action-wrapper {
@apply hidden absolute top-9 -right-2 p-2 w-80;
z-index: 2;
@apply hidden absolute top-9 -right-2 p-2 w-80 z-10;
> .quickly-action-container {
.flex(column, flex-start, flex-start);

View File

@ -1,13 +1,14 @@
@import "./mixin.less";
@import "./memos-header.less";
.setting-dialog {
@apply px-4;
> .dialog-container {
@apply w-176 max-w-full mb-8 p-0;
> .dialog-content-container {
.flex(column, flex-start, flex-start);
@apply relative w-full overflow-y-scroll p-0 flex flex-row justify-start items-start;
@apply relative w-full overflow-y-scroll p-0 flex flex-col sm:flex-row justify-start items-start;
.hide-scroll-bar();
> .close-btn {
@ -20,23 +21,28 @@
}
> .section-selector-container {
@apply w-40 h-full shrink-0 rounded-l-lg p-4 border-r bg-gray-100 flex flex-col justify-start items-start;
@apply w-full sm:w-40 h-auto sm:h-full shrink-0 rounded-t-lg sm:rounded-l-lg p-4 border-r bg-gray-100 flex flex-col justify-start items-start;
> .section-title {
@apply text-sm mt-4 first:mt-3 mb-1 font-mono text-gray-400;
}
> .section-item {
@apply text-base left-6 mt-2 text-gray-700 cursor-pointer hover:opacity-80;
>.section-items-container{
@apply w-full h-auto flex flex-row sm:flex-col justify-start items-start;
&.selected {
@apply font-bold hover:opacity-100;
> .section-item {
@apply text-base mr-2 sm:mr-0 mt-2 text-gray-700 cursor-pointer hover:opacity-80;
&.selected {
@apply font-bold hover:opacity-100;
}
}
}
}
> .section-content-container {
@apply w-auto p-4 px-6 grow flex flex-col justify-start items-start h-128 overflow-y-scroll;
@apply w-full sm:w-auto p-4 px-6 grow flex flex-col justify-start items-start h-128 overflow-y-scroll;
> .section-container {
.flex(column, flex-start, flex-start);
@ -47,8 +53,7 @@
}
> .form-label {
.flex(row, flex-start, center);
@apply w-full mb-2;
@apply flex flex-row justify-start items-center w-full mb-2;
> .normal-text {
@apply shrink-0 select-text;

View File

@ -9,12 +9,14 @@
}
&.username-label {
@apply w-full flex-wrap;
> input {
@apply grow-0 shadow-inner w-auto px-2 py-1 text-base border rounded leading-6 bg-transparent focus:border-black;
@apply grow-0 shadow-inner w-auto px-2 py-1 mr-2 text-base border rounded leading-6 bg-transparent focus:border-black;
}
> .btns-container {
@apply ml-2 shrink-0 flex flex-row justify-start items-center;
@apply mr-2 shrink-0 flex flex-row justify-start items-center;
> .btn {
@apply text-sm shadow px-4 py-1 leading-6 rounded border hover:opacity-80 bg-gray-50;

View File

@ -1,10 +1,21 @@
@import "./mixin.less";
.sidebar-wrapper {
.flex(column, flex-start, flex-start);
@apply w-64 h-full py-4 pl-2 overflow-x-hidden overflow-y-auto;
@apply fixed sm:sticky top-0 left-0 hidden sm:!flex flex-col justify-start items-start w-64 h-screen py-4 pl-2 z-10 bg-white sm:bg-transparent shadow-2xl sm:shadow-none overflow-x-hidden overflow-y-auto transition-all;
.hide-scroll-bar();
> .close-container {
@apply w-full pr-6 my-2 flex sm:hidden flex-row justify-end items-center;
> .action-btn {
@apply p-1 bg-gray-100 rounded shadow;
> .icon-img {
@apply w-4 h-auto;
}
}
}
> .action-btns-container {
@apply w-full px-2 my-2 flex flex-col justify-start items-start shrink-0;

View File

@ -2,7 +2,7 @@
.page-wrapper.signin {
.flex(row, center, center);
@apply w-full h-full bg-white;
@apply w-full min-h-screen bg-white;
> .page-container {
@apply w-80 max-w-full py-4 -mt-16;

View File

@ -32,9 +32,9 @@ function Home() {
}, []);
return (
<>
<section className="page-wrapper home">
{loadingState.isLoading ? null : (
<section id="page-wrapper">
<div className="page-container">
<Sidebar />
<main className="memos-wrapper">
<MemosHeader />
@ -42,9 +42,9 @@ function Home() {
<MemoFilter />
<MemoList />
</main>
</section>
</div>
)}
</>
</section>
);
}

View File

@ -16,5 +16,5 @@
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["./src", "./public"]
"include": ["./src"]
}