In Angular 21, the CDK overlay defaults to using the popover attribute,
which causes overlay-based components (sheets, dialogs, tooltips) to
always render above position: fixed elements like hlm-toaster. This
adds a provideSpartanHlm() utility that configures OVERLAY_DEFAULT_CONFIG
with usePopover: false, and documents the issue in the sonner docs.
Closes#1280
Panel stays mounted through the exit animation then disposes, reopen cancels a
pending teardown, no-animation disposes promptly; plus non-modal (no backdrop),
autoFocus opt-out, outside-pointer gating, unique overlay ids, and the
destroyed-output guard.
Exercises the getPositionStrategy() override for bottom/top/left/right and the
modal backdrop, guarding the drawer's adaptation to the new dialog lifecycle.
Regression coverage for the overlay lifecycle work: autoFocus moves focus to
the first tabbable element on open, leaves focus on the trigger when the
content has none (the select/combobox keyboard model), restores focus to the
trigger on Escape, and a nested popover does not dismiss its parent while it is
the topmost overlay.
Moving popover-backed controls off CDK Dialog dropped the dialog's
autoFocus: 'first-tabbable', so popovers no longer moved focus to their
content on open (form fields were left unfocused, comboboxes could not be
typed into immediately).
Add an opt-in autoFocus option to BrnOverlay that focuses the first tabbable
element once the content renders, and enable it in the popover defaults. The
select keeps focus on its trigger because its listbox has no tabbable element,
preserving the aria-activedescendant keyboard model. Re-expose the autoFocus
input on the helm popover wrapper and its CLI template, and refresh the docs
API snapshot.
The drawer landed on main against the old BrnDialog API. Reconcile it with
this branch's refactor:
- override getPositionStrategy() for the directional position instead of the
removed mutablePositionStrategy/positionBuilder members (matches BrnSheet)
- constrain BrnDrawerContent<T extends Record<string, unknown>> to satisfy
BrnDialogContent's tightened generic
- drop the removed closeDelay-era 'delay' input from the drawer close wrapper
and its CLI template
Resolve brn-dialog.service.ts conflict: drop the deprecated injectBrnDialogCtx
alias (removed on main during the pre-1.0 audit) and keep the typed
injectBrnDialogContext with the unknown default.
* feat(command): add style and rtl support #1399
* fix: comments
* feat(command): remove custom data-hidden is built in
* remove important from rounded
* docs(command): fix typo
* fix(command): check has search input for separator
* otherwise shows multiple separator while searching in the scrollable example
---------
Co-authored-by: Merlin <merlin.moos@oldendorff.com>
Co-authored-by: Marc Stammerjohann <8985933+marcjulian@users.noreply.github.com>
The data-slot pass added host/template data-slot to helm navigation-menu and slider, but the brain
directives those wrappers compose (BrnNavigationMenu* via hostDirectives, BrnSlider/brnSliderTrack/
brnSliderRange/brnSliderThumb in the slider template) already emit the identical data-slot on the
same elements. The helm copies were dead duplication and a future drift hazard. Removed them; the
slots remain in the DOM via the brain layer (verified in browser). The genuinely-new slots
(switch, input, progress, popover, calendar root) stay - the brain layer provides none for those.
The data-slot additions inserted the `host` key directly after `selector`, violating the
workspace `@nx/workspace-component-directive-key-order` rule (host must follow hostDirectives).
Reorder the affected calendar/input/navigation-menu/popover/progress/slider metadata; no behavior
change.
Remove the mis-cased `HlmBreadCrumbImports` alias in favour of the canonical
`HlmBreadcrumbImports`, dropping it before 1.0 rather than carrying it on the stable line. The
NgModule migration map is repointed to the canonical name so `nx g @spartan-ng/cli:migrate-module-
imports` still rewrites `HlmBreadCrumbModule` to an export that exists.
Standardize the `data-slot` styling contract across the helm layer so themes and
consumers have a consistent, public styling hook on every component. Adds the
attribute to switch, switch-thumb, input, slider (track/range/thumb), progress,
progress-indicator, calendar, navigation-menu (root/list/item/trigger/link) and
popover (root/content), matching the shadcn slot names.
BrnAvatarImage/BrnAvatarFallback and their helm wrappers all used the same
unprefixed exportAs ('avatarImage'/'avatarFallback'). Since the helm directive
host-applies the brain one on the same <img>, a template ref was ambiguous, and
the names broke the brn*/hlm* convention every other exportAs follows. Rename to
brnAvatarImage/brnAvatarFallback and hlmAvatarImage/hlmAvatarFallback before the
exportAs surface is locked at 1.0. Regenerated the CLI avatar templates to match.
- Remove unused HlmDrawerHandle directive
- Add static touch-action: none to .spartan-drawer-content in all
style files so iOS Safari does not hijack the gesture before the
pointerdown handler fires
- Set _openTime via effect on dialog state open instead of on first
pointerdown, so the 500ms cooldown starts when the drawer opens
rather than eating the user's first drag
Improve drag smoothness and reliability by implementing position
tracking in BrnDrawerHandle. Simplify the component structure by moving
the handle logic to a host directive on HlmDrawerContent and removing
manual pointer-events management.
Add RTL preview example with EN/AR/HE translations,
pointer-events:none on body while drawer is open (removed with 300ms
delay on close), and replace div.px-4 with hlm-field-group for proper
spacing.
Emit the spartan-slider-ticks marker so the ticks container padding, which
offsets ticks to the thumb center, is defined per registry style instead of a
fixed px-1.5. The previous fixed padding assumed a 12px thumb, so ticks were
misaligned for styles with larger thumbs (luma, vega, mira, maia). Set the
padding to each style's thumb radius across luma, vega, lyra, nova, mira and
maia, for both horizontal and vertical orientations.
Closes#1455
Replace fixed close delays with lifecycle-driven disposal so overlays remain responsive.
Wait only for exit animations that actually start and centralize Escape, backdrop, and
outside-pointer dismissal.
BREAKING CHANGE: remove the closeDelay input and configuration option. Remove explicit delay
values; closed-state exit animations are now detected automatically.
The mcp vite config lacked `root: __dirname`, so the @nx/vitest executor (which
runs from the workspace root) resolved `src/**/*.spec.ts` against the workspace
root, found nothing, and `passWithNoTests` passed it silently - mcp's 19 tests
never ran.
Pin mcp's root, and drop `passWithNoTests` from every project that has specs
(mcp, cli, tools, brain, helm) so a future test-discovery break fails loudly
instead of going green. registry keeps the flag - it genuinely has no specs.
Replace Jest with Vitest across the workspace. The brain and helm Angular suites
now run in a real browser (Playwright/Chromium via Vitest browser mode) so they
exercise real layout, focus, pointer events and computed styles that jsdom could
not. The cli, tools, mcp, registry and cli-smoke suites run on Vitest's node
environment.
- Add per-project vite configs and switch test targets to @nx/vitest:test
- Convert jest APIs to vi.* and jest module mocks to vi.mock with importOriginal
- Replace jest-axe with a browser-native axe-core helper and toHaveNoViolations
- Regenerate snapshots in vitest format (content unchanged, format-only)
- Remove all jest packages, configs, the preset and the @nx/jest target default
- Install Playwright Chromium in the CI unit job for the browser suites
Also fixes a brain avatar test that asserted inside a fire-and-forget setTimeout,
which passed vacuously under jsdom and only surfaced once a real browser loaded
the image.