Here you can see the current readme file with all updates, breaking changes, and todos.
# Jhana UI A beautifully dark-themed Svelte and CSS ui-system that embraces glowing bright colors, round corners and fluid transitions. ## Using Jhana UI Start with the [consumer and agent guide](docs/README.md). It ships in the package under `@leon8ix/jhana-ui/docs/README.md`, alongside the [layout and field contracts](docs/foundations.md) and [help system](docs/help.md). Stable 2.x releases are developed on `main` and published to the `latest` package channel. Follow the [migration guide](docs/modernization.md) when upgrading from 1.x or a 2.0 preview, including its compatibility audit and [published-package installation](docs/modernization.md#move-a-trial-to-the-published-package). The documentation site follows `main`; packaged guides describe the installed version. ## ToDo - Finish documentation site - Add back ActionButton stroke thickening on focus-visible to stroked SVGIcon - Allow opening a context menu programmatically with an explicit anchor element, without a DOM event ## Versions ### 2.0.0 (261104) - Added shared layout and field foundations for settings interfaces - Added a proportional spacing scale, stacks, wrapping rows, natural-width field grids and scrolling panels; controls align independently of labels and hints, and related values can share the widest field's required width - Added Field with labels, visible hints and supplementary help; Field, NumberInput and ColorPicker accept `labelEnd` snippets for reset buttons and other app-owned label actions - Unified label and legend alignment and weight; field-group legends above labeled fields or nested groups receive automatic dividers, while legends above radio/toggle choices remain plain - NumberInput starts at `8em`, grows for long values and unit suffixes, and has larger stepper touch targets; wrapped hints follow the control's width without resizing it - Native separators follow horizontal or vertical layouts; `--sideSpace` defaults to `--space-3` (`1em`) for consistent page and overlay clearance - BREAKING: NumberInput retains wrapper class/style props, but selectors relying on its former wrapping label or direct input child need migration; review the [compatibility audit](docs/modernization.md#check-compatibility-first) for shared CSS and markup changes - Added boxed toggles, shared radio boxes and native radio-card styling - Toggle supports state-dependent side labels while reserving both texts' width; radio cards retain native keyboard behavior and stable dimensions - Contained hidden inputs to prevent phantom scrollbars in settings panels and removed empty radio-label spacing for indicator-only choices - Hints respect the app's text-selection policy - Added Help and tooltip attachments with text, images, snippets and components - One managed tooltip container follows active dialogs and popovers; keyboard access, click/tap pinning and native touch context-menu gestures support explanations without activating their controls - Added instant, normal (300 ms) and long (800 ms) delays, with immediate hover help between triggers until the pointer spends 150 ms away; `openOnSelect` controls radio/checkbox selection help independently and defaults off for long delay - Hover-only help closes on leaving its trigger; only explicitly pinned explanations accept pointer interaction and text selection, and selecting text keeps them open - ActionButton uses its label for an automatic long-delay tooltip; `title` overrides the explanation instead of creating a native browser tooltip - Images and custom content share consistent insets and corner radii; tooltip images are not draggable - BREAKING: Raised the Svelte peer minimum to 5.29 for attachment support - Added ColorPicker and color helpers through `/color` - Supports configurable RGB, CMYK and Grayscale modes, optional opacity, read-only inspection, a swatch field and a popup with shaded sliders, numeric inputs and live previews - Requires a dictionary for visible and accessible labels; English and German dictionaries are separate optional imports - Sliders use whole-number channel steps and opacity percentages; numeric inputs preserve typed decimals and support keyboard editing - Theme-aware handles adapt their contrast to the tracks and retain closed rings at rest without fractional-border pinholes; added a hex preview helper - Added SplitButton and joined native buttons - SplitButton pairs a default action with alternate options; arrow clicks and right-clicks open a context menu anchored to the whole group - Two native buttons can share `.btn-split` with independent actions, text, icons and disabled states; normal, primary and dark variants share one surface with independent interaction outlines - Popup footer buttons accept a menu configuration or popup-aware menu factory, with shared disabled/loading states and guarded form submission; fully disabled groups fade their surface and contents together - Improved context-menu anchoring, layers, placement and animation - Attached groups keep descendants interactive, and nested openers anchor to their control group; direct handlers anchor to their own element instead of a clicked icon or text - One CtxMenuRoot follows the trigger's active dialog or popover, fixing inert menus inside modals and unintended closure of parent popovers; closing or removing the owner dismisses its menu - Menus keep `--sideSpace` viewport clearance, shrink wide content and own scrolling for long content; tall settings menus shift only enough to fit instead of jumping toward the top - Opening and closing animations follow the source's bottom midpoint for menus below, top midpoint for menus above, or pointer position for pointer menus, including after viewport shifts and placement flips - Fallback menus and tag mappings respond to replacement props after mounting - Improved popup keyboard behavior and sizing - Plain Enter activates the visible primary footer action, including split buttons and custom controls, while preserving focused controls, form validation, disabled/loading guards and nested-layer isolation - Added per-popup and app-wide `submitOnEnter` opt-out, neutral initial focus and focus restoration after nested popups close - Content-sized dialogs retain their size within `--sideSpace` viewport limits, borders and rounded corners on narrow screens; long content scrolls while headers and footers remain visible - Fixed clipped bottom padding and unnecessary outer scrollbars in popups without footer buttons - Added shared page progress through `/page-progress` - PageProgressRoot and the reactive `pageProgress` value let components and ordinary client-side functions update one app-wide indicator; the standalone PageProgress component remains available - Added spring smoothing, a stronger leading glow and a completion pause followed by a gradient wipe instead of a backward reset - Clearing progress starts the 1000 ms disappearance delay and a 1700 ms glow fade toward 20%; holding at 100% retains full glow and resumed progress restores brightness - Shared layer handling keeps page progress visible above dialogs and popovers alongside notifications - Fixed notifications appearing behind popups or becoming inert in modal dialogs - One NotifyRoot follows the active modal through a manual popover, preserving notification state and timers across nested dialogs - Notification buttons do not submit surrounding forms - Expanded update-checker reminders and update preparation - Ask later supports split-button choices for timed reminders or successful app saves/exports; ordinary checks respect pending reminders and the default Later delay remains available - Per-call `force` overrides postponements and replaces old reminders when the prompt opens - Added asynchronous `beforeUpdate` callbacks for saving state before reload, with loading and retry after failure; dismissing the dialog prevents subsequent navigation - Refined theme inheritance, contrast and icons - Nested `theme-*` scopes inherit unspecified background, text and error colors instead of resetting them; `.theme-root` owns base defaults and each scope recalculates its shades - Brightened `--cLight` and primary-card text, softened light-button text with `--cDL05`, and added `--cAD90` for primary-button text - Icon inherits `currentColor` by default, including selected-card and button states, while preserving explicit color, hover and active overrides; review existing icon and wrapper color overrides when upgrading - Fixed icon-button interaction states - Disabled ActionButton icons retain their color on hover and press, including when disabled by a fieldset - ButtonRevert preserves an explicit disabled state when visible, preventing unintended focus and actions; hidden/disabled controls suppress pointer feedback, while keyboard focus retains color and rotation feedback without a native outline - Fixed NavIndex ignoring replacement `match` props after mounting - Expanded packaged consumer/agent guides and live documentation - Added migration and compatibility guidance, layout, help, color, icon, shading, popup, notification, progress and update-checker recipes with examples based on consumer apps - Unified examples as explanation, live demo and source with `1em` spacing; added shading configuration and component playgrounds with browser regression coverage - Added an editable icon-converter constant name and grouped its output options - Fixed update-log demo loading and lost clicks before hydration; the documentation sidebar displays the full package version - Finalized stable 2.0 publishing from `main` on the `latest` channel and consolidated the preview update log - Documentation archives use normal GitHub releases and retain the existing independent deployment workflow - Package publishing tolerates already-published versions so pushes without a new package version can still complete ### 1.61.0 (261001) - Added a shared README update-log dialog with version navigation, scroll tracking, nested bullets and inline code - Exposed `openUpdateLog(readme)` through `popup/update-log` - Added a documentation demo that loads the dialog and Jhana UI's README on demand ### 1.60.0 (260929) - Fixed spinner stroke clipping by making thickness grow inward from the outer edge - BREAKING: Changed `strength` from SVG units to a radius ratio between 0 and 1, with a default of 0.2; the SVG box includes a one-unit inset on each side for antialiasing - Added button and inline presets with independent size and strength overrides, and migrated package and documentation usages - Added size and strength playground controls, examples for every preset and a [consumer migration guide](docs/spinner-migration.md) ### 1.59.1 (260929) - Fixed combobox styling regressions from the shared-component migration - Restored the `cDL05` popup background to match cards - Added `inputAlign="center"` to balance padding around inline actions without shifting the text in default start-aligned inputs - Updated the migration guide and demos with the alignment prop, error-themed Clear button, and tabular numbers in async option rows ### Maintenance (260928) - Separated docs build/release and FTP deployment so connection failures can be retried without rebuilding or deleting releases and tags - Deployment retries FTP once after 30 seconds, supports manual deployment by docs release tag, and runs uploads one at a time - The release workflow passes the published docs tag directly to deployment and retains the incrementing docs-version suffix - Replaced archived release actions with GitHub CLI and updated checkout to v7 and FTP deployment to v4.4.0 ### 1.59.0 (260928) - Improved component prop hovers with `PrettifySome`, keeping custom props visible and native attribute types compact - Updated `@leon8ix/utils` to `^1.14.0` ### 1.58.1 (260928) - Prevented toggle and radio tracks from shrinking beside wrapped labels, keeping the controls and toggle knob aligned in narrow layouts ### Maintenance (260927) - Added repository-specific agent instructions adapted from Infinipose and Cover Designer, including release preparation and cross-repository scope rules ### 1.58.0 (260927) - Added `FSHandleAssignmentStorage` to the `fs-handles` entry point - Persisted named assignments to cached file or directory handles in local storage - Restored assigned handles with permission checks and opened a picker when an assignment could not be restored - Kept one target per assignment, retained compatibility with Infinipose's existing storage format and added assignment reset - Supported custom storage keys and picker titles ### 1.57.0 (260927) - Implemented a reusable editable `ComboBox` with typed options and Svelte rendering snippets - Added asynchronous refresh, search, pagination, opening guards, selection overrides and fallback actions - Added keyboard navigation, touch scrolling, loading and error states, and popup sizing that follows available space - Added separate basic and async file demos, Cover Designer migration documentation and browser regression tests ### 1.56.0 (260819) - Fixed update checking for nested SvelteKit routes and unavailable version metadata - Added optional SvelteKit base-path support - Matched visibility checking to its documented opt-in default and cleaned up its event listener - Added fixed and callback-based update destinations so apps can preserve state in the update URL ### Maintenance (260812) - Assigned local Vite preview port `48880` ### 1.55.1 (260530) - Added type declarations for font CSS subpath exports ### 1.55.0 (260207) - BREAKING: `Popup` changes - Renamed Popup.close() to Popup.resolveCurrent() - Clarifies what it actually does - Popup.promise will now always resolve - Returns instead: { ok: true, value } | { ok: false, reason } - Resolves after async action in onresolve or onreject has settled (popup is actually closing) - Avoids uncaught logs in console - Made Popup.resolve() and Popup.reject() async and wait for action to finish - Allows spinner to show processing action - Custom buttons combined with form need to use button type=button - Non-breaking popup changes: - Fixed popup onclose to oncancel - Made PopupButton.text reactive ### 1.54.0 (260131) - Updated all dependencies to the latest versions ### 1.53.0 (260131) - Implemented update checker utility /popup/update-checker ### 1.52.1 (260130) - Fixed ToggleLink color transition ### 1.52.0 (260130) - Made Spinner use Icon - Added hover and active color passing - Fixed hover in ctx-menu - Replaced previous Icon :focus-within with :has(input:focus-visible) - As :focus-within was causing unintended behavior, at least with ctx-menu ### 1.51.0 (260130) - Fixed Icon states for usage with inputs (e.g. ToggleLock and ToggleLink) - Hover color reacted to :focus-visible -> added :focus-within - Active color reacted to :active -> added :has(input:active) - Added accent-color :active state to ToggleLock and ToggleLink - Removed WebKit tap highlight on touch for all styled elements ### 1.50.0 (260127) - Added tables styling ### 1.49.1 (260124) - Fixed light .btn:hover not having outline ### 1.49.0 (260124) - CSS shading system changes - Replaced --glow-offset with --glow-brightness - Replaced --glow-accent with --glow-is-accent - Using transparent colors vs shadow offset for glow fixes transition glitch - Added shading to text/number inputs - Reverted -0.95 outline-offsets back to -1 - Seems to cause more issues than it solves ### 1.48.0 (260124) - BREAKING: ctx-menu changes - `CtxMenuItemProps` - Renamed: runAction > itemAction - Renamed: openSubMenu > itemSubMenu - Renamed: ctxIconItem > itemIcon - Added: ctxIcon - Added CtxMenu.openSub() - Made use of RenderingContent ### 1.47.2 (260123) - Added read-only state to input styling ### 1.47.1 (260122) - Fixed focus-outline sometimes appearing on open dialog ### 1.47.0 (260122) - Implemented CSS shading system - Added shading to .action-list items (e.g. ctx-menu) - Added shading to ProgressBar - Refined FSHandles styling ### 1.46.0 (260120) - Added outline to .btn.dark to match inputs and cards ### 1.45.0 (260120) - BREAKING: `RadioTabs` pass down general props to input element - This changes the type of `onchange` - FSManager and according popups now also read and use the browser-provided handle.name - Optimized FSManager state handling ### 1.44.0 (260116) - Allowed for passing PickerOptions for FSHandlePicker - Restructured and polished FSManager TS generics ### 1.43.1 (260115) - Added /fs-handles to exports ### 1.43.0 (260115) - Polished fs-handle-cache - Polished FSManagerState ### 1.42.0 (260115) - Further polishing of popups system - Allowed for passing components and snippets as buttons - Globalized type RenderingContent and component RenderContent ### 1.41.0 (260114) - Introduced .btn.dark to allow styling like .btn.tab - Unified FSManager and FSPicker ### 1.40.0 (260114) - Separated state and value for popups ### 1.39.1 (260113) - Fixed FSHandleManager missing strings in dict - Globalized FSHandleManager icons ### 1.39.0 (260113) - Major design imprevements - 3D-shaded state on hover and interactions - Added active style to Toggle and Radio - Unified FileSystemAccess API handle handling - Integrated fs-handle-cache system - Added FSManager and FSPicker pre-built popups ### 1.38.1 (260107) - Added /popup as export to package.json ### 1.38.0 (260107) - Implemented first working version of popups - Improved ButtonClose styling with glow effect and transition - Replaced default dev port with custom :38880 ### 1.37.1 (250809) - Fixed card:hover to only change border-color and not completely replace border style ### 1.37.0 (250808) - BREAKING: Renamed `prog`/`progress` prop to `value` for both `Spinner` and `PageProgress` - This makes it consistent with ProgressBar and HTML's native progress element - Added ProgressBar component - Added aria-atts for Spinner and PageProgress ### 1.36.0 (250808) - BREAKING: Renamed `ProgressBar` to `PageProgress` - Fixed ProgressBar to use fixed instead of absolute positioning - Fixed scroll-bar on CodeBlock from being next to header ### 1.35.0 (250802) - Implemented ctx-menu flipping - For anchored to element mode - And for global mode: Implemented additional adapter, so margin is not flipped - Internal: Separated out CtxMenuContent (visually styled content) from CtxMenuRoot (positioning and anchoring logic) ### 1.34.0 (250802) - Added iconFile ### 1.33.0 (250801) - Added keyboard shortcut indicator to ctx-menu item ('kbd') - Improved kbd styling ### 1.32.0 (250801) - Implemented loading state for async ctx-menu actions ### 1.31.0 (250801) - Properly implemented font setups - Fixed font variable fallbacks and optimized their setup - Everthing was defined via font-variation-settings and font-feature-settings - This was unnecessary, as all of these were available via standard CSS properties - Opsz can be auto-derived from font-size with font-optical-sizing: auto - Added class for styling keyboard shortcuts ### 1.30.0 (250801) - BREAKING: Changed .tab.btn to display:block - Added pathname matching modes for NavIndex - Allows for handling subpaths correctly ### 1.29.0 (250727) - Implemented Component support for CtxMenuItem - BREAKING: `CtxMenuItem: Snippet` > `CtxMenuItem: { snippet: Snippet<[CtxMenuItemProps]> }` - Use with components: `CtxMenuItem: { component: Component<CtxMenuItemProps> }` ### 1.28.1 (250727) - Had to unwrap further to reach intended goal of v1.28.0: Also removed li wrapper - Either use: `li > button`, `li > button + button` repeated as often as the entries you need - Or use: `div`, `section`, `p` for uniform block padding and rounded coners - Or use your very own setup ### 1.28.0 (250727) - BREAKING: Removed div.snippet wrapper for `CtxMenuItem Snippets` - To keep previous styling, wrap your Snippet in `div`, `section` or `p` - Allows for using button, which will be identical to native CtxMenuItem actions - Allows for using a reactive Svelte map of multiple buttons ### 1.27.0 (250726) - Improved ctx-menu opening and closing logic - Ignore right-clicks inside context menu - Close if open and would open the exact same menu anchored to the same element ### 1.26.0 (250726) - Implemented workaround for ctx-menu instantly closing again on mobile - BREAKING: Renamed `ContextGlobal` to `CtxMenuRoot` ### 1.25.0 (250724) - Implemented left-click CtxMenu - Use: onclick={openMenu(menu)} - Fixed CtxMenuTagMap for disabled menus - Updated dependencies ### 1.24.0 (250724) - Disabled pointer events for SVGIcons that have an icon-root - Fixes context menu global button handling for icon buttons - Made callback in clipboard action helpers optional - BREAKING: Context menu renames - type MenuConfig > CtxMenuConfig - type MenuItem > CtxMenuItem - class ContextMenu > CtxMenu - type ContextMenu['tagMap'] > CtxMenuTagMap - Allowed non-checkers on CtxMenuTagMap - CtxMenuOpeningAction can be used as well ### 1.23.0 (250724) - Added input context menu clipboard action helpers: copy, cut, paste ### 1.22.0 (250723) - Improved ToggleLink and ToggleLock setup - Fixed sizing issues - Migrated to SVGIcon snippet syntax - Added styling for svg containing .toggles and .radios, so they fit in line with text and number inputs inside .input-groups - Used by ToggleLink and ToggleLock - Corrected \[disabled] to :disabled in the global stylesheet - Removed forced id generation for all input components - Not neccessary, since input is child of label - Name can either be passed or not, id is no longer used as name fallback - BREAKING: Removed highlight prop from Radio, just pass it as the class ### 1.21.0 (250722) - Improved NumberInput styling - Correct cursor for buttons - Correct button style on disabled state ### 1.20.0 (250721) - BREAKING: Removed `.active` class from `Icon` - Only :active pseudo-class will be listened to from now on - For creating alternative theming for an activated state, the color reactivity should be handled by the parent component - Both :hover and :active might be different values on an activated state - ActionButton was adapted accordingly ### 1.19.1 (250718) - Fixed NavIndex, hidden text was visible due to icon-btn change ### 1.19.0 (250718) - Added /transitions, specifically flexSlide ### 1.18.0 (250718) - Added .btn.icon style - Deprecated .btn.icon-btn class, this works automatically now - Remove any .icon-btn classes in your repo ### 1.17.1 (250718) - Fixed recent dirs not being added to package.json to allow importing ### 1.17.0 (250718) - Added scrollbar styling to global stylesheet ### 1.16.0 (250717) - Added context menu logic and component - Added action-list to global stylesheet ### 1.15.0 (250715) - BREAKING: Changed input components, so that class and style apply to wrapper - Other atts still apply to the input element itself - Changed: `NumberInput`, `Radio`, `Toggle`, `ToggleLink`, `ToggleLock` - NumberInput had workaround `cls`, which was replaced with `class` again ### 1.14.1 (250715) - Fixed current location matching for both Tabs and NavIndex - Docs changes - Fixed default minimized state - Fixed output for paths, so reloading works on web server ### 1.14.0 (250714) - Added NavIndex minimized state, with smooth transition ### 1.13.1 (250713) - Fixed CodeBlock overflowing and breaking layout ### 1.13.0 (250713) - BREAKING: Separated font-faces from global style sheet - You need to import `@leon8ix/jhana-ui/fonts/inter.css` to keep Inter font as before - Implemented CSS variables for - Monospace font - Variable font feature and variation settings - Added bold class to CSS and made `b` and `strong` bold as well - Improved CodeBlock styling ### 1.12.0 (250712) - Replaced button texts in CodeBlock with icons ### 1.11.0 (250712) - BREAKING: Transitioned to flexible `SVGIcon` syntax for all icons - Added CodeBlock component ### 1.10.2 (250625) - Fixed NumberInput up/down arrows causing weird numbers (rounds to 12 digits now) ### 1.10.1 (250625) - Fixed NumberInput disable, applies to up/down arrows as well now ### 1.10.0 (250612) - Updated all dependencies ### 1.9.0 (250612) - Changed notify to allow for replacing noti data while open using id ### 1.8.0 (250612) - Switched over to use Bun instead of NPM ### 1.7.0 (250612) - Replaced internal utils functions with @leon8ix/utils - Auth token not included: Needs to be in user's home directory or consuming package ### 1.6.0 (250420) - Added Spinner component ### 1.5.1 (250420) - Removed SVG (and IMG etc.) reset, as it was causing problems with ToggleLock and ToggleLink ### 1.5.0 (250420) - Made CSS reset much less aggressive - Basically no global selector, all default styled elements are targeted specifically - Previously global styles would overwrite any SVG's presentation atts - Only padding and margin are still global - Global 'outline: none' removed for accessibility - Only classes that specifically handle :focus-visible have 'outline: none' - Tested with - Infinipose 3.34.0-pre.4 - Cover Designer 2.0.0-pre.11 ### 1.4.1 (250417) - Fixed font shorthand overwriting variable font-weight ### 1.4.0 (250417) - Improved CSS reset in the stylesheet - Updated dependencies ### 1.3.0 (250416) - Added keyboard shortcut Svelte action ### 1.2.4 (250315) - Fixed ActionButton class and color logic ### 1.2.3 (250315) - Fixed missing unit for space-y-sm ### 1.2.2 (250312) - Fixed NotifyRoot fixed positioning ### 1.2.1 (250309) - Added /notify entrypoint ### 1.2.0 (250309) - Added notification system ### 1.1.2 (250307) - Fixed btn with non-button tags not having browser style for button line-height: normal ### 1.1.1 (250305) - Fixed action-btn svg still depending on px unit ### 1.1.0 (250305) - Replaced rem with em, as rem would cause problems on dynamic font size change ### 1.0.1 (250302) - Fixed style.css import not working for consuming package ### 1.0.0 (250302) - Initial commit - Extracted out from Print Meter v4.0.0 - Before being used for and adapted to Print Meter, it was used in Infinipose - Before being used for and adapted to Infinipose, it was developed for IconBase