@nordmanai/nif 0.2.14 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,9 +70,17 @@ export type NmSidebarTriggerProps = Omit<ComponentProps<'button'>, 'aria-label'>
70
70
  icon?: NmIconId;
71
71
  /** On by default: a tooltip with the name and the ⌘B shortcut. */
72
72
  tooltip?: boolean;
73
+ /**
74
+ * Keeps the toggle at one spot of the provider whether the sidebar is open or closed: it is taken out of
75
+ * the flow and anchored at the top start corner, above the sidebar. The header leaves room for it, and
76
+ * `NmSidebarTriggerSpace` holds its place in a bar while the sidebar is closed.
77
+ */
78
+ anchored?: boolean;
73
79
  };
74
80
  /** The button that opens and closes the sidebar. In the main area's bar, or in the sidebar's own header. Resting on it peeks the sidebar. */
75
- export declare function NmSidebarTrigger({ className, label, icon, tooltip, onClick, onPointerEnter, onPointerLeave, ...props }: NmSidebarTriggerProps): ReactNode;
81
+ export declare function NmSidebarTrigger({ className, label, icon, tooltip, anchored, onClick, onPointerEnter, onPointerLeave, ...props }: NmSidebarTriggerProps): ReactNode;
82
+ /** Holds the anchored trigger's place in a bar while the sidebar is closed, so the bar's content starts beside it. */
83
+ export declare function NmSidebarTriggerSpace({ className, ...props }: ComponentProps<'span'>): ReactNode;
76
84
  /** A thin strip on the sidebar's edge. Clicking it toggles the sidebar. */
77
85
  export declare function NmSidebarRail({ className, label, ...props }: ComponentProps<'button'> & {
78
86
  label?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nordmanai/nif",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "Nordman Interface Framework: the one UI and UX system for every Nordman product. Base UI, in the shadcn composition, styled by NIF tokens.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.13",
2
+ "version": "0.2.14",
3
3
  "versions": {
4
4
  "@animate-ui/react": "^2.4.2",
5
5
  "@base-ui/react": "^1.9.0",
@@ -171,6 +171,29 @@
171
171
  .nm-sidebar__trigger {
172
172
  flex-shrink: 0;
173
173
  }
174
+ /* Anchored: one toggle at the provider's top start corner, above the sidebar, that never moves. */
175
+ .nm-sidebar-provider > .nm-sidebar__trigger--anchored {
176
+ position: absolute;
177
+ top: var(--nm-space-12);
178
+ inset-inline-start: var(--nm-space-12);
179
+ z-index: calc(var(--nm-rail-z) + 1);
180
+ }
181
+ /* The header leaves the anchored toggle's room and lines its first row up with it. */
182
+ .nm-sidebar-provider:has(> .nm-sidebar__trigger--anchored) .nm-sidebar__header {
183
+ padding-block-start: var(--nm-space-12);
184
+ padding-inline-start: calc(var(--nm-space-12) + var(--nm-icon-control) + var(--nm-space-8));
185
+ min-height: calc(var(--nm-space-12) + var(--nm-icon-control) + var(--nm-space-8));
186
+ }
187
+ .nm-sidebar-provider:has(> .nm-sidebar__trigger--anchored) .nm-sidebar__header > .nm-sidebar__menu > .nm-sidebar__menu-item:first-child > .nm-sidebar__menu-button {
188
+ min-height: var(--nm-icon-control);
189
+ }
190
+ /* Holds the anchored toggle's place in a bar while the sidebar is closed. */
191
+ .nm-sidebar__trigger-space {
192
+ display: inline-block;
193
+ flex-shrink: 0;
194
+ width: var(--nm-icon-control);
195
+ height: var(--nm-icon-control);
196
+ }
174
197
  /* A header with the toggle in it is a row: the brand or switcher, then the toggle at the end. */
175
198
  .nm-sidebar__header:has(> .nm-sidebar__trigger) {
176
199
  flex-direction: row;
@@ -433,6 +456,9 @@
433
456
  padding-inline-end: var(--nm-icon-control);
434
457
  }
435
458
  .nm-sidebar__menu-item:has(> .nm-sidebar__menu-actions) > .nm-sidebar__menu-button {
459
+ padding-inline-end: var(--nm-icon-control);
460
+ }
461
+ .nm-sidebar__menu-item:has(> .nm-sidebar__menu-actions > :nth-child(2)) > .nm-sidebar__menu-button {
436
462
  padding-inline-end: calc(var(--nm-icon-control) * 2);
437
463
  }
438
464
  /* A group of actions at the end of a row. Its actions sit in flow inside it; the group takes the row's end. */
@@ -295,10 +295,16 @@ export type NmSidebarTriggerProps = Omit<ComponentProps<'button'>, 'aria-label'>
295
295
  icon?: NmIconId;
296
296
  /** On by default: a tooltip with the name and the ⌘B shortcut. */
297
297
  tooltip?: boolean;
298
+ /**
299
+ * Keeps the toggle at one spot of the provider whether the sidebar is open or closed: it is taken out of
300
+ * the flow and anchored at the top start corner, above the sidebar. The header leaves room for it, and
301
+ * `NmSidebarTriggerSpace` holds its place in a bar while the sidebar is closed.
302
+ */
303
+ anchored?: boolean;
298
304
  };
299
305
 
300
306
  /** The button that opens and closes the sidebar. In the main area's bar, or in the sidebar's own header. Resting on it peeks the sidebar. */
301
- export function NmSidebarTrigger({ className, label, icon = 'panel-left', tooltip = true, onClick, onPointerEnter, onPointerLeave, ...props }: NmSidebarTriggerProps): ReactNode {
307
+ export function NmSidebarTrigger({ className, label, icon = 'panel-left', tooltip = true, anchored = false, onClick, onPointerEnter, onPointerLeave, ...props }: NmSidebarTriggerProps): ReactNode {
302
308
  const { open, isMobile, toggleSidebar, peekIn, peekOut } = useSidebar();
303
309
  const name = label ?? (open || isMobile ? 'Close sidebar' : 'Open sidebar');
304
310
  const button = (
@@ -307,7 +313,8 @@ export function NmSidebarTrigger({ className, label, icon = 'panel-left', toolti
307
313
  glyph={icon}
308
314
  label={name}
309
315
  tone="quiet"
310
- className={nmClass('nm-sidebar__trigger', className)}
316
+ data-anchored={anchored ? 'true' : undefined}
317
+ className={nmClass('nm-sidebar__trigger', anchored ? 'nm-sidebar__trigger--anchored' : null, className)}
311
318
  onClick={(event) => {
312
319
  onClick?.(event);
313
320
  toggleSidebar();
@@ -337,6 +344,11 @@ export function NmSidebarTrigger({ className, label, icon = 'panel-left', toolti
337
344
  );
338
345
  }
339
346
 
347
+ /** Holds the anchored trigger's place in a bar while the sidebar is closed, so the bar's content starts beside it. */
348
+ export function NmSidebarTriggerSpace({ className, ...props }: ComponentProps<'span'>): ReactNode {
349
+ return <span aria-hidden="true" data-slot="sidebar-trigger-space" className={nmClass('nm-sidebar__trigger-space', className)} {...props} />;
350
+ }
351
+
340
352
  /** A thin strip on the sidebar's edge. Clicking it toggles the sidebar. */
341
353
  export function NmSidebarRail({ className, label = 'Toggle sidebar', ...props }: ComponentProps<'button'> & { label?: string }): ReactNode {
342
354
  const { toggleSidebar } = useSidebar();