diff --git a/assets/global.less b/assets/global.less index e58d036..b0e5c60 100644 --- a/assets/global.less +++ b/assets/global.less @@ -17,9 +17,11 @@ h2 { button { padding: 0; + width: 100%; border: none; + padding: .75em; cursor: pointer; - background-color: transparent; + border-radius: .5em; } img { @@ -46,10 +48,6 @@ button, input, textarea { font: inherit; } -form button { - background-color: #eee; -} - textarea { resize: vertical; } diff --git a/popup/read.tsx b/components/biz/read/index.tsx similarity index 86% rename from popup/read.tsx rename to components/biz/read/index.tsx index 2349872..70d42d5 100644 --- a/popup/read.tsx +++ b/components/biz/read/index.tsx @@ -1,14 +1,10 @@ -import { useEffect } from "react"; +import { useEffect, useRef } from "react"; import { sendToBackground } from "@plasmohq/messaging"; import useForm from "~hooks/useForm"; import Tab from "~components/ui/tab"; import Form from "~components/ui/form"; import { add } from "~components/ui/message/utils"; -interface ReadProps { - onBack: () => void; -} - interface FormValue { title: string; link: string; @@ -46,10 +42,18 @@ const submitForm = (body: FormValue) => { content: res.msg, }); } + }).catch((e) => { + if (e instanceof Error) { + add({ + content: e.message, + }); + } }); } -function Read({ onBack }: ReadProps) { +function Read() { + const formRef = useRef(); + const { bindInput, setValues, onSubmit } = useForm({ initialValues: { tags: "", @@ -68,9 +72,8 @@ function Read({ onBack }: ReadProps) { return ( - -
+
@@ -97,9 +100,11 @@ function Read({ onBack }: ReadProps) {
-
+ + +
); } diff --git a/popup/bili.tsx b/components/biz/toy/index.tsx similarity index 88% rename from popup/bili.tsx rename to components/biz/toy/index.tsx index 9eccce8..244cc99 100644 --- a/popup/bili.tsx +++ b/components/biz/toy/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState, useEffect, useRef } from "react"; import { sendToBackground } from "@plasmohq/messaging"; import useForm from "~hooks/useForm"; import Tab from "~components/ui/tab"; @@ -6,11 +6,7 @@ import Form from "~components/ui/form"; import { add } from "~components/ui/message/utils"; import Placeholder from "~components/ui/placeholder"; -import styles from "./bili.module.less"; - -interface ReadProps { - onBack: () => void; -} +import styles from "./toy.module.less"; interface FormValue { name: string; @@ -36,7 +32,9 @@ const getInfo = async () => { } } -function Toy({ onBack }: ReadProps) { +function Toy() { + const formRef = useRef(); + const { bindInput, setValues, onSubmit } = useForm({ initialValues: { type: 3, @@ -89,10 +87,9 @@ function Toy({ onBack }: ReadProps) { }, []); return ( - - - - + + +
@@ -134,12 +131,13 @@ function Toy({ onBack }: ReadProps) {
- - - - - + + + + + + ); } diff --git a/popup/bili.module.less b/components/biz/toy/toy.module.less similarity index 70% rename from popup/bili.module.less rename to components/biz/toy/toy.module.less index eef7058..e3f516f 100644 --- a/popup/bili.module.less +++ b/components/biz/toy/toy.module.less @@ -1,10 +1,10 @@ .bili { - gap: 1em; - width: 600px; - display: flex; - .image { - flex: 0 0 40%; + margin-bottom: 2em; + + img { + border-radius: .5em; + } } .selector { @@ -17,6 +17,7 @@ width: 3em; height: 3em; cursor: pointer; + border-radius: .5em; border: 1px solid #eee; } } diff --git a/components/ui/form/index.tsx b/components/ui/form/index.tsx index 209766c..46d8fad 100644 --- a/components/ui/form/index.tsx +++ b/components/ui/form/index.tsx @@ -1,4 +1,4 @@ -import type { FormHTMLAttributes } from "react"; +import { useImperativeHandle, type FormHTMLAttributes, useRef, forwardRef, type Ref } from "react"; import { clsn } from "~utils"; import styles from "./form.module.less"; @@ -6,12 +6,18 @@ interface FormProps extends FormHTMLAttributes { } -function Form({ children, className, ...props }: FormProps) { +function Form({ children, className, ...props }: FormProps, ref: Ref) { + const formRef = useRef(); + + useImperativeHandle(ref, () => { + return formRef.current; + }, []); + return ( -
+ {children}
); } -export default Form; +export default forwardRef(Form); diff --git a/components/ui/tab/index.tsx b/components/ui/tab/index.tsx index 54b8333..ddfb988 100644 --- a/components/ui/tab/index.tsx +++ b/components/ui/tab/index.tsx @@ -35,4 +35,12 @@ Tab.Body = function Body({ children }: PropsWithChildren) { ); } +Tab.Footer = function Footer({ children }: PropsWithChildren) { + return ( +
+ {children} +
+ ); +} + export default Tab; diff --git a/components/ui/tab/tab.module.less b/components/ui/tab/tab.module.less index f9b194c..b3b7e8c 100644 --- a/components/ui/tab/tab.module.less +++ b/components/ui/tab/tab.module.less @@ -1,7 +1,14 @@ .tab { + .header, .footer { + left: 0; + right: 0; + padding: .75em 1em; + position: sticky; + background-color: #fff; + } + .header { - padding: .75em; - position: relative; + top: 0; text-align: center; border-bottom: 1px solid #eee; @@ -27,4 +34,12 @@ .body { padding: 1em; } + + .footer { + bottom: 0; + border-top: 1px solid #eee; + + display: flex; + align-items: flex-end; + } } diff --git a/popup/index.tsx b/popup/index.tsx index fc51abc..6f08b5c 100644 --- a/popup/index.tsx +++ b/popup/index.tsx @@ -1,7 +1,5 @@ import { useState } from "react"; import Menu from "./menu"; -import Read from "./read"; -import Toy from "./bili"; import Message from "~components/ui/message"; import { clsn } from "~utils"; import "assets/global.less"; @@ -17,6 +15,7 @@ function IndexPopup() { const onClickMenu = (value: string) => { if (value === "options") { chrome.runtime.openOptionsPage(); + return; } else if (value === "home") { @@ -29,24 +28,20 @@ function IndexPopup() { return; } - setTab(value); - } + chrome.tabs.query({ active: true, lastFocusedWindow: true }).then((tabs) => { + const { id, windowId } = tabs[0]; - const renderBody = () => { - if (tab === "read") { - return ; - } - if (tab === "toy") { - return ; - } + chrome.sidePanel.setOptions({ path: `sidepanel.html?type=${value}` }) + chrome.sidePanel.open({ tabId: id, windowId }); - return ; + window.close(); + }); } return ( <>
- {renderBody()} +
diff --git a/sidepanel/index.tsx b/sidepanel/index.tsx new file mode 100644 index 0000000..12ab15d --- /dev/null +++ b/sidepanel/index.tsx @@ -0,0 +1,39 @@ +import { useState } from "react"; +import Read from "~components/biz/read"; +import Toy from "~components/biz/toy"; +import Message from "~components/ui/message"; +import { clsn } from "~utils"; + +import "~assets/global.less"; +import styles from "./sidepanel.module.less"; + +const initialType = new URLSearchParams(location.search).get("type") || "read"; + +const tabItems = [ + { title: "在读", value: "read" }, + { title: "手办", value: "toy" }, + { title: "语录", value: "say" }, +]; + +function SidePanel() { + const [type, setType] = useState(initialType); + + return ( +
+ + {type === "read" && } + {type === "toy" && } + +
+ ); +} + +export default SidePanel; diff --git a/sidepanel/sidepanel.module.less b/sidepanel/sidepanel.module.less new file mode 100644 index 0000000..0f8b413 --- /dev/null +++ b/sidepanel/sidepanel.module.less @@ -0,0 +1,33 @@ +.root { + color: #333; + font-size: 14px; + + .nav { + display: flex; + text-align: center; + border-bottom: 1px solid #eee; + + a { + flex: 1; + cursor: pointer; + position: relative; + padding: .75em 1em; + + &.active { + color: #28b9be; + + &::after { + margin-top: .25em; + position: absolute; + left: calc(50% - .25em); + + content: ""; + width: .75em; + height: 2px; + display: block; + background-color: currentColor; + } + } + } + } +}