diff --git a/{{cookiecutter.project_name}}/README.md b/{{cookiecutter.project_name}}/README.md
index e50e227..3674740 100644
--- a/{{cookiecutter.project_name}}/README.md
+++ b/{{cookiecutter.project_name}}/README.md
@@ -23,6 +23,17 @@ The following commands come pre-configured in this repository. You can see all a
- `lintfix` - runs eslint in fix mode to fix any linting errors that can be fixed automatically
- `formatfix` - runs Prettier in fix mode to fix any formatting errors that can be fixed automatically
-### Available React components
+## Styling your plugin
-See available UI components via our [Storybook](https://cortexapps.github.io/plugin-core/).
+The Cortex UI allows for custom brand colors, and has a light/dark mode switcher. We expose CSS variables to your plugin
+so you may match the current theme. These styles are injected into your plugin iframe once we receive an `init` message
+via plugin-core, and are re-injected each time the theme is changed (such as dark mode switch).
+
+The CSS variables are documented within the demo app in this project. If your plugin requires additional theme
+information, please reach out to Cortex to see about having it added!
+
+### Plugin init
+
+Mentioned above, we inject styles once the `init` message is received. This is necessary due to constraints with
+iframes. To reduce a "flash of unstyled content", it is important that your plugin sends the init message as soon as possible. Avoid calling `init` within library code, and instead keep it at the top level of your scripts so it runs once
+the plugin loads in the browser.
diff --git a/{{cookiecutter.project_name}}/package.json b/{{cookiecutter.project_name}}/package.json
index 0245b41..09afbd0 100644
--- a/{{cookiecutter.project_name}}/package.json
+++ b/{{cookiecutter.project_name}}/package.json
@@ -3,7 +3,7 @@
"version": "{{cookiecutter.version}}",
"license": "{{cookiecutter.license}}",
"dependencies": {
- "@cortexapps/plugin-core": "^2.0.0",
+ "@cortexapps/plugin-core": "^2.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
diff --git a/{{cookiecutter.project_name}}/src/baseStyles.css b/{{cookiecutter.project_name}}/src/baseStyles.css
index e9c5e5f..45a093d 100644
--- a/{{cookiecutter.project_name}}/src/baseStyles.css
+++ b/{{cookiecutter.project_name}}/src/baseStyles.css
@@ -1,3 +1,170 @@
-body {
- font: 14px sans-serif;
+body,
+html {
+ background-color: var(--cortex-plugin-background);
+ font-family: var(--cortex-plugin-font-family);
+ font-size: var(--cortex-plugin-font-size);
+ line-height: var(--cortex-plugin-line-height);
+ color: var(--cortex-plugin-primary);
+}
+.card {
+ border-radius: var(--cortex-plugin-radius);
+ border: 1px solid var(--cortex-plugin-border);
+ flex-direction: column;
+ display: flex;
+ background-color: var(--cortex-plugin-foreground);
+ margin: 8px;
+}
+.card-header {
+ padding-top: var(--cortex-plugin-container-padding);
+ padding-right: var(--cortex-plugin-container-padding);
+ padding-bottom: 0.75rem;
+ padding-left: var(--cortex-plugin-container-padding);
+ color: var(--cortex-plugin-primary);
+ font-size: 1rem;
+ line-height: 1.5rem;
+ font-weight: 500;
+}
+.card-body {
+ padding-left: var(--cortex-plugin-container-padding);
+ padding-right: var(--cortex-plugin-container-padding);
+ padding-bottom: var(--cortex-plugin-container-padding);
+ color: var(--cortex-plugin-secondary);
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+.card-footer {
+ padding-right: var(--cortex-plugin-container-padding);
+ padding-left: var(--cortex-plugin-container-padding);
+ padding-top: 0.75rem;
+ padding-bottom: 0.75rem;
+ border-top: 1px solid var(--cortex-plugin-border);
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+}
+.button {
+ background: none;
+ padding: 0.5rem;
+ border: 1px solid var(--cortex-plugin-border);
+ border-radius: var(--cortex-plugin-radius);
+ background-color: var(--cortex-plugin-background);
+ color: var(--cortex-plugin-primary);
+ font-size: 0.875rem;
+ line-height: 1rem;
+ font-weight: 500;
+ cursor: pointer;
+ transition: filter 0.2s ease;
+ white-space: nowrap;
+}
+.button:focus-visible {
+ outline: 2px solid var(--cortex-plugin-ring);
+ outline-offset: 2px;
+}
+.button:hover {
+ filter: brightness(1.1);
+}
+.button:active {
+ filter: brightness(0.85);
+}
+.button:focus {
+ outline: 2px solid var(--cortex-plugin-ring);
+ outline-offset: 2px;
+}
+.button:disabled,
+.button.disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ background-color: var(--cortex-plugin-background);
+ color: var(--cortex-plugin-muted);
+ border-color: var(--cortex-plugin-border);
+}
+.primary-button {
+ background-color: var(--cortex-plugin-accent);
+ color: var(--cortex-plugin-accent-foreground);
+}
+.danger-button {
+ background-color: var(--cortex-plugin-destructive);
+ color: var(--cortex-plugin-destructive-foreground);
+}
+.form-group {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+.form-label {
+ color: var(--cortex-plugin-primary);
+ font-weight: 500;
+}
+.form-caption {
+ color: var(--cortex-plugin-muted);
+ font-size: 0.75rem;
+ line-height: 1rem;
+}
+.form-input {
+ padding: 0.5rem;
+ border: 1px solid var(--cortex-plugin-border);
+ border-radius: var(--cortex-plugin-radius);
+ background-color: var(--cortex-plugin-input);
+ color: var(--cortex-plugin-primary);
+ transition: border-color 0.2s ease;
+}
+.form-input:focus {
+ outline: 2px solid var(--cortex-plugin-ring);
+ outline-offset: 2px;
+ border-color: var(--cortex-plugin-border);
+}
+.form-input:disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ background-color: var(--cortex-plugin-background);
+}
+
+.swatch-container {
+ display: flex;
+ align-items: end;
+ gap: 8px;
+ font-family: monospace;
+}
+.swatch {
+ border: 1px solid var(--cortex-plugin-border);
+ height: 25px;
+ width: 25px;
+ border-radius: var(--cortex-plugin-radius);
+}
+.swatch--cortex-plugin-background {
+ background-color: var(--cortex-plugin-background);
+}
+.swatch--cortex-plugin-foreground {
+ background-color: var(--cortex-plugin-foreground);
+}
+.swatch--cortex-plugin-primary {
+ background-color: var(--cortex-plugin-primary);
+}
+.swatch--cortex-plugin-secondary {
+ background-color: var(--cortex-plugin-secondary);
+}
+.swatch--cortex-plugin-muted {
+ background-color: var(--cortex-plugin-muted);
+}
+.swatch--cortex-plugin-accent {
+ background-color: var(--cortex-plugin-accent);
+}
+.swatch--cortex-plugin-accent {
+ background-color: var(--cortex-plugin-accent);
+}
+.swatch--cortex-plugin-destructive {
+ background-color: var(--cortex-plugin-destructive);
+}
+.swatch--cortex-plugin-destructive-foreground {
+ background-color: var(--cortex-plugin-destructive-foreground);
+}
+.swatch--cortex-plugin-border {
+ background-color: var(--cortex-plugin-border);
+}
+.swatch--cortex-plugin-input {
+ background-color: var(--cortex-plugin-input);
+}
+.swatch--cortex-plugin-ring {
+ background-color: var(--cortex-plugin-ring);
}
diff --git a/{{cookiecutter.project_name}}/src/components/App.tsx b/{{cookiecutter.project_name}}/src/components/App.tsx
index cc54cbb..8064c5b 100644
--- a/{{cookiecutter.project_name}}/src/components/App.tsx
+++ b/{{cookiecutter.project_name}}/src/components/App.tsx
@@ -1,23 +1,121 @@
import type React from "react";
-import {
- Logo,
- PluginProvider,
- Stack,
- Title,
-} from "@cortexapps/plugin-core/components";
+import { PluginProvider } from "@cortexapps/plugin-core/components";
+import { CortexApi } from "@cortexapps/plugin-core";
import "../baseStyles.css";
import ErrorBoundary from "./ErrorBoundary";
import PluginContext from "./PluginContext";
+// Initialize plugin for iframe style injection of theme CSS variables
+CortexApi.pluginInit();
+
const App: React.FC = () => {
return (
{JSON.stringify(context, null, 2)}
>
);