From f33ac5d0de714a248e21f052914fff57fc5d56a9 Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Mon, 7 Jul 2025 12:49:28 +0900 Subject: [PATCH 1/9] Fix: PageRule PageRule was not applied. --- src/components/Popup.tsx | 32 ++++----- src/hooks/useDetectStartup.ts | 20 +++--- src/hooks/useSetting.ts | 118 +++++++++++++++++++--------------- 3 files changed, 91 insertions(+), 79 deletions(-) diff --git a/src/components/Popup.tsx b/src/components/Popup.tsx index 80b2ef19..1bfe7ff9 100644 --- a/src/components/Popup.tsx +++ b/src/components/Popup.tsx @@ -1,14 +1,14 @@ -import { useState, useEffect, createContext, forwardRef } from 'react' -import { Popover, PopoverContent, PopoverAnchor } from '@/components/ui/popover' -import { Menu } from '@/components/menu/Menu' -import { useUserSettings } from '@/hooks/useSetting' -import { useDetectStartup } from '@/hooks/useDetectStartup' -import { useTabCommandReceiver } from '@/hooks/useTabCommandReceiver' -import { hexToHsl, isMac, onHover, cn } from '@/lib/utils' -import { t } from '@/services/i18n' -import { STYLE_VARIABLE, EXIT_DURATION, SIDE, ALIGN } from '@/const' +import { useState, useEffect, createContext, forwardRef } from "react" +import { Popover, PopoverContent, PopoverAnchor } from "@/components/ui/popover" +import { Menu } from "@/components/menu/Menu" +import { useUserSettings } from "@/hooks/useSetting" +import { useDetectStartup } from "@/hooks/useDetectStartup" +import { useTabCommandReceiver } from "@/hooks/useTabCommandReceiver" +import { hexToHsl, isMac, onHover, cn } from "@/lib/utils" +import { t } from "@/services/i18n" +import { STYLE_VARIABLE, EXIT_DURATION, SIDE, ALIGN } from "@/const" -import css from './Popup.module.css' +import css from "./Popup.module.css" export type PopupProps = { positionElm: Element | null @@ -46,7 +46,7 @@ export const Popup = forwardRef( userSettings?.userStyles && userSettings.userStyles.reduce((acc: any, cur: any) => { if (cur.value == null) return acc - if (cur.name === 'background-color' || cur.name === 'border-color') { + if (cur.name === "background-color" || cur.name === "border-color") { const hsl = hexToHsl(cur.value) return { ...acc, @@ -116,7 +116,7 @@ export const Popup = forwardRef( align={align} sideOffset={sideOffset} alignOffset={alignOffset} - className={cn(css.popup, isPreview && 'z-10')} + className={cn(css.popup, isPreview && "z-10")} style={userStyles} onOpenAutoFocus={noFocus} {...onHover(handleOnHover, true)} @@ -136,7 +136,7 @@ export function PreviewDesc(props: PopupProps) { const { userSettings } = useUserSettings() const key = userSettings?.startupMethod?.keyboardParam - const os = isMac() ? 'mac' : 'windows' + const os = isMac() ? "mac" : "windows" const keyLabel = t(`Option_keyboardParam_${key}_${os}`) return ( @@ -145,16 +145,16 @@ export function PreviewDesc(props: PopupProps) { Preview...

{isContextMenu && ( -

{t('previewOnContextMenu')}

+

{t("previewOnContextMenu")}

)} {!visible && isKeyboard && (

- {t('previewOnKeyboard', [keyLabel])} + {t("previewOnKeyboard", [keyLabel])}

)} {!visible && isLeftClickHold && (

- {t('previewOnLeftClickHold', [keyLabel])} + {t("previewOnLeftClickHold", [keyLabel])}

)} diff --git a/src/hooks/useDetectStartup.ts b/src/hooks/useDetectStartup.ts index e696bdf2..88d6378e 100644 --- a/src/hooks/useDetectStartup.ts +++ b/src/hooks/useDetectStartup.ts @@ -1,11 +1,11 @@ -import { useState, useEffect } from 'react' -import type { PopupProps } from '@/components/Popup' -import { useSetting } from '@/hooks/useSetting' -import { useLeftClickHold } from '@/hooks/useLeftClickHold' -import { useSelectContext } from '@/hooks/useSelectContext' -import { POPUP_ENABLED, STARTUP_METHOD, KEYBOARD } from '@/const' -import { Ipc, TabCommand } from '@/services/ipc' -import { isEmpty } from '@/lib/utils' +import { useState, useEffect } from "react" +import type { PopupProps } from "@/components/Popup" +import { useSetting } from "@/hooks/useSetting" +import { useLeftClickHold } from "@/hooks/useLeftClickHold" +import { useSelectContext } from "@/hooks/useSelectContext" +import { POPUP_ENABLED, STARTUP_METHOD, KEYBOARD } from "@/const" +import { Ipc, TabCommand } from "@/services/ipc" +import { isEmpty } from "@/lib/utils" type Props = PopupProps & { isHover?: boolean @@ -85,9 +85,9 @@ export function useKeyboard(_: Props) { setDetectKey((prev) => !prev) } } - window.addEventListener('keyup', handleKeyUp) + window.addEventListener("keyup", handleKeyUp) return () => { - window.removeEventListener('keyup', handleKeyUp) + window.removeEventListener("keyup", handleKeyUp) } }, [method, keyboardParam]) diff --git a/src/hooks/useSetting.ts b/src/hooks/useSetting.ts index 8fceb839..803a0834 100644 --- a/src/hooks/useSetting.ts +++ b/src/hooks/useSetting.ts @@ -1,10 +1,10 @@ -import { useState, useEffect, useCallback, useRef, useMemo } from 'react' -import { enhancedSettings } from '../services/enhancedSettings' +import { useState, useEffect, useCallback, useRef, useMemo } from "react" +import { enhancedSettings } from "../services/enhancedSettings" import { settingsCache, CacheSection, CACHE_SECTIONS, -} from '../services/settingsCache' +} from "../services/settingsCache" import type { SettingsType, @@ -14,9 +14,43 @@ import type { ShortcutSettings, UserSettings, PageRule, -} from '@/types' -import { isEmpty } from '@/lib/utils' -import { INHERIT } from '@/const' +} from "@/types" +import { isEmpty } from "@/lib/utils" +import { INHERIT } from "@/const" + +// Find page rule that matches current URL +function findMatchingPageRule( + settings: Partial, +): PageRule | undefined { + if (!settings || typeof window === "undefined") return undefined + + const rule = (settings.pageRules || []) + .filter((r) => !isEmpty(r.urlPattern)) + .find((rule) => { + try { + const re = new RegExp(rule.urlPattern) + return window.location.href.match(re) != null + } catch { + return false + } + }) + + return rule +} + +// Apply page rule to settings, modifying popupPlacement if needed +function applyPageRuleToSettings( + settings: Partial, + pageRule: PageRule | undefined, +): void { + if ( + pageRule != null && + pageRule.popupPlacement !== INHERIT && + settings.popupPlacement + ) { + settings.popupPlacement = pageRule.popupPlacement + } +} // Type definitions for section-specific hook return values type SectionData = @@ -64,7 +98,7 @@ function useAsyncData( } } catch (err) { if (mountedRef.current) { - setError(err instanceof Error ? err : new Error('Unknown error')) + setError(err instanceof Error ? err : new Error("Unknown error")) } } finally { if (mountedRef.current) { @@ -140,8 +174,23 @@ export function useUserSettings(forceFresh = false) { forceFresh, ) + // Find matching page rule and apply to settings + const pageRule = useMemo(() => { + if (!data) return undefined + return findMatchingPageRule(data) + }, [data]) + + const userSettings = useMemo(() => { + if (!data) return {} as UserSettings + + const settings = { ...data } as UserSettings + applyPageRuleToSettings(settings, pageRule) + return settings + }, [data, pageRule]) + return { - userSettings: (data || {}) as UserSettings, + userSettings, + pageRule, loading, error, refetch, @@ -159,24 +208,16 @@ export function useSetting( settings: Partial pageRule: PageRule | undefined loading: boolean - error: Error | null - refetch: () => Promise - invalidateCache: (sectionsToInvalidate?: CacheSection[]) => void } { const sectionsRef = useRef(sections) - const sectionsKey = useMemo(() => sections.join(','), [sections]) + const sectionsKey = useMemo(() => sections.join(","), [sections]) // Update when sections change useEffect(() => { sectionsRef.current = sections }, [sections]) - const { - data: settings, - loading, - error, - refetch, - } = useAsyncData>( + const { data: settings, loading } = useAsyncData>( () => enhancedSettings.get({ sections: sectionsRef.current, @@ -189,53 +230,26 @@ export function useSetting( })), ) - // Page rule calculation + // Find matching page rule using centralized logic const pageRule = useMemo(() => { - if (!settings || typeof window === 'undefined') return undefined - - const rule = (settings.pageRules || []) - .filter((r) => !isEmpty(r.urlPattern)) - .find((rule) => { - try { - const re = new RegExp(rule.urlPattern) - return window.location.href.match(re) != null - } catch { - return false - } - }) - - if ( - rule != null && - rule.popupPlacement !== INHERIT && - settings.popupPlacement - ) { - settings.popupPlacement = rule.popupPlacement + if (!settings) return undefined + const rule = findMatchingPageRule(settings) + if (rule) { + applyPageRuleToSettings(settings, rule) } - return rule }, [settings]) - const invalidateCache = useCallback( - (sectionsToInvalidate?: CacheSection[]) => { - const targetSections = sectionsToInvalidate || sectionsRef.current - enhancedSettings.invalidateCache(targetSections) - }, - [], - ) - return { settings: settings || {}, pageRule, loading, - error, - refetch, - invalidateCache, } } // Settings hook with image cache applied export function useSettingsWithImageCache() { - const { settings, pageRule, loading } = useSetting([ + const { settings, loading } = useSetting([ CACHE_SECTIONS.COMMANDS, CACHE_SECTIONS.USER_SETTINGS, CACHE_SECTIONS.CACHES, @@ -276,7 +290,5 @@ export function useSettingsWithImageCache() { commands: commandsWithCache, folders: foldersWithCache, iconUrls, - pageRule, - loading, } } From a0e7508362ce6f5119bb5c5739f13e1086aab38d Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Mon, 7 Jul 2025 13:12:43 +0900 Subject: [PATCH 2/9] Update: Improve the display of Storage Usage. --- src/components/option/StorageUsage.tsx | 6 ++--- src/services/storage/storageUsage.ts | 35 +++++++++++--------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/components/option/StorageUsage.tsx b/src/components/option/StorageUsage.tsx index 43b384ea..b46e65af 100644 --- a/src/components/option/StorageUsage.tsx +++ b/src/components/option/StorageUsage.tsx @@ -102,7 +102,7 @@ const StorageUsage: React.FC = () => {

Storage Usage

-

+

Sync Area

@@ -113,7 +113,7 @@ const StorageUsage: React.FC = () => { className="w-full" />
-
+
System: {storageData.sync.systemPercent}%
@@ -135,7 +135,7 @@ const StorageUsage: React.FC = () => {
-

+

Local Area

diff --git a/src/services/storage/storageUsage.ts b/src/services/storage/storageUsage.ts index 524b5ce8..35a43b6e 100644 --- a/src/services/storage/storageUsage.ts +++ b/src/services/storage/storageUsage.ts @@ -118,6 +118,13 @@ const getStorageUsage = async (): Promise => { const localUsed = localTotalBytes const localFree = localLimitTotal - localUsed + const formatPercentage = (value: number): number => { + const percentage = value * 100 + return Number( + percentage >= 10 ? percentage.toFixed(0) : percentage.toFixed(1), + ) + } + return { sync: { total: syncLimitTotal, @@ -126,16 +133,10 @@ const getStorageUsage = async (): Promise => { system: syncSystemBytes, reservedRemain, commands: syncCommandBytes, - systemPercent: Number( - ((syncSystemBytes / syncLimitTotal) * 100).toFixed(0), - ), - reservedPercent: Number( - ((reservedRemain / syncLimitTotal) * 100).toFixed(0), - ), - commandsPercent: Number( - ((syncCommandBytes / syncLimitTotal) * 100).toFixed(0), - ), - freePercent: Number(((syncFree / syncLimitTotal) * 100).toFixed(0)), + systemPercent: formatPercentage(syncSystemBytes / syncLimitTotal), + reservedPercent: formatPercentage(reservedRemain / syncLimitTotal), + commandsPercent: formatPercentage(syncCommandBytes / syncLimitTotal), + freePercent: formatPercentage(syncFree / syncLimitTotal), }, local: { total: localLimitTotal, @@ -144,16 +145,10 @@ const getStorageUsage = async (): Promise => { system: localSystemBytes, backup: localBackupBytes, commands: localCommandBytes, - systemPercent: Number( - ((localSystemBytes / localLimitTotal) * 100).toFixed(0), - ), - backupPercent: Number( - ((localBackupBytes / localLimitTotal) * 100).toFixed(0), - ), - commandsPercent: Number( - ((localCommandBytes / localLimitTotal) * 100).toFixed(0), - ), - freePercent: Number(((localFree / localLimitTotal) * 100).toFixed(0)), + systemPercent: formatPercentage(localSystemBytes / localLimitTotal), + backupPercent: formatPercentage(localBackupBytes / localLimitTotal), + commandsPercent: formatPercentage(localCommandBytes / localLimitTotal), + freePercent: formatPercentage(localFree / localLimitTotal), }, } } catch (error) { From c763a5cd66c78ebb8c551a8626440fb1fa7b99ca Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Mon, 7 Jul 2025 13:22:35 +0900 Subject: [PATCH 3/9] Update: If no backup data exists, disable the restore button. --- src/components/option/Dialog.tsx | 18 ++++++++++++------ src/components/option/ImportExport.tsx | 19 +++++-------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/components/option/Dialog.tsx b/src/components/option/Dialog.tsx index 7d320405..e7475fc1 100644 --- a/src/components/option/Dialog.tsx +++ b/src/components/option/Dialog.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React from "react" import { Dialog as DialogRoot, DialogContent, @@ -7,11 +7,12 @@ import { DialogFooter, DialogTitle, DialogPortal, -} from '@/components/ui/dialog' +} from "@/components/ui/dialog" -import { t } from '@/services/i18n' +import { t } from "@/services/i18n" +import { cn } from "@/lib/utils" -import css from './Dialog.module.css' +import css from "./Dialog.module.css" type Props = { open: boolean @@ -19,6 +20,7 @@ type Props = { title: string description: () => React.ReactNode okText: string + okDisabled?: boolean children?: React.ReactNode } @@ -40,14 +42,18 @@ export function Dialog(props: Props) { {props.children} - diff --git a/src/components/option/ImportExport.tsx b/src/components/option/ImportExport.tsx index 8baac1a7..1899327d 100644 --- a/src/components/option/ImportExport.tsx +++ b/src/components/option/ImportExport.tsx @@ -276,15 +276,6 @@ export function ImportExport() { } const handleRestore = async () => { - const hasAnyBackup = Object.values(backupData).some( - (backup) => backup.status === BACKUP_STATUS.AVAILABLE, - ) - - if (!hasAnyBackup) { - alert(t("Option_RestoreFromBackup_no_data")) - return - } - setRestoreDialog(true) } @@ -379,11 +370,6 @@ export function ImportExport() { onClick={handleRestore} className={css.menuButton} type="button" - disabled={ - !Object.values(backupData).some( - (backup) => backup.status === BACKUP_STATUS.AVAILABLE, - ) - } title={ Object.values(backupData).every( (backup) => backup.status === BACKUP_STATUS.CHECKING, @@ -451,6 +437,11 @@ export function ImportExport() { return {t("Option_RestoreFromBackup_dialog_select")} }} okText={t("Option_RestoreFromBackup_dialog_restore")} + okDisabled={ + !Object.values(backupData).some( + (backup) => backup.status === BACKUP_STATUS.AVAILABLE, + ) + } > {(() => { const availableBackups = Object.entries(backupData).filter( From e2fb1146068c63fdc53dff870b29d207a796cb42 Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Mon, 7 Jul 2025 21:06:13 +0900 Subject: [PATCH 4/9] Update: Prevent auto focus. --- src/components/Popup.tsx | 1 + src/components/menu/Menu.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/src/components/Popup.tsx b/src/components/Popup.tsx index 1bfe7ff9..b0cc1762 100644 --- a/src/components/Popup.tsx +++ b/src/components/Popup.tsx @@ -119,6 +119,7 @@ export const Popup = forwardRef( className={cn(css.popup, isPreview && "z-10")} style={userStyles} onOpenAutoFocus={noFocus} + onCloseAutoFocus={noFocus} {...onHover(handleOnHover, true)} > {!isContextMenu ? : null} diff --git a/src/components/menu/Menu.tsx b/src/components/menu/Menu.tsx index 93a94052..c050b63f 100644 --- a/src/components/menu/Menu.tsx +++ b/src/components/menu/Menu.tsx @@ -186,6 +186,7 @@ const MenuFolder = (props: { sideOffset={isHorizontal ? 2 : -2} className={clsx({ flex: isHorizontal })} ref={contentRef} + onCloseAutoFocus={(e) => e.preventDefault()} {...onHover(props.onHoverContent, folder.id)} > {!isHorizontal ? ( From 9019c2263175aff126c8fc73bc5b6e181b854fa9 Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Mon, 7 Jul 2025 21:53:58 +0900 Subject: [PATCH 5/9] Update: Use Japanese in CLAUDE.md. --- CLAUDE.md | 86 +++++++++++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 266d9572..177595c6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,60 +1,60 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +このファイルは、このリポジトリのコードを扱う際にClaude Code (claude.ai/code)に対するガイダンスを提供します。 -## Development Commands +## 開発コマンド -- `yarn dev` - Start development mode with Vite -- `yarn build` - Build the extension (runs TypeScript compilation + Vite build) -- `yarn lint` - Run ESLint to check code quality -- `yarn zip` - Create a distributable extension zip file from the built dist folder +- `yarn dev` - Viteを使用した開発モードの開始 +- `yarn build` - 拡張機能のビルド(TypeScriptコンパイル + Viteビルドを実行) +- `yarn lint` - ESLintを実行してコード品質をチェック +- `yarn zip` - ビルドされたdistフォルダから配布可能な拡張機能のzipファイルを作成 -## Architecture Overview +## アーキテクチャ概要 -This is a Chrome Extension (Manifest V3) called **Selection Command** that allows users to perform various actions on selected text on web pages. +これは**Selection Command**と呼ばれるChrome拡張機能(Manifest V3)で、ユーザーがWebページ上で選択したテキストに対してさまざまなアクションを実行できます。 -### Key Components +### 主要コンポーネント -**Chrome Extension Structure:** +**Chrome拡張機能の構造:** -- `manifest.json` - Extension manifest defining permissions, content scripts, and background workers -- `src/background_script.ts` - Service worker handling extension lifecycle and background operations -- `src/content_script.tsx` - Main content script injected into web pages -- `src/options_page.tsx` - Extension options/settings page +- `manifest.json` - 権限、コンテンツスクリプト、バックグラウンドワーカーを定義する拡張機能マニフェスト +- `src/background_script.ts` - 拡張機能のライフサイクルとバックグラウンド操作を処理するサービスワーカー +- `src/content_script.tsx` - Webページに注入されるメインのコンテンツスクリプト +- `src/options_page.tsx` - 拡張機能のオプション/設定ページ -**Core Architecture:** +**コアアーキテクチャ:** -- **Actions** (`src/action/`) - Core functionality modules including background operations, popup handling, page actions, and command execution -- **Components** (`src/components/`) - React components organized by feature: - - `menu/` - Context menu and menu item components - - `option/` - Settings and configuration UI - - `pageAction/` - Page automation and recording components - - `result/` - Result display and popup components - - `ui/` - Reusable UI components (uses Radix UI) -- **Services** (`src/services/`) - Business logic and utilities including settings management, storage, analytics, and page action handling -- **Hooks** (`src/hooks/`) - Custom React hooks for state management and Chrome extension APIs +- **Actions** (`src/action/`) - バックグラウンド操作、ポップアップ処理、ページアクション、コマンド実行を含むコア機能モジュール +- **Components** (`src/components/`) - 機能別に整理されたReactコンポーネント: + - `menu/` - コンテキストメニューとメニューアイテムコンポーネント + - `option/` - 設定と構成UI + - `pageAction/` - ページ自動化と記録コンポーネント + - `result/` - 結果表示とポップアップコンポーネント + - `ui/` - 再利用可能なUIコンポーネント(Radix UIを使用) +- **Services** (`src/services/`) - 設定管理、ストレージ、分析、ページアクション処理を含むビジネスロジックとユーティリティ +- **Hooks** (`src/hooks/`) - 状態管理とChrome拡張機能APIのためのカスタムReactフック -**Key Features:** +**主要機能:** -- **Page Actions** - Record and replay browser automation sequences -- **Command Hub** - Web interface for sharing and discovering commands (separate Next.js app in `pages/`) -- **Context Menus** - Right-click actions on selected text -- **Settings Management** - Import/export configurations and user preferences +- **ページアクション** - ブラウザ自動化シーケンスの記録と再生 +- **コマンドハブ** - コマンドの共有と発見のためのWebインターフェース(`pages/`内の独立したNext.jsアプリ) +- **コンテキストメニュー** - 選択したテキストに対する右クリックアクション +- **設定管理** - 構成とユーザー設定のインポート/エクスポート -### Technical Stack +### 技術スタック -- **Frontend**: React 18 with TypeScript -- **Build System**: Vite with `@crxjs/vite-plugin` for Chrome extension development -- **UI Components**: Shadcn -- **Form and Validation**: react-hook-form and zod -- **Styling**: CSS Modules + Tailwind CSS(ver.3) -- **State Management**: React hooks with Chrome extension storage APIs -- **Testing**: ESLint for code quality +- **フロントエンド**: React 18 with TypeScript +- **ビルドシステム**: Vite with `@crxjs/vite-plugin` for Chrome extension development +- **UIコンポーネント**: Shadcn +- **フォームとバリデーション**: react-hook-form and zod +- **スタイリング**: CSS Modules + Tailwind CSS(ver.3) +- **状態管理**: React hooks with Chrome extension storage APIs +- **テスト**: ESLint for code quality -### Project Structure Notes +### プロジェクト構造の注意事項 -- The main extension code is in `src/` -- The command hub website is a separate Next.js application in `pages/` -- Extension supports internationalization with locale files in `public/_locales/` -- Uses Shadow DOM for content script styling isolation -- Implements Robula+ algorithm for robust XPath selector generation (`src/lib/robula-plus/`) +- メインの拡張機能コードは`src/`内にある +- コマンドハブのウェブサイトは`pages/`内の独立したNext.jsアプリケーション +- 拡張機能は`public/_locales/`のロケールファイルによる国際化をサポート +- コンテンツスクリプトのスタイリング分離にShadow DOMを使用 +- 堅牢なXPathセレクター生成のためのRobula+アルゴリズムを実装(`src/lib/robula-plus/`) From 366529e59c90c8d417eab9ea1a72b6a165b7e9d9 Mon Sep 17 00:00:00 2001 From: ujiro99 Date: Mon, 7 Jul 2025 22:25:21 +0900 Subject: [PATCH 6/9] Update: Unified font color. --- src/components/Popup.module.css | 12 +++---- src/components/Popup.tsx | 2 +- src/components/option/HubBanner.module.css | 5 ++- src/components/option/Option.module.css | 25 ++++++-------- src/components/option/Option.tsx | 30 ++++++++-------- src/components/option/StorageUsage.tsx | 8 ++--- .../option/TableOfContents.module.css | 2 +- src/components/ui/form.tsx | 34 +++++++++---------- 8 files changed, 56 insertions(+), 62 deletions(-) diff --git a/src/components/Popup.module.css b/src/components/Popup.module.css index 4aed3138..3fa37371 100644 --- a/src/components/Popup.module.css +++ b/src/components/Popup.module.css @@ -19,31 +19,29 @@ --background: var(--sc-bg-color-h) var(--sc-bg-color-s) var(--sc-bg-color-l); --foreground: 222.2 47.4% 11.2%; --border: var(--sc-bd-color-h) var(--sc-bd-color-s) var(--sc-bd-color-l); - --accent: var(--sc-bg-color-h) var(--sc-bg-color-s) - calc(var(--sc-bg-color-l) - 6%); + --accent: var(--sc-bg-color-h) var(--sc-bg-color-s) calc(var(--sc-bg-color-l) - 6%); --accent-foreground: 224 71% 4%; } -.popup[data-state='open'] { +.popup[data-state="open"] { animation-duration: var(--sc-duration) !important; } -.popup[data-state='closed'] { +.popup[data-state="closed"] { animation-duration: 100ms !important; } .previewContainer { position: relative; - & > div { + &>div { transform: translate(0, 0) !important; } } .previewLabel { - font-family: var(--font-monospace); + @apply font-mono text-gray-800; font-size: 1.2rem; - color: #444; } .previewDescription { diff --git a/src/components/Popup.tsx b/src/components/Popup.tsx index b0cc1762..81bbd4c6 100644 --- a/src/components/Popup.tsx +++ b/src/components/Popup.tsx @@ -116,7 +116,7 @@ export const Popup = forwardRef( align={align} sideOffset={sideOffset} alignOffset={alignOffset} - className={cn(css.popup, isPreview && "z-10")} + className={cn(css.popup, isPreview && "z-10 mt-2")} style={userStyles} onOpenAutoFocus={noFocus} onCloseAutoFocus={noFocus} diff --git a/src/components/option/HubBanner.module.css b/src/components/option/HubBanner.module.css index 7dd2be32..7f1c8da0 100644 --- a/src/components/option/HubBanner.module.css +++ b/src/components/option/HubBanner.module.css @@ -1,7 +1,6 @@ .menuLabel { - font-family: var(--font-monospace); + @apply font-mono text-gray-800; font-size: 1.2rem; - color: #444; } .banner { @@ -16,7 +15,7 @@ } .description { + @apply font-mono text-gray-800; font-size: 0.8rem; - font-family: var(--font-family); padding-left: 4px; } diff --git a/src/components/option/Option.module.css b/src/components/option/Option.module.css index 2db517c5..1bd60ac8 100644 --- a/src/components/option/Option.module.css +++ b/src/components/option/Option.module.css @@ -1,6 +1,6 @@ :root { --font-family: - -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-color: #333; --menu-top: 150px; @@ -22,7 +22,7 @@ margin: 0; } -.titleSpan + .titleSpan { +.titleSpan+.titleSpan { margin-left: 4px; } @@ -45,9 +45,8 @@ } .menuLabel { - @apply font-mono; + @apply font-mono text-gray-800; font-size: 1.2rem; - color: #444; margin-bottom: 16px; } @@ -57,13 +56,13 @@ } .menuButton { - @apply font-mono flex items-center; + @apply flex items-center; + @apply font-mono text-gray-800; border: none; background: none; font-size: 0.9rem; padding: 6px 8px; border-radius: 4px; - color: #444; transition: background-color, ease-out 0.2s, @@ -77,7 +76,7 @@ } .buttonImport { - composes: button from '../Common.module.css'; + composes: button from "../Common.module.css"; width: 100%; padding: 6px 8px; @@ -93,11 +92,9 @@ .bgHatching { background-color: #fff; - background-image: repeating-linear-gradient( - 45deg, - #6b7280, - #6b7280 1px, - transparent 1px, - transparent 4px - ); + background-image: repeating-linear-gradient(45deg, + #6b7280, + #6b7280 1px, + transparent 1px, + transparent 4px); } diff --git a/src/components/option/Option.tsx b/src/components/option/Option.tsx index 72cab0fd..27707edb 100644 --- a/src/components/option/Option.tsx +++ b/src/components/option/Option.tsx @@ -1,17 +1,17 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect } from "react" -import { Settings } from '@/services/settings' -import { capitalize } from '@/lib/utils' -import { APP_ID, VERSION } from '@/const' +import { Settings } from "@/services/settings" +import { capitalize } from "@/lib/utils" +import { APP_ID, VERSION } from "@/const" -import { Popup } from '@/components/Popup' -import { TableOfContents } from '@/components/option/TableOfContents' -import { ImportExport } from '@/components/option/ImportExport' -import { HubBanner } from '@/components/option/HubBanner' -import { SettingForm } from '@/components/option/SettingForm' -import StorageUsage from '@/components/option/StorageUsage' +import { Popup } from "@/components/Popup" +import { TableOfContents } from "@/components/option/TableOfContents" +import { ImportExport } from "@/components/option/ImportExport" +import { HubBanner } from "@/components/option/HubBanner" +import { SettingForm } from "@/components/option/SettingForm" +import StorageUsage from "@/components/option/StorageUsage" -import css from './Option.module.css' +import css from "./Option.module.css" const SCROLL_OFFSET = 80 @@ -49,7 +49,7 @@ export function Option() { elm.getBoundingClientRect().top + window.scrollY - SCROLL_OFFSET window.scrollTo({ top: targetPosition, - behavior: 'smooth', + behavior: "smooth", }) } } @@ -58,7 +58,7 @@ export function Option() {

- {APP_ID.split('-').map((n) => { + {APP_ID.split("-").map((n) => { return ( {capitalize(n)} @@ -90,10 +90,10 @@ export function Option() { ref={setPopupElm} />

-
+
-
+
diff --git a/src/components/option/StorageUsage.tsx b/src/components/option/StorageUsage.tsx index b46e65af..b6bc99ec 100644 --- a/src/components/option/StorageUsage.tsx +++ b/src/components/option/StorageUsage.tsx @@ -101,7 +101,7 @@ const StorageUsage: React.FC = () => { return (

Storage Usage

-
+

Sync Area @@ -112,7 +112,7 @@ const StorageUsage: React.FC = () => { backgroundColor="#f3f4f6" className="w-full" /> -
+
System: {storageData.sync.systemPercent}% @@ -134,7 +134,7 @@ const StorageUsage: React.FC = () => {
-
+

Local Area @@ -145,7 +145,7 @@ const StorageUsage: React.FC = () => { backgroundColor="#f3f4f6" className="w-full" /> -
+
System: {storageData.local.systemPercent}% diff --git a/src/components/option/TableOfContents.module.css b/src/components/option/TableOfContents.module.css index 56b14923..e1faf6d3 100644 --- a/src/components/option/TableOfContents.module.css +++ b/src/components/option/TableOfContents.module.css @@ -1,7 +1,7 @@ .container { + @apply text-gray-800; margin: 0; padding: 0; - color: #444; } .label { diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx index 10602807..ea4e7532 100644 --- a/src/components/ui/form.tsx +++ b/src/components/ui/form.tsx @@ -1,8 +1,8 @@ -'use client' +"use client" -import * as React from 'react' -import * as LabelPrimitive from '@radix-ui/react-label' -import { Slot } from '@radix-ui/react-slot' +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" import { Controller, ControllerProps, @@ -10,10 +10,10 @@ import { FieldValues, FormProvider, useFormContext, -} from 'react-hook-form' +} from "react-hook-form" -import { cn } from '@/lib/utils' -import { Label } from '@/components/ui/label' +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" const Form = FormProvider @@ -49,7 +49,7 @@ const useFormField = () => { const fieldState = getFieldState(fieldContext.name, formState) if (!fieldContext) { - throw new Error('useFormField should be used within ') + throw new Error("useFormField should be used within ") } const { id } = itemContext @@ -84,7 +84,7 @@ const FormItem = React.forwardRef< ) }) -FormItem.displayName = 'FormItem' +FormItem.displayName = "FormItem" const FormLabel = React.forwardRef< React.ElementRef, @@ -96,8 +96,8 @@ const FormLabel = React.forwardRef<