@nordmanai/nif 0.2.5 → 0.2.9

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.
Files changed (70) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.js +6915 -6376
  3. package/dist/styles.css +1 -1
  4. package/dist/ui/components/nm-alert-dialog/nm-alert-dialog.d.ts +17 -0
  5. package/dist/ui/components/nm-dialog/nm-dialog.d.ts +4 -0
  6. package/dist/ui/components/nm-drawer/nm-drawer.d.ts +18 -0
  7. package/dist/ui/components/nm-sidebar/nm-sidebar.d.ts +134 -0
  8. package/dist/ui/config/nm-appearance.d.ts +13 -1
  9. package/dist/ui/config/nm-drawer.d.ts +3 -0
  10. package/dist/ui/config/nm-sidebar.d.ts +29 -0
  11. package/dist/ui/lib/appearance/appearanceState.d.ts +2 -1
  12. package/package.json +1 -1
  13. package/registry/index.json +212 -1
  14. package/registry/ui/components/nm-ai/nm-ai.css +3 -3
  15. package/registry/ui/components/nm-alert/nm-alert.css +1 -1
  16. package/registry/ui/components/nm-alert-dialog/nm-alert-dialog.css +4 -0
  17. package/registry/ui/components/nm-alert-dialog/nm-alert-dialog.tsx +43 -0
  18. package/registry/ui/components/nm-button/nm-button.css +2 -2
  19. package/registry/ui/components/nm-button-group/nm-button-group.css +1 -1
  20. package/registry/ui/components/nm-calendar/nm-calendar.css +1 -1
  21. package/registry/ui/components/nm-card/nm-card.css +2 -2
  22. package/registry/ui/components/nm-chatbox/nm-chatbox.css +1 -1
  23. package/registry/ui/components/nm-checkbox/nm-checkbox.css +2 -2
  24. package/registry/ui/components/nm-chip/nm-chip.css +1 -1
  25. package/registry/ui/components/nm-code-block/nm-code-block.css +1 -1
  26. package/registry/ui/components/nm-collection/nm-collection.css +2 -2
  27. package/registry/ui/components/nm-color-picker/nm-color-picker.css +1 -1
  28. package/registry/ui/components/nm-combobox/nm-combobox.css +2 -2
  29. package/registry/ui/components/nm-command/nm-command.css +1 -1
  30. package/registry/ui/components/nm-composer/nm-composer.css +3 -3
  31. package/registry/ui/components/nm-date-picker/nm-date-picker.css +2 -2
  32. package/registry/ui/components/nm-dialog/nm-dialog.css +16 -1
  33. package/registry/ui/components/nm-dialog/nm-dialog.tsx +8 -0
  34. package/registry/ui/components/nm-drawer/nm-drawer.css +70 -0
  35. package/registry/ui/components/nm-drawer/nm-drawer.tsx +41 -0
  36. package/registry/ui/components/nm-dropdown/nm-dropdown.css +2 -2
  37. package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.css +1 -1
  38. package/registry/ui/components/nm-field/nm-field.css +6 -6
  39. package/registry/ui/components/nm-hover-card/nm-hover-card.css +1 -1
  40. package/registry/ui/components/nm-input/nm-input.css +3 -3
  41. package/registry/ui/components/nm-input-group/nm-input-group.css +2 -2
  42. package/registry/ui/components/nm-message/nm-message.css +1 -1
  43. package/registry/ui/components/nm-native-select/nm-native-select.css +2 -2
  44. package/registry/ui/components/nm-popover/nm-popover.css +1 -1
  45. package/registry/ui/components/nm-prose/nm-prose.css +3 -3
  46. package/registry/ui/components/nm-questionnaire/nm-questionnaire.css +3 -3
  47. package/registry/ui/components/nm-radio-group/nm-radio-group.css +2 -2
  48. package/registry/ui/components/nm-segmented/nm-segmented.css +1 -1
  49. package/registry/ui/components/nm-select/nm-select.css +2 -2
  50. package/registry/ui/components/nm-separator/nm-separator.css +1 -1
  51. package/registry/ui/components/nm-side-panel/nm-side-panel.css +1 -1
  52. package/registry/ui/components/nm-sidebar/nm-sidebar.css +647 -0
  53. package/registry/ui/components/nm-sidebar/nm-sidebar.tsx +532 -0
  54. package/registry/ui/components/nm-spinner/nm-spinner.css +1 -1
  55. package/registry/ui/components/nm-switch/nm-switch.css +1 -1
  56. package/registry/ui/components/nm-table/nm-table.css +4 -4
  57. package/registry/ui/components/nm-tabs/nm-tabs.css +1 -1
  58. package/registry/ui/components/nm-textarea/nm-textarea.css +5 -5
  59. package/registry/ui/components/nm-toggle/nm-toggle.css +1 -1
  60. package/registry/ui/components/nordman-icon-button/nordman-icon-button.css +2 -2
  61. package/registry/ui/components/nordman-login/nordman-login.css +3 -3
  62. package/registry/ui/components/nordman-toggle/nordman-toggle.css +1 -1
  63. package/registry/ui/config/nm-appearance.ts +17 -0
  64. package/registry/ui/config/nm-drawer.ts +3 -0
  65. package/registry/ui/config/nm-sidebar.ts +37 -0
  66. package/registry/ui/lib/appearance/appearanceState.ts +8 -0
  67. package/registry/ui/lib/appearance/applyAppearance.ts +3 -1
  68. package/registry/ui/lib/appearance/deriveTokens.ts +2 -0
  69. package/registry/ui/styles/light-appearance.css +3 -3
  70. package/registry/ui/styles/tokens.css +31 -0
