From 8460d894e1d737101fdbfa6605f8d1498fab7b03 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Thu, 27 Nov 2025 16:24:30 +0100 Subject: [PATCH] feat(automationPlugin): improve button styles and add copyTo option for plugin output --- .../plugin-dev/automation-plugin/package.json | 1 + .../automation-plugin/src/app/App.css | 80 ++++++++++++------- .../src/app/components/ActionDialog.tsx | 2 +- .../src/app/components/ConditionDialog.tsx | 2 +- .../src/app/components/RuleEditor.tsx | 18 ++--- .../src/app/components/RuleList.tsx | 6 +- .../automation-plugin/vite.config.ts | 7 +- packages/vite-plugin/src/index.ts | 49 +++++++++--- 8 files changed, 108 insertions(+), 57 deletions(-) diff --git a/packages/plugin-dev/automation-plugin/package.json b/packages/plugin-dev/automation-plugin/package.json index de1fd7554d..d0a7a0cab5 100644 --- a/packages/plugin-dev/automation-plugin/package.json +++ b/packages/plugin-dev/automation-plugin/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "vite build", + "watch": "vite build --watch", "preview": "vite preview", "test": "vitest", "lint": "eslint .", diff --git a/packages/plugin-dev/automation-plugin/src/app/App.css b/packages/plugin-dev/automation-plugin/src/app/App.css index 8bf8dd38ae..345a08da8d 100644 --- a/packages/plugin-dev/automation-plugin/src/app/App.css +++ b/packages/plugin-dev/automation-plugin/src/app/App.css @@ -13,6 +13,9 @@ --pico-primary-focus: var(--c-accent); --pico-card-background-color: var(--card-bg); --pico-border-color: var(--divider-color); + /* Tighten default control padding to avoid oversized buttons */ + --pico-form-element-spacing-vertical: 0.35rem; + --pico-form-element-spacing-horizontal: 0.75rem; /* Additional Pico overrides for better integration */ --pico-form-element-background-color: var(--bg-darker); @@ -20,6 +23,46 @@ --pico-form-element-color: var(--text-color); } +/* Force primary button color */ +button:not(.outline):not(.secondary):not(.contrast):not(.close-btn) { + background-color: var(--c-primary); + border-color: var(--c-primary); + color: #fff; +} + +/* Primary outline buttons */ +button.outline:not(.secondary):not(.contrast), +button.outline.secondary { + background-color: transparent !important; + color: var(--c-primary) !important; + border-color: var(--c-primary) !important; +} +button.outline:not(.secondary):not(.contrast):hover, +button.outline.secondary:hover { + background-color: var(--c-primary) !important; + color: #fff !important; +} + +/* Make secondary outlines look like primary outlines for cancel buttons */ +/* Force warn color for delete buttons (using contrast class) */ +button.contrast { + background-color: var(--c-warn); + border-color: var(--c-warn); + color: #fff; +} +button.outline.contrast { + background-color: transparent !important; + border-color: var(--c-warn) !important; + color: var(--c-warn) !important; +} + +/* Checkboxes */ +input[type='checkbox']:checked { + background-color: var(--c-primary); + border-color: var(--c-primary); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); +} + body { margin: 0; padding: 0; @@ -37,15 +80,14 @@ main.container { max-width: 960px !important; } -/* Small button utility */ -button.btn-sm, -a[role='button'].btn-sm, -input[type='submit'].btn-sm, -input[type='button'].btn-sm { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - width: auto; - margin-bottom: 0; +/* Reduce button height globally */ +button, +[role='button'], +input[type='submit'], +input[type='button'], +input[type='reset'] { + min-height: auto; + padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal); } /* Dialog styles */ @@ -60,26 +102,6 @@ dialog article header { align-items: center; } -/* Icon-only close button */ -button.close-btn { - background: transparent; - border: none; - padding: 0; - margin: 0; - width: auto; - color: var(--text-color); - opacity: 0.7; - cursor: pointer; - font-size: 1.5rem; - line-height: 1; -} - -button.close-btn:hover { - background: transparent; - opacity: 1; - color: var(--primary-color); -} - /* Table styles */ table { width: 100%; diff --git a/packages/plugin-dev/automation-plugin/src/app/components/ActionDialog.tsx b/packages/plugin-dev/automation-plugin/src/app/components/ActionDialog.tsx index f9e36d71d0..e3b282f101 100644 --- a/packages/plugin-dev/automation-plugin/src/app/components/ActionDialog.tsx +++ b/packages/plugin-dev/automation-plugin/src/app/components/ActionDialog.tsx @@ -31,7 +31,7 @@ export function ActionDialog(props: ActionDialogProps) { title={props.initialAction ? 'Edit Action' : 'Add Action'} footer={
- diff --git a/packages/plugin-dev/automation-plugin/src/app/components/ConditionDialog.tsx b/packages/plugin-dev/automation-plugin/src/app/components/ConditionDialog.tsx index bf52c5a771..34330b7c40 100644 --- a/packages/plugin-dev/automation-plugin/src/app/components/ConditionDialog.tsx +++ b/packages/plugin-dev/automation-plugin/src/app/components/ConditionDialog.tsx @@ -33,7 +33,7 @@ export function ConditionDialog(props: ConditionDialogProps) { title={props.initialCondition ? 'Edit Condition' : 'Add Condition'} footer={
- diff --git a/packages/plugin-dev/automation-plugin/src/app/components/RuleEditor.tsx b/packages/plugin-dev/automation-plugin/src/app/components/RuleEditor.tsx index 1a98f3a579..64e6f02124 100644 --- a/packages/plugin-dev/automation-plugin/src/app/components/RuleEditor.tsx +++ b/packages/plugin-dev/automation-plugin/src/app/components/RuleEditor.tsx @@ -111,7 +111,7 @@ export function RuleEditor(props: RuleEditorProps) {
- @@ -221,7 +217,6 @@ export function RuleEditor(props: RuleEditorProps) {
- diff --git a/packages/plugin-dev/automation-plugin/src/app/components/RuleList.tsx b/packages/plugin-dev/automation-plugin/src/app/components/RuleList.tsx index 6895ec81b3..e4f5e7dde4 100644 --- a/packages/plugin-dev/automation-plugin/src/app/components/RuleList.tsx +++ b/packages/plugin-dev/automation-plugin/src/app/components/RuleList.tsx @@ -17,7 +17,7 @@ export function RuleList(props: RuleListProps) {

Automation Rules

-
@@ -60,13 +60,13 @@ export function RuleList(props: RuleListProps) { - diff --git a/packages/plugin-dev/automation-plugin/vite.config.ts b/packages/plugin-dev/automation-plugin/vite.config.ts index 16a89ab074..a3dec516e4 100644 --- a/packages/plugin-dev/automation-plugin/vite.config.ts +++ b/packages/plugin-dev/automation-plugin/vite.config.ts @@ -4,7 +4,12 @@ import solidPlugin from 'vite-plugin-solid'; import { superProductivityPlugin } from '@super-productivity/vite-plugin'; export default defineConfig({ - plugins: [solidPlugin(), superProductivityPlugin()], + plugins: [ + solidPlugin(), + superProductivityPlugin({ + copyTo: '../../../src/assets/bundled-plugins/automation-plugin', + }), + ], test: { environment: 'jsdom', globals: true, diff --git a/packages/vite-plugin/src/index.ts b/packages/vite-plugin/src/index.ts index 8e7a49ac1d..c84c6a9ac6 100644 --- a/packages/vite-plugin/src/index.ts +++ b/packages/vite-plugin/src/index.ts @@ -1,4 +1,4 @@ -import { Plugin, UserConfig } from 'vite'; +import { Plugin } from 'vite'; import path from 'path'; import fs from 'fs'; @@ -9,18 +9,21 @@ export interface SuperProductivityPluginOptions { * Default: true */ inlineAssets?: boolean; + /** + * Directory to copy the build output to. + * Useful for watching and auto-updating the plugin in the main app. + */ + copyTo?: string; } -export function superProductivityPlugin( +export const superProductivityPlugin = ( options: SuperProductivityPluginOptions = {}, -): Plugin { - const { inlineAssets = true } = options; - let config: UserConfig; +): Plugin => { + const { inlineAssets = true, copyTo } = options; return { name: 'super-productivity-plugin', - config(userConfig) { - config = userConfig; + config: () => { return { build: { outDir: 'dist', @@ -46,7 +49,7 @@ export function superProductivityPlugin( }, closeBundle: { order: 'post', - handler() { + handler: () => { const distDir = path.resolve(process.cwd(), 'dist'); // 1. Copy manifest.json @@ -115,7 +118,35 @@ export function superProductivityPlugin( fs.writeFileSync(htmlPath, html); console.log('✅ Assets inlined successfully'); } + + // 4. Copy to destination if specified + if (copyTo) { + const destDir = path.resolve(process.cwd(), copyTo); + if (!fs.existsSync(destDir)) { + fs.mkdirSync(destDir, { recursive: true }); + } + + // Recursive copy function + const copyRecursive = (src: string, dest: string): void => { + const entries = fs.readdirSync(src, { withFileTypes: true }); + if (!fs.existsSync(dest)) fs.mkdirSync(dest); + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + copyRecursive(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); + } + } + }; + + copyRecursive(distDir, destDir); + console.log(`✅ Copied build to ${copyTo}`); + } }, }, }; -} +};