refactor: single source for writing styles + action labels; add theme module
- src/lib/actions.ts: canonical ACTIONS/ACTION_LABELS/WRITING_STYLES; context-menu styles derived (WRITING_STYLES minus Default). Replaces the three duplicated style arrays in popup, content, and background. - src/lib/theme.ts: canonical palette. Existing hex literals in the entrypoints are swapped wholesale when light/dark theming lands, so the color plumbing is only rewritten once. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { defineBackground } from 'wxt/utils/define-background';
|
import { defineBackground } from 'wxt/utils/define-background';
|
||||||
import nacl from 'tweetnacl';
|
import nacl from 'tweetnacl';
|
||||||
import type { AnalyzePayload, LexAIConfig, LexAIResponse } from '@lib/types';
|
import type { AnalyzePayload, LexAIConfig, LexAIResponse } from '@lib/types';
|
||||||
|
import { ACTIONS, ACTION_LABELS, CONTEXT_MENU_STYLES } from '@lib/actions';
|
||||||
|
|
||||||
// ─── Fetch with timeout ───────────────────────────────────────────────────────
|
// ─── Fetch with timeout ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -431,25 +432,15 @@ export default defineBackground(() => {
|
|||||||
console.log('LexAI background service worker started');
|
console.log('LexAI background service worker started');
|
||||||
|
|
||||||
// ─── Context menus ───────────────────────────────────────────────────────
|
// ─── Context menus ───────────────────────────────────────────────────────
|
||||||
const CONTEXT_ACTIONS = ['fix', 'rephrase', 'shorten', 'expand', 'explain'] as const;
|
|
||||||
const CONTEXT_ACTION_LABELS: Record<string, string> = {
|
|
||||||
fix: 'Fix Grammar',
|
|
||||||
rephrase: 'Rephrase',
|
|
||||||
shorten: 'Shorten',
|
|
||||||
expand: 'Expand',
|
|
||||||
explain: 'Explain',
|
|
||||||
};
|
|
||||||
const CONTEXT_STYLES = ['Formal', 'Casual', 'Academic', 'Creative', 'Concise'];
|
|
||||||
|
|
||||||
chrome.runtime.onInstalled.addListener(() => {
|
chrome.runtime.onInstalled.addListener(() => {
|
||||||
chrome.contextMenus.removeAll(() => {
|
chrome.contextMenus.removeAll(() => {
|
||||||
CONTEXT_ACTIONS.forEach(action => {
|
ACTIONS.forEach(action => {
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: `lexai-${action}`,
|
id: `lexai-${action}`,
|
||||||
title: `⚡ LexAI: ${CONTEXT_ACTION_LABELS[action]}`,
|
title: `⚡ LexAI: ${ACTION_LABELS[action]}`,
|
||||||
contexts: ['selection'],
|
contexts: ['selection'],
|
||||||
});
|
});
|
||||||
CONTEXT_STYLES.forEach(style => {
|
CONTEXT_MENU_STYLES.forEach(style => {
|
||||||
chrome.contextMenus.create({
|
chrome.contextMenus.create({
|
||||||
id: `lexai-${action}-${style.toLowerCase()}`,
|
id: `lexai-${action}-${style.toLowerCase()}`,
|
||||||
parentId: `lexai-${action}`,
|
parentId: `lexai-${action}`,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineContentScript } from 'wxt/utils/define-content-script';
|
import { defineContentScript } from 'wxt/utils/define-content-script';
|
||||||
import { isExtensionValid, safeSendMessage } from '@lib/messaging';
|
import { isExtensionValid, safeSendMessage } from '@lib/messaging';
|
||||||
|
import { WRITING_STYLES } from '@lib/actions';
|
||||||
|
|
||||||
export default defineContentScript({
|
export default defineContentScript({
|
||||||
matches: ['<all_urls>'],
|
matches: ['<all_urls>'],
|
||||||
@@ -744,7 +745,7 @@ export default defineContentScript({
|
|||||||
modal.appendChild(body);
|
modal.appendChild(body);
|
||||||
|
|
||||||
// ─── Style selector row ───────────────────────────────────────────────
|
// ─── Style selector row ───────────────────────────────────────────────
|
||||||
const STYLES = ['Default', 'Formal', 'Casual', 'Academic', 'Creative', 'Concise'];
|
const STYLES = WRITING_STYLES;
|
||||||
|
|
||||||
const styleRow = document.createElement('div');
|
const styleRow = document.createElement('div');
|
||||||
Object.assign(styleRow.style, {
|
Object.assign(styleRow.style, {
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
|
|||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { safeSendMessage, safeStorageGet, safeStorageSet } from '@lib/messaging';
|
import { safeSendMessage, safeStorageGet, safeStorageSet } from '@lib/messaging';
|
||||||
|
|
||||||
// ─── Constants ───────────────────────────────────────────────────────────────
|
import { WRITING_STYLES } from '@lib/actions';
|
||||||
|
|
||||||
const WRITING_STYLES = ['Default', 'Formal', 'Casual', 'Academic', 'Creative', 'Concise'];
|
|
||||||
|
|
||||||
// ─── Types ───────────────────────────────────────────────────────────────────
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
23
src/lib/actions.ts
Normal file
23
src/lib/actions.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Canonical action + writing-style lists shared by the toolbar, popup,
|
||||||
|
// context menus, and result modal. Values must stay in sync with the system
|
||||||
|
// prompts in the background worker.
|
||||||
|
|
||||||
|
// 'fix' is the user-facing id emitted by the context menu and popup; the
|
||||||
|
// background normalizes it to the 'grammar' prompt.
|
||||||
|
export const ACTIONS = ['fix', 'rephrase', 'shorten', 'expand', 'explain'] as const;
|
||||||
|
export type ActionId = (typeof ACTIONS)[number];
|
||||||
|
|
||||||
|
export const ACTION_LABELS: Record<ActionId, string> = {
|
||||||
|
fix: 'Fix Grammar',
|
||||||
|
rephrase: 'Rephrase',
|
||||||
|
shorten: 'Shorten',
|
||||||
|
expand: 'Expand',
|
||||||
|
explain: 'Explain',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Full list, including the 'Default' pseudo-style (= no style modifier).
|
||||||
|
export const WRITING_STYLES = ['Default', 'Formal', 'Casual', 'Academic', 'Creative', 'Concise'] as const;
|
||||||
|
export type WritingStyle = (typeof WRITING_STYLES)[number];
|
||||||
|
|
||||||
|
// Context menus omit 'Default' — the parent action item already covers it.
|
||||||
|
export const CONTEXT_MENU_STYLES = WRITING_STYLES.filter((s) => s !== 'Default');
|
||||||
32
src/lib/theme.ts
Normal file
32
src/lib/theme.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Canonical LexAI palette (Catppuccin Mocha-derived). This is the single
|
||||||
|
// source of truth for UI colors; a light variant can be added here later.
|
||||||
|
//
|
||||||
|
// NOTE: the entrypoints still contain literal hex values from before this
|
||||||
|
// module existed. New/edited styles should reference THEME; the wholesale
|
||||||
|
// swap of existing literals happens together with light/dark theming so the
|
||||||
|
// color plumbing is only rewritten once.
|
||||||
|
|
||||||
|
export const THEME = {
|
||||||
|
// Surfaces
|
||||||
|
base: '#1e1e2e',
|
||||||
|
mantle: '#181825',
|
||||||
|
surface: '#313244',
|
||||||
|
surfaceGradient: 'linear-gradient(135deg, #1e1e2e 0%, #181825 100%)',
|
||||||
|
|
||||||
|
// Text
|
||||||
|
text: '#cdd6f4',
|
||||||
|
subtext: '#a6adc8',
|
||||||
|
muted: '#6c7086',
|
||||||
|
|
||||||
|
// Accents
|
||||||
|
accent: '#89b4fa', // blue — primary actions, links
|
||||||
|
success: '#a6e3a1', // green — success toasts
|
||||||
|
danger: '#f38ba8', // red — errors
|
||||||
|
warning: '#f9e2af', // yellow
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
border: 'rgba(205,214,244,0.12)',
|
||||||
|
borderStrong: 'rgba(205,214,244,0.15)',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type Theme = typeof THEME;
|
||||||
Reference in New Issue
Block a user