diff --git a/README.md b/README.md
index 64cb06248..cc8e12184 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
[![JetBrains incubator](https://img.shields.io/badge/JetBrains-incubator-yellow)](https://github.com/JetBrains#jetbrains-on-github) [![CI checks](https://img.shields.io/github/actions/workflow/status/JetBrains/jewel/build.yml?logo=github)](https://github.com/JetBrains/jewel/actions/workflows/build.yml) [![Licensed under Apache 2.0](https://img.shields.io/github/license/JetBrains/jewel)](https://github.com/JetBrains/jewel/blob/main/LICENSE) [![Latest release](https://img.shields.io/github/v/release/JetBrains/jewel?include_prereleases&label=Latest%20Release&logo=github)](https://github.com/JetBrains/jewel/releases/latest)
-
# Jewel: a Compose for Desktop theme
@@ -10,11 +9,14 @@ desktop-optimized theme and set of components.
> [!WARNING]
>
-> This project is in active development, and caution is advised when considering it for production uses. You _can_,
-> but you should expect APIs to change often, things to move around and/or break, and all that jazz. Binary
-> compatibility is not currently guaranteed across releases, but it is an eventual aim for 1.0, if it is possible.
+> This project is in active development, and caution is advised when considering it for production uses. You _can_ use
+> it, but you should expect APIs to change often, things to move around and/or break, and all that jazz. Binary
+> compatibility is not guaranteed across releases, and APIs are still in flux and subject to change.
+>
+> Writing 3rd party IntelliJ Plugins in Compose for Desktop is currently **not officially supported** by the IntelliJ
+> Platform. It should work, but your mileage may vary, and if things break you're on your own.
>
-> Use at your own risk! (but have fun if you do!)
+> Use at your own risk!
Jewel provides stand-alone implementations of the IntelliJ Platform themes that can be used in any Compose for Desktop
application, and a Swing LaF Bridge that only works in the IntelliJ Platform (i.e., used to create IDE plugins), but
@@ -26,15 +28,27 @@ The project is split in modules:
1. `buildSrc` contains the build logic, including:
* The `jewel` and `jewel-publish` configuration plugins
+ * The `jewel-check-public-api` and `jewel-linting` configuration plugins
* The Theme Palette generator plugin
-2. `core` contains the foundational Jewel functionality, including the components and their styling primitives
-3. `int-ui` implements the standalone version of the IntelliJ New UI, which implements the
- ["Int UI" design system](https://www.figma.com/community/file/1227732692272811382/int-ui-kit), and can be used
- anywhere
-4. `ide-laf-bridge` contains the Swing LaF bridge to use in IntelliJ Platform plugins (see more below)
-5. `samples` contains the example apps, which showcase the available components:
- 1. `standalone` is a regular CfD app, using the predefined "base" theme definitions
- 2. `ide-plugin` is an IntelliJ plugin, adding some UI to the IDE, and showcasing the use of the Swing Bridge
+ * The Studio Releases generator plugin
+2. `foundation` contains the foundational Jewel functionality:
+ * Basic components without strong styling (e.g., `SelectableLazyColumn`, `BasicLazyTree`)
+ * The `JewelTheme` interface with a few basic composition locals
+ * The state management primitives
+ * The Jewel annotations
+ * A few other primitives
+3. `ui` contains all the styled components and custom painters logic
+4. `decorated-window` contains basic, unstyled functionality to have custom window decoration on the JetBrains Runtime
+5. `int-ui` contains two modules:
+ * `int-ui-standalone` has a standalone version of the Int UI styling values that can be used in any Compose for
+ Desktop app
+ * `int-ui-decorated-window` has a standalone version of the Int UI styling values for the custom window decoration
+ that can be used in any Compose for Desktop app
+5. `ide-laf-bridge` contains the Swing LaF bridge to use in IntelliJ Platform plugins (see more below)
+ * The `ide-laf-bridge-*` sub-modules contain code that is specific to a certain IntelliJ Platform version
+6. `samples` contains the example apps, which showcase the available components:
+ * `standalone` is a regular CfD app, using the standalone theme definitions and custom window decoration
+ * `ide-plugin` is an IntelliJ plugin that showcases the use of the Swing Bridge
### Int UI Standalone theme
@@ -46,31 +60,107 @@ to your heart's content. By default, it matches the official Int UI specs.
> as it has extra features and patches for UI functionalities that aren't available in other JDKs.
> We **do not support** running Jewel on any other JDK.
+To use Jewel components in a non-IntelliJ Platform environment, you need to wrap your UI hierarchy in a `IntUiTheme`
+composable:
+
+```kotlin
+IntUiTheme(isDark = false) {
+ // ...
+}
+```
+
+If you want more control over the theming, you can use other `IntUiTheme` overloads, like the standalone sample does.
+
+#### Custom window decoration
+The JetBrains Runtime allows windows to have a custom decoration instead of the regular title bar.
+
+![A screenshot of the custom window decoration in the standalone sample](art/docs/custom-chrome.png)
+
+The standalone sample app shows how to easily get something that looks like a JetBrains IDE; if you want to go _very_
+custom, you only need to depend on the `decorated-window` module, which contains all the required primitives, but not
+the Int UI styling.
+
+To get an IntelliJ-like custom title bar, you need to pass the window decoration styling to your theme call, and add the
+`DecoratedWindow` composable at the top level of the theme:
+
+```kotlin
+IntUiTheme(
+ themeDefinition,
+ componentStyling = {
+ themeDefinition.decoratedWindowComponentStyling(
+ titleBarStyle = TitleBarStyle.light()
+ )
+ },
+) {
+ DecoratedWindow(
+ onCloseRequest = { exitApplication() },
+ ) {
+ // ...
+ }
+}
+```
+
### The Swing Bridge
-Jewel includes a crucial element for proper integration with the IDE: a bridge between the Swing components, theme
-and LaF, and the Compose world.
+Jewel includes a crucial element for proper integration with the IDE: a bridge between the Swing components — theme
+and LaF — and the Compose world.
This bridge ensures that we pick up the colours, typography, metrics, and images as defined in the current IntelliJ
-theme, and apply them to the Compose components as well — at least for themes that use the
-standard [IntelliJ theming](https://plugins.jetbrains.com/docs/intellij/themes-getting-started.html) mechanisms.
+theme, and apply them to the Compose components as well. This means Jewel will automatically adapt to IntelliJ Platform
+themes that use the [standard theming](https://plugins.jetbrains.com/docs/intellij/themes-getting-started.html) mechanisms.
> [!NOTE]
> IntelliJ themes that use non-standard mechanisms (such as providing custom UI implementations for Swing components)
-> are not, and will never, be supported.
+> are not, and can never, be supported.
-If you're writing an IntelliJ Platform plugin, you should use the `SwingBridgeTheme` instead of a standalone theme.
+If you're writing an IntelliJ Platform plugin, you should use the `SwingBridgeTheme` instead of the standalone theme:
+
+```kotlin
+SwingBridgeTheme {
+ // ...
+}
+```
#### Accessing icons
-When you want to draw an icon from the resources, you should use a `PainterProvider`. Reading an icon from the IDE is
-as easy as using the `retrieveStatefulIcon()` and `retrieveStatelessIcon()`:
+When you want to draw an icon from the resources, you can either use the `Icon` composable and pass it the resource path
+and the corresponding class to look up the classpath from, or go one lever deeper and use the lower level,
+`Painter`-based API.
+
+The `Icon` approach looks like this:
```kotlin
-val svgLoader = service().svgLoader
-val painterProvider = retrieveStatelessIcon("icons/bot-toolwindow.svg", svgLoader, iconData)
+// Load the "close" icon from the IDE's AllIcons class
+Icon(
+ "actions/close.svg",
+ iconClass = AllIcons::class.java,
+ contentDescription = "Close",
+)
```
+To obtain a `Painter`, instead, you'd use:
+
+```kotlin
+val painterProvider = rememberResourcePainterProvider(
+ path = "actions/close.svg",
+ iconClass = AllIcons::class.java
+)
+val painter by painterProvider.getPainter()
+```
+
+#### Icon runtime patching
+Jewel emulates the under-the-hood machinations that happen in the IntelliJ Platform when loading icons. Specifically,
+the resource will be subject to some transformations before being loaded.
+
+For example, in the IDE, if New UI is active, the icon path may be replaced with a different one. Some key colors in SVG
+icons will also be replaced based on the current theme. See
+[the docs](https://plugins.jetbrains.com/docs/intellij/work-with-icons-and-images.html#new-ui-icons).
+
+Beyond that, even in standalone, Jewel will pick up icons with the appropriate dark/light variant for the current theme,
+and for bitmap icons it will try to pick the 2x variants based on the `LocalDensity`.
+
+If you want to learn more about this system, the entry point is the `PainterHint` class.
+
### Swing interoperability
As this is Compose for Desktop, you get a good degree of interoperability with Swing. To avoid glitches and z-order
@@ -79,7 +169,7 @@ issues, you should enable the
before you initialize Compose content.
The `ToolWindow.addComposeTab()` extension function provided by the `ide-laf-bridge` module will take care of that for
-you, but if you want to also enable it in other scenarios and in standalone applications, you can call the
+you. However, if you want to also enable it in other scenarios and in standalone applications, you can call the
`enableNewSwingCompositing()` function in your Compose entry points (that is, right before creating a `ComposePanel`).
> [!NOTE]
diff --git a/art/docs/custom-chrome.png b/art/docs/custom-chrome.png
new file mode 100644
index 000000000..a8a331a18
Binary files /dev/null and b/art/docs/custom-chrome.png differ