@@ -47,7 +47,7 @@
47
47
  .nm-login__error {
48
48
  margin: 0;
49
49
  color: var(--nm-fg);
50
- border: var(--nm-rule) solid var(--nm-line-strong);
50
+ border: var(--nm-rule) solid var(--nm-border-strong);
51
51
  border-radius: var(--nm-control-r);
52
52
  padding: var(--control-px);
53
53
  font-size: var(--control-fs);
@@ -89,7 +89,7 @@
89
89
  width: 100%;
90
90
  height: var(--nm-field-h);
91
91
  padding: 0 var(--control-px);
92
- border: var(--nm-rule) solid var(--nm-line-strong);
92
+ border: var(--nm-rule) solid var(--nm-border-strong);
93
93
  border-radius: var(--nm-control-r);
94
94
  background: var(--nm-raised);
95
95
  color: var(--nm-fg);
@@ -98,7 +98,7 @@
98
98
  }
99
99
 
100
100
  .nm-login__control:focus {
101
- border-color: var(--nm-stroke);
101
+ border-color: var(--nm-border-stroke);
102
102
  outline: none;
103
103
  }
104
104
 
@@ -6,7 +6,7 @@
6
6
  max-width: 100%;
7
7
  overflow-x: auto;
8
8
  padding: var(--toggle-pad);
9
- border: var(--nm-rule) solid var(--nm-line-strong);
9
+ border: var(--nm-rule) solid var(--nm-border-strong);
10
10
  border-radius: var(--toggle-r);
11
11
  }
12
12
 
@@ -55,6 +55,21 @@ export const NM_UI_SPACE_PERCENT = {
55
55
  default: 100,
56
56
  } as const;
57
57
 
