mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 02:36:05 +00:00
5.1 KiB
5.1 KiB
Plan: Plugin UI Consistency via CSS Library + Reactive Theme
Goal
Make iframe plugin UI more consistent with the main app by:
- Providing a shared CSS component library
- Adding reactive theme updates when user switches dark/light mode
Approach
CSS-only component library (minimal: 5-7 components) + reactive theme hook
Part 1: Reactive Theme Updates
Changes Required
1. Add THEME_CHANGE hook
- File:
src/app/plugins/plugin-api.model.ts - Add
THEME_CHANGE = 'themeChange'toPluginHooksenum
2. Emit theme change events to plugins
- File:
src/app/plugins/plugin-bridge.service.ts - Subscribe to
GlobalThemeService.darkMode()signal - When theme changes, call all registered
themeChangehook handlers - Also post
THEME_UPDATEmessage to all active plugin iframes with new CSS variables
3. Add message handler in iframe for CSS variable updates
- File:
src/app/plugins/util/plugin-iframe.util.ts - Add new message type
THEME_UPDATEto handle dynamic CSS variable injection - In
createPluginApiScript(), add listener that updates:rootCSS variables
4. Update plugin API types
- File:
packages/plugin-api/src/index.ts - Add
THEME_UPDATEtoPluginIframeMessageType - Export
THEME_CHANGEhook type
Part 2: CSS Component Library
Components to Include (Minimal Set)
- Buttons -
.btn,.btn-primary,.btn-outline,.btn-icon - Cards -
.card,.card-header,.card-content - Inputs -
.input,.textarea,.select - Checkbox/Toggle -
.checkbox,.toggle - Text utilities -
.text-muted,.text-primary,.text-sm - Layout helpers -
.flex,.gap,.stack(vertical stack) - Lists -
.list,.list-item
No prefix - keeps classes simple. Plugins are isolated in iframes so no conflict risk.
Implementation
1. Create CSS library file
- File:
src/assets/plugin-components.css - Define all component classes using existing CSS variables
- Match Angular Material visual style (border-radius, shadows, colors, etc.)
2. Inject CSS library into plugin iframes
- File:
src/app/plugins/util/plugin-iframe.util.ts - Modify
createPluginCssInjection()to include the component library CSS - Alternatively, inline the CSS directly (avoids external fetch issues in blob URLs)
3. Document for plugin developers
- Add documentation/examples in
packages/plugin-dev/ - Update one example plugin to demonstrate usage
Files to Modify
| File | Changes |
|---|---|
src/app/plugins/plugin-api.model.ts |
Add THEME_CHANGE hook |
packages/plugin-api/src/index.ts |
Add THEME_UPDATE message type |
src/app/plugins/plugin-bridge.service.ts |
Emit theme change events |
src/app/plugins/util/plugin-iframe.util.ts |
Handle THEME_UPDATE, inject CSS library |
src/assets/plugin-components.css |
New file - CSS component library |
Implementation Order
- Add
THEME_UPDATEmessage type to plugin API package - Create
plugin-components.csswith minimal components - Update
createPluginCssInjection()to inject the CSS library - Add
THEME_CHANGEhook type - Implement theme change detection and broadcasting in
plugin-bridge.service.ts - Add message handler in iframe script for updating CSS variables
- Test with existing plugin (e.g., procrastination-buster)
CSS Component Library Design
/* Example structure for plugin-components.css */
/* Buttons */
.btn {
padding: var(--s-half) var(--s);
border-radius: 4px;
border: 1px solid var(--extra-border-color);
background: transparent;
color: var(--text-color);
cursor: pointer;
font-family: inherit;
font-size: inherit;
transition: var(--transition-standard);
}
.btn:hover {
border-color: var(--c-primary);
}
.btn-primary {
background: var(--c-primary);
border-color: var(--c-primary);
color: white;
}
.btn-primary:hover {
filter: brightness(1.1);
}
/* Cards */
.card {
background: var(--card-bg);
border-radius: var(--card-border-radius);
box-shadow: var(--card-shadow);
padding: var(--s2);
}
/* Inputs */
.input,
.textarea,
.select {
padding: var(--s-half) var(--s);
border-radius: 4px;
border: 1px solid var(--extra-border-color);
background: var(--bg);
color: var(--text-color);
font-family: inherit;
font-size: inherit;
}
.input:focus,
.textarea:focus,
.select:focus {
outline: none;
border-color: var(--c-primary);
}
/* Text utilities */
.text-muted {
color: var(--text-color-muted);
}
.text-primary {
color: var(--c-primary);
}
.text-sm {
font-size: 0.875rem;
}
/* Layout */
.stack {
display: flex;
flex-direction: column;
gap: var(--s);
}
.flex {
display: flex;
gap: var(--s);
}
Notes
- CSS library is opt-in (plugins can use it or ignore it)
- Existing plugins continue to work (backward compatible)
- Theme updates happen automatically via postMessage
- Plugins can also manually listen to
THEME_CHANGEhook for custom handling