Releases: athledev-labs/opennook
OpenNook v0.4.0
Added
NookChromeTypography- a host-tunable token type for the framework's own
fonts. Set viaNookConfiguration.typography; defaults reproduce the framework
exactly, and the resolvedfontDesignstill cascades over the roles. Restyles
framework text without forking, the typography counterpart to the existing color
(NookResolvedTheme) and layout (NookChromeMetrics) seams. Roles cover the
top bar, compact pill, and status banner, plus the placeholder home, the
built-in Settings panel, and the optionalNookComponentsadd-ons.NookChromeMetricsgained the element-level dimensions, corner radii, spacing,
and emphasis-opacity values that were previously baked into the framework views -
the chrome (header icons, leading brand mark, compact pill, status banner), the
placeholder home, the Settings panel (rows, pickers, the shortcut key cap, the
accent swatches, the disclosure section), and theNookComponentsshelf,
activity card, and volume glyph. All new fields default to today's values, so
the change is additive and non-breaking.
Changed
- The framework views now read every font, size, radius, spacing, and opacity from
NookChromeTypography/NookChromeMetricsinstead of inline literals - the
chrome (top bar, header icons, compact pill, status banner), the placeholder
home, the built-in Settings panel, and theNookComponentsadd-ons. No visual
change at the defaults; a host can now restyle any of these surfaces through
public API only. (A few intentionally-structural literals stay inline: motion
spring/offset magnitudes, the breadcrumb gradient mask, the fixed severity and
destructive-action colors, and zero-floor spacers.) - The GitHub repository moved to athledev-labs/opennook.
Update your Swift package URL; GitHub redirects the oldglendonC/opennookpath
for a transition period.
v0.3.1 - Build on older Xcode
A small fix release. The headline: OpenNook no longer requires Xcode 26 to
build.
This is still 0.x: the public API is not frozen. Pin to a tag.
Fixed
- The Liquid Glass surface style now builds on Xcode versions earlier than
26. ItsGlass/.glassEffectuse is from the macOS 26 SDK, and
@availableis only a runtime gate - it still needs those symbols present in
the SDK being compiled against, so an earlier Xcode failed with "cannot find
'Glass' in scope". The real path is now compile-gated behind
#if compiler(>=6.2): an earlier toolchain compiles the pre-Tahoe
approximation instead, while building with the macOS 26 SDK keeps the real
material (runtime-gated to macOS 26). A consumer on an older Xcode can now
build the package. - Cleared a Swift 6 concurrency warning on
NookFilePickerKey.defaultValue(a
@MainActor-isolated value held in a nonisolated static) by giving the inert
default picker anonisolated init. No behavior change.
Install
.package(url: "https://github.com/glendonC/opennook", from: "0.3.1")Requirements
- macOS 15 or later (the Liquid Glass material itself needs macOS 26; every
other surface style works on macOS 15+) - Swift 5.9+ to consume; building the real Liquid Glass material needs the
macOS 26 SDK (Xcode 26+), otherwise the package builds the approximation
Migration
Nothing to do beyond bumping the dependency.
v0.3.0 - The chrome-customization release
v0.3.0 opens up the framework chrome. Everything a host could previously change
only by forking NookExpandedView is now an additive, non-breaking seam on
NookConfiguration - corner radii, transition curves, expanded width, the
top-bar trailing items, labels, metrics, motion, brand mark, launch defaults,
and a replaceable Settings surface. It also adds a Liquid Glass surface style,
a chrome-derived safe-area for host content (NookContentInsets), and the
module drill-in breadcrumb.
This is the surface downstream hosts have been pinning from main. As of
0.3.0 you can pin a tag again.
This is still 0.x: the public API is not frozen. Pin to a tag.
No source-breaking changes
Every new seam defaults to the existing behavior, and nothing changes for a
single-module host. NookConfiguration(), the Nook demo, and all Examples/*
build unchanged.
One behavior change for multi-module hosts: the module switcher is no longer
a chrome band at the top of the expanded surface. By default switching now
lives in a "Modules" menu-bar section and the cycle / per-module hotkeys, and
the surface stays entirely the module's own. Opt back into an on-screen
switcher with host.moduleSwitcherPlacement = .leadingCluster.
What's new
Chrome customization seams
The headline of the release. All additive on NookConfiguration:
style- chrome corner radii.transitions- expand / collapse / convert animation curves.expandedWidthplus a top-bar width mode (.contentColumn) so the top bar
and host content share one horizontal edge.setSettings(_:)/settings- drop in a custom Settings surface, still
reached via the gear.NookAppearanceSettingsSectionlets you embed the
framework's appearance controls inside it.setTopBarTrailingItems- host actions left of the lock / gear.NookChromeBehavior- hover side-effects, the cold-launch shimmer, and the
appearance-to-backdrop mapping.NookChromeLabels/NookChromeMetrics/NookChromeMotionand host status
severity - localized strings, the few fixed layout values, the in-panel
springs, and info / success / warning / error banners.NookPreferenceDefaults- host-seeded launch appearance, hotkey, and display
target. Seed-only: a user value always wins and the seed is never persisted,
so a later build can revise it for untouched users.NookHostBrandingbrand mark +NookMarkView- a custom mark that replaces
the OpenNook glyph in the top bar, About card, and menu bar.NookAccentPreset/accentPreset,NookResolvedTheme.accent, and
NookResolvedTheme.fontDesign- brand the interactive chrome tint and the
chrome's own typography.
See the new Examples/ChromeNook for the deeper seams in one place.
Liquid Glass surface style
A third surface style alongside translucent and solid: the real macOS 26
glassEffect material, with a layered pre-Tahoe approximation as the fallback.
It is availability-gated, so it renders the modern material on macOS 26 and the
approximation everywhere else without a runtime-version crash. Host-configurable
like the other styles.
NookContentInsets
A chrome-derived safe-area. Host content can read the inset the chrome occupies
and align to the same horizontal edge as the top bar instead of double-padding.
The per-edge expanded-content inset is configurable (NookEdgeInsets).
Module drill-in breadcrumb
AppState.moduleBreadcrumb renders a drill-in breadcrumb on the host top bar
for multi-module hosts, with an overflow fade mask constrained to the pre-notch
region so it never bleeds under the physical notch.
Module switcher placement
host.moduleSwitcherPlacement decides where a multi-module host surfaces its
switcher; switching is always reachable through the cycle and per-module
hotkeys regardless.
.menuBar(default) - a "Modules" section in the menu-bar item, with a check
on the active module. Nothing is added to the expanded surface..leadingCluster- a compact switcher folded into the top bar's leading
cluster. It replaces the leading title rather than adding a band, so it costs
no extra height and never duplicates the active module's identity..none- no on-screen switcher; hotkeys only.
Host file picker for modules
Modules present open / save panels through the host's file picker
(filePicker), which activates the app so the panel is interactive from the
non-activating notch panel and holds the surface open while it is up. File
import is folded into the shelf.
Install
.package(url: "https://github.com/glendonC/opennook", from: "0.3.0")Requirements
- macOS 15 or later
- Swift 5.9+
- Apple Silicon or Intel; notched display preferred but not required
Migration
Nothing required beyond bumping the dependency. Every chrome seam defaults to
the current behavior; adopt them only where you want to diverge from the demo
chrome.
v0.1.0 - Foundation
v0.1.0 - Foundation
The first tagged release of OpenNook - an open-source Swift framework for
building macOS notch apps. The notch window, lifecycle, hotkey, settings
shell, and an opt-in components layer are all here.
This is 0.x: the public API is intentionally not frozen yet. Pin to a
tag, expect minor surface adjustments before 1.0.
What's in the box
NookSurface(MIT) - the notch window engine: shape, panel, hover
behavior, translucent backdrop, shimmer feedback. Multi-display aware;
survives fullscreen; falls back to a floating capsule on non-notched
Macs.NookKit(Apache-2.0) - the app chrome:AppCoordinatorlifecycle,
AppState, persisted appearance/display/hotkey preferences, the top bar- settings panels, Carbon-backed global hotkey, screen locator with
stable display UUIDs.
- settings panels, Carbon-backed global hotkey, screen locator with
NookApp- the library entry point.NookApp.main { MyHomeView() }
is the headline "register a view, go" signature.NookComponents(Apache-2.0, opt-in) - three production-ready
add-ons:- File shelf - drop files on the notch, drag them back out (promise-
backed, works for Mail/upload widgets), persistent across launches via
scoped bookmarks, sandbox-aware acceptance modes. - Activity queue - priority-ordered transient takeovers of the
expanded surface; yields back to the user automatically. - Ambient volume glyph - CoreAudio-backed indicator in the compact
pill. No HUD interception - it's an ambient cue, not a replacement.
- File shelf - drop files on the notch, drag them back out (promise-
Highlights
- Multiple modules in one notch. A single host can run several
interchangeable notch surfaces sharing one window, one menu bar, and one
set of preferences. Module switching is one atomic transaction -
arbiter claims do not leak across modules. - Surface-ownership arbiter.
NookSurfacePresentinggeneralizes the
expand/compact save/restore pattern. Sticky owners (shelf), transient
owners (activity), and the user (hotkey/hover) coexist without colliding. - Layout: auto / notch / floating.
NookPresentationadapts to the
display: notched-shape on notched displays, floating capsule on others.
User-overridable in Settings → Appearance. - Optional chrome.
showsTopBar/showsSettingsflags strip the
framework chrome for a bare glance/widget surface without forking. - Strict concurrency, every target.
StrictConcurrencyupcoming
feature opted in across the package - including examples and tests, so
the public idiom can't drift from the rules. - Dual-license boundary, CI-enforced. Every Swift file carries an SPDX
header; CI fails ifSources/NookSurface/drifts off MIT or anything
else drifts off Apache-2.0.
Seven runnable examples
Each is a single main.swift using the public API:
swift run HelloNook # register one view, go
swift run ClockNook # custom home + custom compact slot
swift run ThemedNook # host-supplied theme + lifecycle hooks
swift run ShelfNook # drop-files shelf (NookComponents)
swift run ActivityNook # priority live-activity queue (NookComponents)
swift run VolumeNook # ambient volume glyph (NookComponents)
swift run MultiNook # multiple modules sharing one surfaceInstall
Add OpenNook to your Package.swift:
.package(url: "https://github.com/glendonC/opennook", from: "0.1.0")Then depend on NookApp (and optionally NookComponents) in your target.
Requirements
- macOS 13 or later
- Swift 5.9+
- Apple Silicon or Intel; notched display preferred but not required
What's deliberately not in 0.1
- No Now Playing / media integration in-package - the only working path is
privateMediaRemote, which disqualifies hosts from the Mac App Store.
A documented out-of-tree integration is planned. - No brightness indicator - requires private
DisplayServiceson Apple
Silicon. Volume is shipped (CoreAudio is fully public). - No native HUD suppression - would require SIP-off / event interception,
not viable for a framework.
Licensing
- Everything is Apache-2.0 except
Sources/NookSurface/, which is
MIT (forked from
DynamicNotchKit by Kai
Azim). Both licenses are permissive; you can ship closed-source on top. - See
LICENSE,LICENSE-MIT-NOOKSURFACE,NOTICE.md, and
ThirdPartyLicenses/.
Thanks
Built on top of Kai Azim's
DynamicNotchKit. The
chrome-primitive layer remains MIT and acknowledges the upstream
throughout - see NOTICE.md for the full attribution.