58
+ /**
59
+ * How visible the borders are. Every border colour in the kit is mixed through one strength, so default is the kit as
60
+ * drawn, subtle is barely there, and none removes them. Geometry does not change: the border turns transparent and keeps
61
+ * its width. Fills and tracks that share the line colours are untouched, and so are state borders: focus, selection, checked and
62
+ * error keep their colour.
63
+ */
64
+ export const NM_BORDER_STYLES = ['default', 'subtle', 'none'] as const;
65
+ export type NmBorderStyle = (typeof NM_BORDER_STYLES)[number];
66
+ export const NM_BORDER_STRENGTH: Record<NmBorderStyle, string> = {
67
+ default: '100%',
68
+ subtle: '35%',
69
+ none: '0%',
70
+ };
71
+ /** Set on the root beside the tokens, so a product can style a state without the appearance script: `:root[data-nm-borders="none"]`. */
72
+ export const NM_BORDER_ATTRIBUTE = 'data-nm-borders' as const;
58
73
  export const NM_APPEARANCE_CONTRAST = {
59
74
  min: 0,
60
75
  max: 100,
@@ -183,6 +198,7 @@ export const NM_APPEARANCE_DEFAULTS = {
183
198
  uiRadiusPercent: NM_UI_RADIUS_PERCENT.default,
184
199
  uiSpacePercent: NM_UI_SPACE_PERCENT.default,
185
200
  contrast: NM_APPEARANCE_CONTRAST.default,
201
+ borders: 'default' as NmBorderStyle,
186
202
  } as const;
187
203
 
188
204
  export const NM_APPEARANCE_CSS_VARS = [
@@ -241,6 +257,7 @@ export const NM_APPEARANCE_CSS_VARS = [
241
257
  '--nm-ui-chip-min-height',
242
258
  '--nm-radius-scale',
243
259
  '--nm-space-scale',
260
+ '--nm-border-strength',
244
261
  '--text-primary',
245
262
  '--text-secondary',
246
263
  '--text-tertiary',
@@ -0,0 +1,3 @@
1
+ /** The edge a drawer slides in from. */
2
+ export const NM_DRAWER_SIDES = ['left', 'right'] as const;
3
+ export type NmDrawerSide = (typeof NM_DRAWER_SIDES)[number];
@@ -0,0 +1,37 @@
1
+ /** Which edge of the view the sidebar sits on. */
2
+ export const NM_SIDEBAR_SIDES = ['left', 'right'] as const;
3
+ export type NmSidebarSide = (typeof NM_SIDEBAR_SIDES)[number];
4
+
5
+ /** `sidebar` is flush with the edge. `floating` is a raised card inside a margin. `inset` sits in a margin and the main area is the raised card. */
6
+ export const NM_SIDEBAR_VARIANTS = ['sidebar', 'floating', 'inset'] as const;
7
+ export type NmSidebarVariant = (typeof NM_SIDEBAR_VARIANTS)[number];
8
+
9
+ /**
10
+ * How the sidebar collapses.
11
+ * `offcanvas` slides out of view; the trigger lives in the main area.
12
+ * `icon` keeps a column of icons, one per row.
13
+ * `toggle` keeps only the toggle button, in the sidebar's own header.
14
+ * `none` never collapses.
15
+ */
16
+ export const NM_SIDEBAR_COLLAPSIBLE = ['offcanvas', 'icon', 'toggle', 'none'] as const;
17
+ export type NmSidebarCollapsible = (typeof NM_SIDEBAR_COLLAPSIBLE)[number];
18
+
19
+ export const NM_SIDEBAR_STATES = ['expanded', 'collapsed'] as const;
20
+ export type NmSidebarState = (typeof NM_SIDEBAR_STATES)[number];
21
+
22
+ /** Row heights of a menu button: the small, default and large control heights. */
23
+ export const NM_SIDEBAR_BUTTON_SIZES = ['sm', 'default', 'lg'] as const;
24
+ export type NmSidebarButtonSize = (typeof NM_SIDEBAR_BUTTON_SIZES)[number];
25
+
26
+ /** `default` is a quiet row that fills on hover. `outline` draws the row's line and raises it. */
27
+ export const NM_SIDEBAR_BUTTON_VARIANTS = ['default', 'outline'] as const;
28
+ export type NmSidebarButtonVariant = (typeof NM_SIDEBAR_BUTTON_VARIANTS)[number];
29
+
30
+ /** The key that toggles the sidebar with the platform modifier: ⌘B on Mac, Ctrl+B elsewhere. */
31
+ export const NM_SIDEBAR_SHORTCUT = 'b';
32
+
33
+ /** How long the pointer may be between the toggle and the peeked sidebar before the peek closes, in ms. */
34
+ export const NM_SIDEBAR_PEEK_LEAVE_MS = 200;
35
+
36
+ /** Below this width the sidebar opens over the page instead of beside it. The same breakpoint as the tokens' phone step. */
37
+ export const NM_SIDEBAR_MOBILE_QUERY = '(max-width: 48rem)';
@@ -4,6 +4,7 @@ import {
4
4
  NM_APPEARANCE_DEFAULTS,
5
5
  NM_APPEARANCE_MODES,
6
6
  NM_APPEARANCE_STORAGE_KEY,
7
+ NM_BORDER_STYLES,
7
8
  NM_UI_FONT_SIZE_PX,
8
9
  NM_UI_FONT_WEIGHT,
9
10
  NM_UI_ICON_SIZE_PX,
@@ -12,6 +13,7 @@ import {
12
13
  findThemePreset,
13
14
  type NmAccentPreset,
14
15
  type NmAppearanceMode,
16
+ type NmBorderStyle,
15
17
  } from '../../config/nm-appearance.ts';
16
18
  import { normalizeHexColor } from './color.ts';
17
19
 
@@ -28,6 +30,7 @@ export type NmAppearanceState = {
28
30
  uiRadiusPercent: number;
29
31
  uiSpacePercent: number;
30
32
  contrast: number;
33
+ borders: NmBorderStyle;
31
34
  };
32
35
 
33
36
  export { NM_APPEARANCE_STORAGE_KEY };
@@ -36,6 +39,9 @@ function isMode(value: unknown): value is NmAppearanceMode {
36
39
  return typeof value === 'string' && (NM_APPEARANCE_MODES as readonly string[]).includes(value);
37
40
  }
38
41
 
42
+ function isBorderStyle(value: unknown): value is NmBorderStyle {
43
+ return typeof value === 'string' && (NM_BORDER_STYLES as readonly string[]).includes(value);
44
+ }
39
45
  function isAccentPreset(value: unknown): value is NmAccentPreset {
40
46
  return typeof value === 'string' && (NM_ACCENT_PRESETS as readonly string[]).includes(value);
41
47
  }
@@ -82,6 +88,7 @@ export function createDefaultAppearanceState(): NmAppearanceState {
82
88
  uiRadiusPercent: NM_APPEARANCE_DEFAULTS.uiRadiusPercent,
83
89
  uiSpacePercent: NM_APPEARANCE_DEFAULTS.uiSpacePercent,
84
90
  contrast: NM_APPEARANCE_CONTRAST.default,
91
+ borders: NM_APPEARANCE_DEFAULTS.borders,
85
92
  };
86
93
  return applyThemePresetPalette(base);
87
94
  }
@@ -185,6 +192,7 @@ export function parseAppearanceState(raw: unknown): NmAppearanceState {
185
192
  NM_APPEARANCE_CONTRAST.max,
186
193
  defaults.contrast,
187
194
  ),
195
+ borders: isBorderStyle(record.borders) ? record.borders : defaults.borders,
188
196
  };
189
197
  }
190
198
 
@@ -1,5 +1,5 @@
1
1
  import type { NmAppearanceState } from './appearanceState.ts';
2
- import { NM_APPEARANCE_APPLIED_EVENT, NM_APPEARANCE_CSS_VARS } from '../../config/nm-appearance.ts';
2
+ import { NM_APPEARANCE_APPLIED_EVENT, NM_APPEARANCE_CSS_VARS, NM_BORDER_ATTRIBUTE } from '../../config/nm-appearance.ts';
3
3
  import { resolveAppearanceScheme } from './appearanceState.ts';
4
4
  import { deriveAppearanceTokens } from './deriveTokens.ts';
5
5
  import { createLogger } from '../../kit-logger.ts';
@@ -17,6 +17,7 @@ export function clearAppliedAppearance(root: HTMLElement = document.documentElem
17
17
  NM_APPEARANCE_CSS_VARS.forEach((property) => {
18
18
  root.style.removeProperty(property);
19
19
  });
20
+ root.removeAttribute(NM_BORDER_ATTRIBUTE);
20
21
  }
21
22
 
22
23
  export function applyAppearanceState(
@@ -29,6 +30,7 @@ export function applyAppearanceState(
29
30
  Object.entries(tokens).forEach(([property, value]) => {
30
31
  root.style.setProperty(property, value);
31
32
  });
33
+ root.setAttribute(NM_BORDER_ATTRIBUTE, state.borders);
32
34
  if (typeof window !== 'undefined') {
33
35
  window.dispatchEvent(new CustomEvent(NM_APPEARANCE_APPLIED_EVENT));
34
36
  }
@@ -2,6 +2,7 @@ import type { NmAppearanceState } from './appearanceState.ts';
2
2
  import {
3
3
  NM_ACCENT_HEX,
4
4
  NM_APPEARANCE_CONTRAST,
5
+ NM_BORDER_STRENGTH,
5
6
  NM_THEME_PRESETS,
6
7
  NM_UI_FONT_SIZE_PX,
7
8
  NM_UI_FONT_WEIGHT,
@@ -205,6 +206,7 @@ export function deriveAppearanceTokens(
205
206
  ...deriveUiControlTokens(state.uiFontSizePx, state.uiIconSizePx),
206
207
  ...deriveRadiusScale(state.uiRadiusPercent),
207
208
  ...deriveSpaceScale(state.uiSpacePercent),
209
+ '--nm-border-strength': NM_BORDER_STRENGTH[state.borders],
208
210
  };
209
211
 
210
212
  return {
@@ -1,10 +1,10 @@
1
1
  html.light .nm-panel-bar {
2
- border-bottom-color: var(--nm-line);
2
+ border-bottom-color: var(--nm-border);
3
3
  }
4
4
 
5
5
  html.light .nm-collection__stage-bar {
6
- border-bottom-color: var(--nm-line);
7
- border-left-color: var(--nm-line);
6
+ border-bottom-color: var(--nm-border);
7
+ border-left-color: var(--nm-border);
8
8
  }
9
9
 
10
10
  html.light .nm-list-item:not(.nm-list-item--face) {
@@ -205,8 +205,17 @@
205
205
  --nm-width-tile: 9rem;
206
206
  --nm-width-panel-min: 16rem;
207
207
  --nm-width-panel-max: 80%;
208
+ /* The sidebar beside the main area: open, on a phone, and collapsed to icons (a square row inside the group padding). */
209
+ --nm-width-sidebar: 16rem;
210
+ --nm-width-sidebar-mobile: 18rem;
211
+ /* A drawer over the page from an edge. */
212
+ --nm-width-drawer: 20rem;
213
+ --nm-width-sidebar-icon: calc(var(--control-h) + var(--nm-space-8) * 2);
208
214
  --nm-height-workspace-sm: 20rem;
209
215
  --nm-height-workspace-lg: 36rem;
216
+ /* A sidebar shown inside a page. */
217
+ --nm-height-sidebar-sm: 26rem;
218
+ --nm-height-sidebar-lg: 42rem;
210
219
  /* Typography. Line height, tracking and weight come from here. The typeface itself is in assets/tokens.css. */
211
220
  /* Structural dividers and resize handles. Invisible at Contrast 0, and they appear as Contrast rises. */
212
221
  --nm-divider: var(--nm-canvas);
@@ -268,6 +277,7 @@
268
277
  --nm-code-gutter: 3ch;
269
278
  --nm-width-date: 11rem;
270
279
  --nm-width-dialog: 40rem;
280
+ --nm-width-alert-dialog: 26rem;
271
281
  /* A page column, such as a settings page: a share of the view, never narrower or wider than its bounds. */
272
282
  --nm-width-column: 90%;
273
283
  --nm-width-column-min: 20rem;
@@ -311,6 +321,18 @@
311
321
  --nm-knot-pulse: 3.2s;
312
322
  --nm-knot-pulse-min: 0.4;
313
323
  --nm-rule: 1px;
324
+ /* Borders. Every border colour is one of the line colours mixed through one strength, so a product can turn its
325
+ borders subtle or off in one place while the fills and tracks that share those colours keep theirs. The border
326
+ keeps its width and turns transparent, so nothing moves. State is not part of this: focus, selection, checked and error
327
+ borders keep the foreground or destructive colour, so a keyboard user and an active tab are never lost. */
328
+ --nm-border-strength: 100%;
329
+ --nm-border: color-mix(in srgb, var(--nm-line) var(--nm-border-strength), transparent);
330
+ --nm-border-strong: color-mix(in srgb, var(--nm-line-strong) var(--nm-border-strength), transparent);
331
+ --nm-border-stroke: color-mix(in srgb, var(--nm-stroke) var(--nm-border-strength), transparent);
332
+ --nm-border-divider: color-mix(in srgb, var(--nm-divider) var(--nm-border-strength), transparent);
333
+ /* A control whose only shape is its border (checkbox, radio) takes this fill, so it still has a shape with the
334
+ borders off. Transparent until then. */
335
+ --nm-borderless-fill: transparent;
314
336
  --nm-rule-dash: 4px;
315
337
  --nm-rule-gap: 4px;
316
338
  --nm-rule-pair: 2.5rem;
@@ -429,3 +451,12 @@ html.light {
429
451
  --nm-syntax-function: #6f42c1;
430
452
  --nm-syntax-constant: #005cc5;
431
453
  }
454
+
455
+ /* The border setting without the appearance script: set the attribute on the root. */
456
+ :root[data-nm-borders='subtle'] {
457
+ --nm-border-strength: 35%;
458
+ }
459
+ :root[data-nm-borders='none'] {
460
+ --nm-border-strength: 0%;
461
+ --nm-borderless-fill: var(--nm-inset);
462
+ }