diff --git a/.changeset/ninety-books-itch.md b/.changeset/ninety-books-itch.md
new file mode 100644
index 00000000..b24997dc
--- /dev/null
+++ b/.changeset/ninety-books-itch.md
@@ -0,0 +1,34 @@
+---
+'playroom': minor
+---
+
+Enable embedded CSS formatting on save
+
+CSS authored inside `style` tags inside a playroom will now be formatted as CSS when wrapped in a `css` template literal tag.
+
+A `css` template literal tag can be injected into your playroom scope via the [custom scope] feature:
+
+```js
+// customScope.js
+
+export default () => {
+ return {
+ css: (css) => css,
+ };
+};
+```
+
+This template literal tag can then be used in your playroom:
+
+```jsx
+
+
Hello, world!
+```
+
+[custom scope]: https://github.com/seek-oss/playroom?tab=readme-ov-file#custom-scope
diff --git a/cypress/projects/basic/useScope.js b/cypress/projects/basic/useScope.js
index 5f6042c7..f80072d0 100644
--- a/cypress/projects/basic/useScope.js
+++ b/cypress/projects/basic/useScope.js
@@ -1,4 +1,5 @@
export default () => ({
hello: () => 'HELLO',
world: () => 'WORLD',
+ css: (css) => css,
});
diff --git a/src/utils/formatting.ts b/src/utils/formatting.ts
index dbdecff8..9798d84b 100644
--- a/src/utils/formatting.ts
+++ b/src/utils/formatting.ts
@@ -1,5 +1,6 @@
import prettier from 'prettier/standalone';
import babel from 'prettier/parser-babel';
+import postcss from 'prettier/parser-postcss';
import type { CursorPosition } from '../StoreContext/StoreContext';
import { insertAtCursor } from './cursor';
@@ -21,7 +22,7 @@ export const runPrettier = ({
return prettier.formatWithCursor(code, {
cursorOffset,
parser: 'babel',
- plugins: [babel],
+ plugins: [babel, postcss],
});
} catch (e) {
// Just a formatting error so we pass