@dbcdk/react-components 0.0.189 → 0.0.190

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 (41) hide show
  1. package/dist/components/accordion/Accordion.cjs +4 -8
  2. package/dist/components/accordion/Accordion.d.ts +1 -1
  3. package/dist/components/accordion/Accordion.js +4 -8
  4. package/dist/components/accordion/Accordion.module.css +55 -6
  5. package/dist/components/accordion/components/AccordionRow.cjs +2 -2
  6. package/dist/components/accordion/components/AccordionRow.d.ts +2 -2
  7. package/dist/components/accordion/components/AccordionRow.js +2 -2
  8. package/dist/components/accordion/components/AccordionRow.module.css +24 -2
  9. package/dist/components/breadcrumbs/Breadcrumbs.cjs +10 -7
  10. package/dist/components/breadcrumbs/Breadcrumbs.js +10 -7
  11. package/dist/components/breadcrumbs/Breadcrumbs.module.css +1 -5
  12. package/dist/components/button/Button.module.css +4 -2
  13. package/dist/components/chip/Chip.module.css +13 -0
  14. package/dist/components/forms/input/Input.module.css +2 -1
  15. package/dist/components/forms/input-container/InputContainer.d.ts +3 -3
  16. package/dist/components/nav-bar/NavBar.d.ts +1 -0
  17. package/dist/components/page-layout/PageLayout.module.css +8 -1
  18. package/dist/components/sidebar/components/SidebarItem.cjs +2 -0
  19. package/dist/components/sidebar/components/SidebarItem.d.ts +2 -1
  20. package/dist/components/sidebar/components/SidebarItem.js +2 -0
  21. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.cjs +4 -0
  22. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.d.ts +2 -1
  23. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +4 -0
  24. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.cjs +6 -1
  25. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.d.ts +2 -1
  26. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +6 -1
  27. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.module.css +14 -0
  28. package/dist/components/sidebar/components/sidebar-items/SidebarItems.cjs +13 -2
  29. package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +13 -2
  30. package/dist/components/table/Table.module.css +2 -4
  31. package/dist/components/table/Table.types.d.ts +1 -0
  32. package/dist/components/table/components/TableHeaderCell.cjs +1 -1
  33. package/dist/components/table/components/TableHeaderCell.js +1 -1
  34. package/dist/components/table/components/TableRow.cjs +1 -0
  35. package/dist/components/table/components/TableRow.js +1 -0
  36. package/dist/components/table/tanstackTable.utils.cjs +3 -2
  37. package/dist/components/table/tanstackTable.utils.js +3 -2
  38. package/dist/components/tabs/Tabs.module.css +13 -4
  39. package/dist/styles/styles.css +39 -3
  40. package/dist/styles.css +39 -3
  41. package/package.json +1 -1
@@ -23,7 +23,7 @@ function Accordion({
23
23
  items,
24
24
  mode = "single",
25
25
  size = "md",
26
- variant = "default",
26
+ variant = "filled",
27
27
  renderMode = "lazy",
28
28
  defaultOpenIndex = null,
29
29
  defaultOpenIndexes = [],
@@ -35,6 +35,7 @@ function Accordion({
35
35
  ...rest
36
36
  }) {
37
37
  const uid = react.useId();
38
+ const resolvedVariant = variant === "default" ? "filled" : variant;
38
39
  const isControlled = mode === "single" ? openIndex !== void 0 : openIndexes !== void 0;
39
40
  const [hasMounted, setHasMounted] = react.useState(false);
40
41
  react.useEffect(() => {
@@ -96,12 +97,7 @@ function Accordion({
96
97
  "div",
97
98
  {
98
99
  ...rest,
99
- className: [
100
- styles__default.default.container,
101
- styles__default.default[size],
102
- variant !== "default" ? styles__default.default[variant] : "",
103
- className
104
- ].filter(Boolean).join(" "),
100
+ className: [styles__default.default.container, styles__default.default[size], styles__default.default[resolvedVariant], className].filter(Boolean).join(" "),
105
101
  children: items.map((item, i) => {
106
102
  var _a;
107
103
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -114,7 +110,7 @@ function Accordion({
114
110
  onToggle: toggle,
115
111
  shouldAnimate: hasMounted,
116
112
  headlineSize: size === "sm" ? 4 : 3,
117
- variant,
113
+ variant: resolvedVariant,
118
114
  renderMode
119
115
  },
120
116
  (_a = item.id) != null ? _a : i
@@ -13,7 +13,7 @@ export interface AccordionItem {
13
13
  }
14
14
  type Size = 'sm' | 'md' | 'lg';
15
15
  type Mode = 'single' | 'multiple';
16
- type Variant = 'default' | 'outlined';
16
+ type Variant = 'filled' | 'outlined' | 'default';
17
17
  type OpenIndexes = number[] | 'all';
18
18
  type RenderMode = 'lazy' | 'eager';
19
19
  export interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
@@ -17,7 +17,7 @@ function Accordion({
17
17
  items,
18
18
  mode = "single",
19
19
  size = "md",
20
- variant = "default",
20
+ variant = "filled",
21
21
  renderMode = "lazy",
22
22
  defaultOpenIndex = null,
23
23
  defaultOpenIndexes = [],
@@ -29,6 +29,7 @@ function Accordion({
29
29
  ...rest
30
30
  }) {
31
31
  const uid = useId();
32
+ const resolvedVariant = variant === "default" ? "filled" : variant;
32
33
  const isControlled = mode === "single" ? openIndex !== void 0 : openIndexes !== void 0;
33
34
  const [hasMounted, setHasMounted] = useState(false);
34
35
  useEffect(() => {
@@ -90,12 +91,7 @@ function Accordion({
90
91
  "div",
91
92
  {
92
93
  ...rest,
93
- className: [
94
- styles.container,
95
- styles[size],
96
- variant !== "default" ? styles[variant] : "",
97
- className
98
- ].filter(Boolean).join(" "),
94
+ className: [styles.container, styles[size], styles[resolvedVariant], className].filter(Boolean).join(" "),
99
95
  children: items.map((item, i) => {
100
96
  var _a;
101
97
  return /* @__PURE__ */ jsx(
@@ -108,7 +104,7 @@ function Accordion({
108
104
  onToggle: toggle,
109
105
  shouldAnimate: hasMounted,
110
106
  headlineSize: size === "sm" ? 4 : 3,
111
- variant,
107
+ variant: resolvedVariant,
112
108
  renderMode
113
109
  },
114
110
  (_a = item.id) != null ? _a : i
@@ -1,41 +1,90 @@
1
1
  .container {
2
2
  border-radius: var(--border-radius-default);
3
- background-color: var(--color-bg-surface);
3
+ background-color: transparent;
4
4
  box-sizing: border-box;
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  overflow: hidden;
8
- gap: var(--spacing-xs);
8
+ gap: 0;
9
+ }
10
+
11
+ .filled {
12
+ --acc-item-bg: transparent;
13
+ --acc-trigger-bg: color-mix(
14
+ in srgb,
15
+ var(--color-bg-contextual-subtle) 66%,
16
+ var(--color-bg-surface)
17
+ );
18
+ --acc-trigger-bg-hover: color-mix(
19
+ in srgb,
20
+ var(--color-bg-contextual-subtle) 74%,
21
+ var(--color-bg-surface)
22
+ );
23
+ --acc-content-bg: var(--color-bg-surface);
24
+ --acc-item-separator: none;
25
+ --acc-item-gap: calc((var(--spacing-xxs) + var(--spacing-xs)) / 2);
26
+ --acc-item-radius: var(--border-radius-sm);
27
+ --acc-content-px: var(--acc-trigger-px);
28
+ --acc-content-open-pt: var(--spacing-2xs);
9
29
  }
10
30
 
11
31
  .outlined {
12
- background-color: transparent;
32
+ background-color: var(--color-bg-surface);
13
33
  border: 1px solid var(--color-border-subtle);
14
34
  border-radius: var(--border-radius-md);
15
35
  gap: 0;
36
+ --acc-item-bg: transparent;
37
+ --acc-content-bg: transparent;
38
+ --acc-item-gap: 0;
39
+ --acc-item-radius: 0;
16
40
  --acc-trigger-bg: transparent;
41
+ --acc-trigger-bg-hover: transparent;
17
42
  --acc-content-px: var(--acc-trigger-px);
18
43
  --acc-item-separator: 1px solid var(--color-border-subtle);
19
44
  }
20
45
 
21
46
  /* Size variables (consumed by AccordionRow) */
22
47
  .sm {
23
- --acc-trigger-py: var(--spacing-xs);
48
+ --acc-trigger-py: var(--spacing-xxs);
24
49
  --acc-trigger-px: var(--spacing-sm);
25
50
  --acc-content-py: var(--spacing-sm);
26
51
  --acc-font-size: var(--font-size-sm);
27
52
  }
28
53
 
29
54
  .md {
30
- --acc-trigger-py: var(--spacing-sm);
55
+ --acc-trigger-py: var(--spacing-xs);
31
56
  --acc-trigger-px: var(--spacing-md);
32
57
  --acc-content-py: var(--spacing-md);
33
58
  --acc-font-size: var(--font-size-md);
34
59
  }
35
60
 
36
61
  .lg {
37
- --acc-trigger-py: var(--spacing-md);
62
+ --acc-trigger-py: var(--spacing-sm);
38
63
  --acc-trigger-px: var(--spacing-md);
39
64
  --acc-content-py: var(--spacing-md);
40
65
  --acc-font-size: var(--font-size-md);
41
66
  }
67
+
68
+ .filled.sm {
69
+ --acc-trigger-py: var(--spacing-2xs);
70
+ }
71
+
72
+ .filled.md {
73
+ --acc-trigger-py: calc((var(--spacing-xs) + var(--spacing-xxs)) / 2);
74
+ }
75
+
76
+ .filled.lg {
77
+ --acc-trigger-py: calc((var(--spacing-sm) + var(--spacing-xs)) / 2);
78
+ }
79
+
80
+ .outlined.sm {
81
+ --acc-trigger-py: var(--spacing-xs);
82
+ }
83
+
84
+ .outlined.md {
85
+ --acc-trigger-py: var(--spacing-sm);
86
+ }
87
+
88
+ .outlined.lg {
89
+ --acc-trigger-py: var(--spacing-md);
90
+ }
@@ -19,11 +19,11 @@ function AccordionRow({
19
19
  onToggle,
20
20
  shouldAnimate = true,
21
21
  headlineSize = 4,
22
- variant = "default",
22
+ variant: _variant = "filled",
23
23
  renderMode = "lazy"
24
24
  }) {
25
25
  const isDisabled = !!item.disabled;
26
- const headlineWeight = variant === "outlined" ? 400 : 500;
26
+ const headlineWeight = 400;
27
27
  const buttonId = `${uid}-acc-btn-${index}`;
28
28
  const panelId = `${uid}-acc-panel-${index}`;
29
29
  const { innerRef, height, onTransitionEnd } = useCollapsibleHeight.useCollapsibleHeight(isOpen, shouldAnimate);
@@ -8,7 +8,7 @@ export type AccordionRowProps = {
8
8
  onToggle: (index: number) => void;
9
9
  shouldAnimate?: boolean;
10
10
  headlineSize?: 1 | 2 | 3 | 4 | 5 | 6;
11
- variant?: 'default' | 'outlined';
11
+ variant?: 'filled' | 'outlined' | 'default';
12
12
  renderMode?: 'lazy' | 'eager';
13
13
  };
14
- export declare function AccordionRow({ uid, index, item, isOpen, onToggle, shouldAnimate, headlineSize, variant, renderMode, }: AccordionRowProps): JSX.Element;
14
+ export declare function AccordionRow({ uid, index, item, isOpen, onToggle, shouldAnimate, headlineSize, variant: _variant, renderMode, }: AccordionRowProps): JSX.Element;
@@ -13,11 +13,11 @@ function AccordionRow({
13
13
  onToggle,
14
14
  shouldAnimate = true,
15
15
  headlineSize = 4,
16
- variant = "default",
16
+ variant: _variant = "filled",
17
17
  renderMode = "lazy"
18
18
  }) {
19
19
  const isDisabled = !!item.disabled;
20
- const headlineWeight = variant === "outlined" ? 400 : 500;
20
+ const headlineWeight = 400;
21
21
  const buttonId = `${uid}-acc-btn-${index}`;
22
22
  const panelId = `${uid}-acc-panel-${index}`;
23
23
  const { innerRef, height, onTransitionEnd } = useCollapsibleHeight(isOpen, shouldAnimate);
@@ -5,6 +5,15 @@
5
5
  background: var(--acc-trigger-bg, var(--color-bg-contextual-subtle));
6
6
  }
7
7
 
8
+ .item:not(.disabled):hover .headerRow {
9
+ background: var(--acc-trigger-bg-hover, var(--acc-trigger-bg, var(--color-bg-contextual-subtle)));
10
+ }
11
+
12
+ .item:not(.disabled):hover .title,
13
+ .item:not(.disabled):hover .chevron {
14
+ color: var(--color-fg-default);
15
+ }
16
+
8
17
  .trigger {
9
18
  all: unset;
10
19
  box-sizing: border-box;
@@ -75,9 +84,10 @@
75
84
  }
76
85
 
77
86
  .chevron {
78
- width: var(--icon-size-md);
79
- height: var(--icon-size-md);
87
+ width: var(--icon-size-sm);
88
+ height: var(--icon-size-sm);
80
89
  flex: 0 0 auto;
90
+ color: var(--color-fg-muted);
81
91
  transition: transform var(--transition-normal) var(--ease-standard);
82
92
  }
83
93
 
@@ -108,12 +118,24 @@
108
118
 
109
119
  .content {
110
120
  padding: var(--acc-content-py) var(--acc-content-px, 0);
121
+ background: var(--acc-content-bg, transparent);
122
+ }
123
+
124
+ .item[data-state='open'] .content {
125
+ padding-top: var(--acc-content-open-pt, var(--acc-content-py));
111
126
  }
112
127
 
113
128
  .item {
129
+ background: var(--acc-item-bg, transparent);
130
+ border-radius: var(--acc-item-radius, 0);
131
+ overflow: hidden;
114
132
  border-bottom: var(--acc-item-separator, none);
115
133
  }
116
134
 
135
+ .item + .item {
136
+ margin-top: var(--acc-item-gap, 0);
137
+ }
138
+
117
139
  :global(.outlined) .item[data-state='open'] .headerRow {
118
140
  box-shadow: inset 3px 0 0 var(--color-border-selected);
119
141
  }
@@ -12,13 +12,16 @@ function Breadcrumbs({
12
12
  items,
13
13
  ...navProps
14
14
  }) {
15
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: styles__default.default.breadcrumbs, "aria-label": "breadcrumb", ...navProps, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
16
- /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
17
- item.icon && item.icon,
18
- item.onClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: item.onClick, children: item.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label })
19
- ] }),
20
- index < items.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.separator, children: "/" })
21
- ] }, `breadcrumbItem-${item.label}-${index}`)) }) });
15
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: styles__default.default.breadcrumbs, "aria-label": "breadcrumb", ...navProps, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((item, index) => {
16
+ const isCurrent = index === items.length - 1;
17
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
18
+ /* @__PURE__ */ jsxRuntime.jsxs("li", { "aria-current": isCurrent ? "page" : void 0, children: [
19
+ item.icon && item.icon,
20
+ item.onClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: item.onClick, children: item.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label })
21
+ ] }),
22
+ index < items.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.separator, children: "/" })
23
+ ] }, `breadcrumbItem-${item.label}-${index}`);
24
+ }) }) });
22
25
  }
23
26
 
24
27
  exports.Breadcrumbs = Breadcrumbs;
@@ -6,13 +6,16 @@ function Breadcrumbs({
6
6
  items,
7
7
  ...navProps
8
8
  }) {
9
- return /* @__PURE__ */ jsx("nav", { className: styles.breadcrumbs, "aria-label": "breadcrumb", ...navProps, children: /* @__PURE__ */ jsx("ul", { children: items.map((item, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
10
- /* @__PURE__ */ jsxs("li", { children: [
11
- item.icon && item.icon,
12
- item.onClick ? /* @__PURE__ */ jsx("button", { onClick: item.onClick, children: item.label }) : /* @__PURE__ */ jsx("span", { children: item.label })
13
- ] }),
14
- index < items.length - 1 && /* @__PURE__ */ jsx("span", { className: styles.separator, children: "/" })
15
- ] }, `breadcrumbItem-${item.label}-${index}`)) }) });
9
+ return /* @__PURE__ */ jsx("nav", { className: styles.breadcrumbs, "aria-label": "breadcrumb", ...navProps, children: /* @__PURE__ */ jsx("ul", { children: items.map((item, index) => {
10
+ const isCurrent = index === items.length - 1;
11
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
12
+ /* @__PURE__ */ jsxs("li", { "aria-current": isCurrent ? "page" : void 0, children: [
13
+ item.icon && item.icon,
14
+ item.onClick ? /* @__PURE__ */ jsx("button", { onClick: item.onClick, children: item.label }) : /* @__PURE__ */ jsx("span", { children: item.label })
15
+ ] }),
16
+ index < items.length - 1 && /* @__PURE__ */ jsx("span", { className: styles.separator, children: "/" })
17
+ ] }, `breadcrumbItem-${item.label}-${index}`);
18
+ }) }) });
16
19
  }
17
20
 
18
21
  export { Breadcrumbs };
@@ -34,12 +34,8 @@
34
34
  .breadcrumbs li[aria-current='page'],
35
35
  .breadcrumbs li:last-of-type {
36
36
  color: var(--color-fg-default);
37
- cursor: default;
38
- }
39
-
40
- .breadcrumbs li[aria-current='page'] button,
41
- .breadcrumbs li:last-of-type button {
42
37
  font-weight: var(--font-weight-medium);
38
+ cursor: default;
43
39
  }
44
40
 
45
41
  .separator {
@@ -259,7 +259,8 @@
259
259
  }
260
260
 
261
261
  .header:hover {
262
- background-color: color-mix(in srgb, var(--color-navbar-fg) 12%, transparent);
262
+ background-color: transparent;
263
+ border-color: var(--color-navbar-fg);
263
264
  }
264
265
 
265
266
  .header:focus-visible {
@@ -275,7 +276,8 @@
275
276
  }
276
277
 
277
278
  .header.active:hover {
278
- background-color: color-mix(in srgb, var(--color-navbar-fg) 22%, transparent);
279
+ background-color: color-mix(in srgb, var(--color-navbar-fg) 16%, transparent);
280
+ border-color: var(--color-navbar-fg);
279
281
  }
280
282
 
281
283
  .button.xs {
@@ -24,6 +24,10 @@
24
24
  transform var(--transition-fast) var(--ease-standard);
25
25
  }
26
26
 
27
+ .hasClose {
28
+ gap: var(--spacing-2xs);
29
+ }
30
+
27
31
  .container:focus-visible {
28
32
  outline: none;
29
33
  }
@@ -120,6 +124,15 @@
120
124
  box-shadow: none;
121
125
  }
122
126
 
127
+ .neutral .close {
128
+ color: var(--color-fg-subtle);
129
+ }
130
+
131
+ .neutral .close:hover,
132
+ .neutral .close:focus-visible {
133
+ color: var(--color-fg-default);
134
+ }
135
+
123
136
  .success {
124
137
  --chip-bg: var(--color-status-success-bg);
125
138
  --chip-fg: var(--color-status-success-fg);
@@ -191,7 +191,8 @@
191
191
  }
192
192
 
193
193
  .header:hover:not([aria-disabled='true']) {
194
- background-color: color-mix(in srgb, var(--color-navbar-fg) 8%, transparent);
194
+ background-color: transparent;
195
+ border-color: var(--color-navbar-fg);
195
196
  }
196
197
 
197
198
  .header:focus-within:not([aria-disabled='true']) {
@@ -3,9 +3,9 @@ export interface InputContainerProps {
3
3
  label?: string;
4
4
  labelAction?: React.ReactNode;
5
5
  htmlFor?: string;
6
- error?: string;
7
- helpText?: string;
8
- helpTextAddition?: string;
6
+ error?: React.ReactNode;
7
+ helpText?: React.ReactNode;
8
+ helpTextAddition?: React.ReactNode;
9
9
  fullWidth?: boolean;
10
10
  required?: boolean;
11
11
  children: React.ReactNode;
@@ -4,6 +4,7 @@ export type NavBarItem = NavBarLinkItem | NavBarExpandableItem | NavBarGroupItem
4
4
  type NavBarBase = {
5
5
  label: string;
6
6
  icon?: ReactNode;
7
+ badge?: number | string;
7
8
  iconWidth?: string | number;
8
9
  enabled?: boolean;
9
10
  tags?: string[];
@@ -16,6 +16,9 @@
16
16
  --page-layout-banner-height: calc(
17
17
  var(--spacing-2xs) * 2 + var(--font-size-md) * var(--line-height-normal)
18
18
  );
19
+
20
+ /* Structural bottom breathing room for all page content. */
21
+ --page-layout-content-padding-bottom: var(--spacing-2xl);
19
22
  }
20
23
 
21
24
  /* Viewport handling:
@@ -215,7 +218,11 @@
215
218
  align-items: center;
216
219
 
217
220
  background: var(--color-bg-surface);
218
- padding: var(--spacing-md);
221
+ padding-block-start: var(--spacing-md);
222
+ padding-inline: var(--spacing-md);
223
+ padding-block-end: calc(
224
+ var(--page-layout-content-padding-bottom) + env(safe-area-inset-bottom, 0px)
225
+ );
219
226
  overflow: visible;
220
227
  }
221
228
 
@@ -7,6 +7,7 @@ function SidebarItem({
7
7
  component: Component,
8
8
  label,
9
9
  icon,
10
+ badge,
10
11
  href,
11
12
  iconWidth,
12
13
  truncateLabel
@@ -18,6 +19,7 @@ function SidebarItem({
18
19
  SidebarItemContent.SidebarItemContent,
19
20
  {
20
21
  icon,
22
+ badge,
21
23
  iconWidth,
22
24
  label,
23
25
  href,
@@ -3,9 +3,10 @@ interface SidebarItemProps {
3
3
  component?: React.ElementType;
4
4
  label: string;
5
5
  icon: React.ReactNode;
6
+ badge?: number | string;
6
7
  href?: string;
7
8
  iconWidth?: string | number;
8
9
  truncateLabel?: boolean;
9
10
  }
10
- export declare function SidebarItem({ component: Component, label, icon, href, iconWidth, truncateLabel, }: SidebarItemProps): React.ReactNode;
11
+ export declare function SidebarItem({ component: Component, label, icon, badge, href, iconWidth, truncateLabel, }: SidebarItemProps): React.ReactNode;
11
12
  export {};
@@ -5,6 +5,7 @@ function SidebarItem({
5
5
  component: Component,
6
6
  label,
7
7
  icon,
8
+ badge,
8
9
  href,
9
10
  iconWidth,
10
11
  truncateLabel
@@ -16,6 +17,7 @@ function SidebarItem({
16
17
  SidebarItemContent,
17
18
  {
18
19
  icon,
20
+ badge,
19
21
  iconWidth,
20
22
  label,
21
23
  href,
@@ -21,6 +21,7 @@ function ExpandableSidebarItem({
21
21
  items,
22
22
  label,
23
23
  icon,
24
+ badge,
24
25
  component: Component,
25
26
  href,
26
27
  iconWidth,
@@ -85,6 +86,7 @@ function ExpandableSidebarItem({
85
86
  items: (_b = item.children) != null ? _b : [],
86
87
  label: item.label,
87
88
  icon: item.icon,
89
+ badge: item.badge,
88
90
  href: item.href,
89
91
  iconWidth: item.iconWidth,
90
92
  component: item.component
@@ -98,6 +100,7 @@ function ExpandableSidebarItem({
98
100
  component: item.component,
99
101
  label: item.label,
100
102
  icon: item.icon,
103
+ badge: item.badge,
101
104
  href: item.href,
102
105
  iconWidth: item.iconWidth,
103
106
  truncateLabel: item.truncateLabel
@@ -112,6 +115,7 @@ function ExpandableSidebarItem({
112
115
  {
113
116
  headerStyle: expanded,
114
117
  icon,
118
+ badge,
115
119
  iconWidth,
116
120
  label,
117
121
  href,
@@ -5,9 +5,10 @@ type ExpandableSidebarItemProps = {
5
5
  label: string;
6
6
  component: React.ElementType;
7
7
  icon: React.ReactNode;
8
+ badge?: number | string;
8
9
  href: string;
9
10
  iconWidth?: string | number;
10
11
  truncateLabel?: boolean;
11
12
  };
12
- export declare function ExpandableSidebarItem({ items, label, icon, component: Component, href, iconWidth, truncateLabel, }: ExpandableSidebarItemProps): React.ReactNode;
13
+ export declare function ExpandableSidebarItem({ items, label, icon, badge, component: Component, href, iconWidth, truncateLabel, }: ExpandableSidebarItemProps): React.ReactNode;
13
14
  export {};
@@ -15,6 +15,7 @@ function ExpandableSidebarItem({
15
15
  items,
16
16
  label,
17
17
  icon,
18
+ badge,
18
19
  component: Component,
19
20
  href,
20
21
  iconWidth,
@@ -79,6 +80,7 @@ function ExpandableSidebarItem({
79
80
  items: (_b = item.children) != null ? _b : [],
80
81
  label: item.label,
81
82
  icon: item.icon,
83
+ badge: item.badge,
82
84
  href: item.href,
83
85
  iconWidth: item.iconWidth,
84
86
  component: item.component
@@ -92,6 +94,7 @@ function ExpandableSidebarItem({
92
94
  component: item.component,
93
95
  label: item.label,
94
96
  icon: item.icon,
97
+ badge: item.badge,
95
98
  href: item.href,
96
99
  iconWidth: item.iconWidth,
97
100
  truncateLabel: item.truncateLabel
@@ -106,6 +109,7 @@ function ExpandableSidebarItem({
106
109
  {
107
110
  headerStyle: expanded,
108
111
  icon,
112
+ badge,
109
113
  iconWidth,
110
114
  label,
111
115
  href,
@@ -5,6 +5,7 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
  var React = require('react');
6
6
  var getHighlightedSegments = require('../../../../utils/text/get-highlighted-segments');
7
7
  var styles = require('./SidebarItemContent.module.css');
8
+ var Chip = require('../../../chip/Chip');
8
9
  var SidebarProvider = require('../../providers/SidebarProvider');
9
10
 
10
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -15,6 +16,7 @@ var styles__default = /*#__PURE__*/_interopDefault(styles);
15
16
  function SidebarItemContent({
16
17
  icon,
17
18
  label,
19
+ badge,
18
20
  suffixIcon,
19
21
  href,
20
22
  iconWidth,
@@ -45,7 +47,10 @@ function SidebarItemContent({
45
47
  }
46
48
  )
47
49
  ] }),
48
- suffixIcon && !isSidebarCollapsed && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.suffixIcon, children: suffixIcon })
50
+ !isSidebarCollapsed && (badge != null || suffixIcon) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.trailing, children: [
51
+ badge != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badge, children: /* @__PURE__ */ jsxRuntime.jsx(Chip.Chip, { size: "sm", children: typeof badge === "number" ? badge.toLocaleString("da-DK") : badge }) }) : null,
52
+ suffixIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.suffixIcon, children: suffixIcon }) : null
53
+ ] }) : null
49
54
  ]
50
55
  }
51
56
  );
@@ -3,6 +3,7 @@ import type { JSX } from 'react';
3
3
  export interface SidebarItemContentProps {
4
4
  icon?: React.ReactNode;
5
5
  label: React.ReactNode;
6
+ badge?: number | string;
6
7
  suffixIcon?: React.ReactNode;
7
8
  href?: string;
8
9
  iconWidth?: string | number;
@@ -10,4 +11,4 @@ export interface SidebarItemContentProps {
10
11
  headerStyle?: boolean;
11
12
  truncateLabel?: boolean;
12
13
  }
13
- export declare function SidebarItemContent({ icon, label, suffixIcon, href, iconWidth, disableActiveStyles, headerStyle, truncateLabel, }: SidebarItemContentProps): JSX.Element;
14
+ export declare function SidebarItemContent({ icon, label, badge, suffixIcon, href, iconWidth, disableActiveStyles, headerStyle, truncateLabel, }: SidebarItemContentProps): JSX.Element;
@@ -3,11 +3,13 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React from 'react';
4
4
  import { getHighlightedSegments } from '../../../../utils/text/get-highlighted-segments';
5
5
  import styles from './SidebarItemContent.module.css';
6
+ import { Chip } from '../../../chip/Chip';
6
7
  import { useSidebar } from '../../providers/SidebarProvider';
7
8
 
8
9
  function SidebarItemContent({
9
10
  icon,
10
11
  label,
12
+ badge,
11
13
  suffixIcon,
12
14
  href,
13
15
  iconWidth,
@@ -38,7 +40,10 @@ function SidebarItemContent({
38
40
  }
39
41
  )
40
42
  ] }),
41
- suffixIcon && !isSidebarCollapsed && /* @__PURE__ */ jsx("span", { className: styles.suffixIcon, children: suffixIcon })
43
+ !isSidebarCollapsed && (badge != null || suffixIcon) ? /* @__PURE__ */ jsxs("span", { className: styles.trailing, children: [
44
+ badge != null ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: typeof badge === "number" ? badge.toLocaleString("da-DK") : badge }) }) : null,
45
+ suffixIcon ? /* @__PURE__ */ jsx("span", { className: styles.suffixIcon, children: suffixIcon }) : null
46
+ ] }) : null
42
47
  ]
43
48
  }
44
49
  );
@@ -87,6 +87,20 @@
87
87
  color: inherit;
88
88
  }
89
89
 
90
+ .trailing {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ gap: var(--spacing-xs);
94
+ flex: 0 0 auto;
95
+ margin-inline-start: auto;
96
+ min-inline-size: 0;
97
+ }
98
+
99
+ .badge {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ }
103
+
90
104
  .collapsed svg {
91
105
  inline-size: var(--icon-size-md);
92
106
  block-size: var(--icon-size-md);
@@ -26,13 +26,23 @@ function SidebarItems({ activeLink }) {
26
26
  ] }, key);
27
27
  }
28
28
  if (item.type === "expandable") {
29
- const { component: Component2, label: label2, icon: icon2, children, href: href2, iconWidth: iconWidth2, truncateLabel: truncateLabel2 } = item;
29
+ const {
30
+ component: Component2,
31
+ label: label2,
32
+ icon: icon2,
33
+ badge: badge2,
34
+ children,
35
+ href: href2,
36
+ iconWidth: iconWidth2,
37
+ truncateLabel: truncateLabel2
38
+ } = item;
30
39
  return /* @__PURE__ */ jsxRuntime.jsx(
31
40
  ExpandableSidebarItem.ExpandableSidebarItem,
32
41
  {
33
42
  items: children,
34
43
  label: label2,
35
44
  icon: icon2,
45
+ badge: badge2,
36
46
  href: href2,
37
47
  iconWidth: iconWidth2,
38
48
  truncateLabel: truncateLabel2,
@@ -41,13 +51,14 @@ function SidebarItems({ activeLink }) {
41
51
  key
42
52
  );
43
53
  }
44
- const { component: Component, label, icon, href, iconWidth, truncateLabel } = item;
54
+ const { component: Component, label, icon, badge, href, iconWidth, truncateLabel } = item;
45
55
  return /* @__PURE__ */ jsxRuntime.jsx(
46
56
  SidebarItem.SidebarItem,
47
57
  {
48
58
  component: Component,
49
59
  label,
50
60
  icon,
61
+ badge,
51
62
  href,
52
63
  iconWidth,
53
64
  truncateLabel
@@ -20,13 +20,23 @@ function SidebarItems({ activeLink }) {
20
20
  ] }, key);
21
21
  }
22
22
  if (item.type === "expandable") {
23
- const { component: Component2, label: label2, icon: icon2, children, href: href2, iconWidth: iconWidth2, truncateLabel: truncateLabel2 } = item;
23
+ const {
24
+ component: Component2,
25
+ label: label2,
26
+ icon: icon2,
27
+ badge: badge2,
28
+ children,
29
+ href: href2,
30
+ iconWidth: iconWidth2,
31
+ truncateLabel: truncateLabel2
32
+ } = item;
24
33
  return /* @__PURE__ */ jsx(
25
34
  ExpandableSidebarItem,
26
35
  {
27
36
  items: children,
28
37
  label: label2,
29
38
  icon: icon2,
39
+ badge: badge2,
30
40
  href: href2,
31
41
  iconWidth: iconWidth2,
32
42
  truncateLabel: truncateLabel2,
@@ -35,13 +45,14 @@ function SidebarItems({ activeLink }) {
35
45
  key
36
46
  );
37
47
  }
38
- const { component: Component, label, icon, href, iconWidth, truncateLabel } = item;
48
+ const { component: Component, label, icon, badge, href, iconWidth, truncateLabel } = item;
39
49
  return /* @__PURE__ */ jsx(
40
50
  SidebarItem,
41
51
  {
42
52
  component: Component,
43
53
  label,
44
54
  icon,
55
+ badge,
45
56
  href,
46
57
  iconWidth,
47
58
  truncateLabel
@@ -185,16 +185,15 @@
185
185
  background: var(--table-component-row-bg);
186
186
  overflow: hidden;
187
187
  line-height: 20px;
188
- height: 40px;
189
188
  }
190
189
 
191
190
  .md .headerCell {
192
- padding-block: var(--spacing-xxs);
191
+ padding-block: var(--spacing-xs);
193
192
  padding-inline: var(--spacing-xs);
194
193
  }
195
194
 
196
195
  .md .cell {
197
- padding-block: var(--spacing-xxs);
196
+ padding-block: var(--spacing-xs);
198
197
  padding-inline: var(--spacing-xs);
199
198
  }
200
199
 
@@ -208,7 +207,6 @@
208
207
  padding-inline: var(--spacing-sm);
209
208
  font-size: var(--font-size-xs);
210
209
  line-height: 20px;
211
- height: 32px;
212
210
  }
213
211
 
214
212
  .sm .contextMenuTrigger {
@@ -12,6 +12,7 @@ export interface ColumnItem<T> {
12
12
  render?: (item: T) => ReactNode;
13
13
  hidden?: boolean;
14
14
  align?: 'left' | 'right' | 'center';
15
+ muted?: boolean;
15
16
  verticalAlign?: 'top' | 'middle' | 'bottom';
16
17
  divider?: 'right' | 'left';
17
18
  allowWrap?: boolean;
@@ -31,7 +31,7 @@ function TableHeaderCell({
31
31
  return /* @__PURE__ */ jsxRuntime.jsxs(
32
32
  "th",
33
33
  {
34
- className: styles__default.default.headerCell,
34
+ className: table_classes.cx(styles__default.default.headerCell, column.muted && "dbc-muted-text"),
35
35
  scope: "col",
36
36
  "aria-sort": ariaSort,
37
37
  "data-align": align,
@@ -25,7 +25,7 @@ function TableHeaderCell({
25
25
  return /* @__PURE__ */ jsxs(
26
26
  "th",
27
27
  {
28
- className: styles.headerCell,
28
+ className: cx(styles.headerCell, column.muted && "dbc-muted-text"),
29
29
  scope: "col",
30
30
  "aria-sort": ariaSort,
31
31
  "data-align": align,
@@ -144,6 +144,7 @@ function TableRow({
144
144
  {
145
145
  className: table_classes.cx(
146
146
  styles__default.default.cell,
147
+ column.muted && "dbc-muted-text",
147
148
  showRowActions && styles__default.default.actionCell,
148
149
  allowOverflow && styles__default.default.allowOverflow,
149
150
  allowWrap ? styles__default.default.allowWrap : styles__default.default.nowrap,
@@ -138,6 +138,7 @@ function TableRow({
138
138
  {
139
139
  className: cx(
140
140
  styles.cell,
141
+ column.muted && "dbc-muted-text",
141
142
  showRowActions && styles.actionCell,
142
143
  allowOverflow && styles.allowOverflow,
143
144
  allowWrap ? styles.allowWrap : styles.nowrap,
@@ -20,7 +20,7 @@ function buildColumnVisibilityFromVisibleIds(defs, visibleColumnIds) {
20
20
  }
21
21
  function mapDefsToColumnItems(defs, columnVisibility, resolvedLayout = {}) {
22
22
  return defs.map((def, index) => {
23
- var _a, _b, _c, _d, _e, _f, _g;
23
+ var _a, _b, _c, _d, _e, _f, _g, _h;
24
24
  const id = getColumnId(def, index);
25
25
  const accessorKey = def.accessorKey;
26
26
  const accessorFn = def.accessorFn;
@@ -52,9 +52,10 @@ function mapDefsToColumnItems(defs, columnVisibility, resolvedLayout = {}) {
52
52
  verticalAlign: meta.verticalAlign,
53
53
  emptyPlaceholder: (_e = meta.emptyPlaceholder) != null ? _e : "-",
54
54
  allowWrap: (_f = meta.allowWrap) != null ? _f : false,
55
+ muted: (_g = meta.muted) != null ? _g : false,
55
56
  severity: meta.severity,
56
57
  divider: meta.divider,
57
- allowOverflow: (_g = meta.allowOverflow) != null ? _g : false
58
+ allowOverflow: (_h = meta.allowOverflow) != null ? _h : false
58
59
  };
59
60
  });
60
61
  }
@@ -18,7 +18,7 @@ function buildColumnVisibilityFromVisibleIds(defs, visibleColumnIds) {
18
18
  }
19
19
  function mapDefsToColumnItems(defs, columnVisibility, resolvedLayout = {}) {
20
20
  return defs.map((def, index) => {
21
- var _a, _b, _c, _d, _e, _f, _g;
21
+ var _a, _b, _c, _d, _e, _f, _g, _h;
22
22
  const id = getColumnId(def, index);
23
23
  const accessorKey = def.accessorKey;
24
24
  const accessorFn = def.accessorFn;
@@ -50,9 +50,10 @@ function mapDefsToColumnItems(defs, columnVisibility, resolvedLayout = {}) {
50
50
  verticalAlign: meta.verticalAlign,
51
51
  emptyPlaceholder: (_e = meta.emptyPlaceholder) != null ? _e : "-",
52
52
  allowWrap: (_f = meta.allowWrap) != null ? _f : false,
53
+ muted: (_g = meta.muted) != null ? _g : false,
53
54
  severity: meta.severity,
54
55
  divider: meta.divider,
55
- allowOverflow: (_g = meta.allowOverflow) != null ? _g : false
56
+ allowOverflow: (_h = meta.allowOverflow) != null ? _h : false
56
57
  };
57
58
  });
58
59
  }
@@ -47,7 +47,7 @@
47
47
  squeezing it. */
48
48
  .tabListAddition {
49
49
  display: flex;
50
- align-items: center;
50
+ align-items: start;
51
51
  flex-shrink: 0;
52
52
  gap: var(--spacing-sm);
53
53
  margin-inline-start: auto;
@@ -242,6 +242,15 @@
242
242
  border-start-start-radius: var(--border-radius-md);
243
243
  }
244
244
 
245
+ .filled > .tabList > .tabButtons > .tab > .tabButton {
246
+ padding-block: var(--spacing-xs);
247
+ }
248
+
249
+ .filled > .tabList > .tabButtons > .tab > .tabButton .icon svg {
250
+ inline-size: var(--icon-size-sm);
251
+ block-size: var(--icon-size-sm);
252
+ }
253
+
245
254
  .filled > .tabList > .tabButtons.tabButtonsEnd {
246
255
  border-start-end-radius: var(--border-radius-md);
247
256
  }
@@ -260,6 +269,7 @@
260
269
  .filled > .tabList > .tabButtons > .tab {
261
270
  border: 1px solid transparent;
262
271
  border-block-end-width: 1px;
272
+ margin-block-end: -1px;
263
273
  color: var(--color-fg-muted);
264
274
  position: relative;
265
275
  transition:
@@ -281,7 +291,6 @@
281
291
  border-block-end-color: var(--color-bg-surface);
282
292
  border-start-start-radius: var(--border-radius-md);
283
293
  border-start-end-radius: var(--border-radius-md);
284
- margin-block-end: -1px;
285
294
  z-index: 1;
286
295
  color: var(--color-fg-default);
287
296
  }
@@ -301,7 +310,7 @@
301
310
  border-block-start: none;
302
311
  border-radius: 0 0 var(--border-radius-md) var(--border-radius-md);
303
312
  box-shadow: var(--shadow-xs);
304
- padding: var(--spacing-md);
313
+ padding: calc(var(--spacing-md) + var(--spacing-xs)) var(--spacing-md) var(--spacing-md);
305
314
  }
306
315
 
307
316
  /* =========================
@@ -381,7 +390,7 @@
381
390
 
382
391
  .filled > .tabContent,
383
392
  .panelStyle.outlined > .tabContent {
384
- padding-block: var(--spacing-sm);
393
+ padding-block: calc(var(--spacing-sm) + var(--spacing-xs)) var(--spacing-sm);
385
394
  padding-inline: var(--spacing-sm);
386
395
  }
387
396
 
@@ -72,9 +72,45 @@ body.dbc-app {
72
72
  font-family: monospace;
73
73
  }
74
74
 
75
- /* ==========================================================================
76
- Tables
77
- ========================================================================== */
75
+ .dbc-pulse {
76
+ position: relative;
77
+ display: inline-flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ border-radius: var(--border-radius-round);
81
+ color: var(--color-primary-500, var(--color-brand));
82
+ transform-origin: center;
83
+ }
84
+
85
+ .dbc-pulse::after {
86
+ content: '';
87
+ position: absolute;
88
+ inset: 0;
89
+ border-radius: inherit;
90
+ animation: dbc-pulse 1.8s ease-out infinite;
91
+ pointer-events: none;
92
+ }
93
+
94
+ @keyframes dbc-pulse {
95
+ 0% {
96
+ opacity: 0.2;
97
+ }
98
+ 20% {
99
+ opacity: 0.55;
100
+ }
101
+ 60% {
102
+ opacity: 0.15;
103
+ }
104
+ 100% {
105
+ opacity: 0;
106
+ }
107
+ }
108
+
109
+ @media (prefers-reduced-motion: reduce) {
110
+ .dbc-pulse::after {
111
+ animation: none;
112
+ }
113
+ }
78
114
 
79
115
  .dbc-table {
80
116
  --card-label-width: 260px;
package/dist/styles.css CHANGED
@@ -72,9 +72,45 @@ body.dbc-app {
72
72
  font-family: monospace;
73
73
  }
74
74
 
75
- /* ==========================================================================
76
- Tables
77
- ========================================================================== */
75
+ .dbc-pulse {
76
+ position: relative;
77
+ display: inline-flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ border-radius: var(--border-radius-round);
81
+ color: var(--color-primary-500, var(--color-brand));
82
+ transform-origin: center;
83
+ }
84
+
85
+ .dbc-pulse::after {
86
+ content: '';
87
+ position: absolute;
88
+ inset: 0;
89
+ border-radius: inherit;
90
+ animation: dbc-pulse 1.8s ease-out infinite;
91
+ pointer-events: none;
92
+ }
93
+
94
+ @keyframes dbc-pulse {
95
+ 0% {
96
+ opacity: 0.2;
97
+ }
98
+ 20% {
99
+ opacity: 0.55;
100
+ }
101
+ 60% {
102
+ opacity: 0.15;
103
+ }
104
+ 100% {
105
+ opacity: 0;
106
+ }
107
+ }
108
+
109
+ @media (prefers-reduced-motion: reduce) {
110
+ .dbc-pulse::after {
111
+ animation: none;
112
+ }
113
+ }
78
114
 
79
115
  .dbc-table {
80
116
  --card-label-width: 260px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.189",
3
+ "version": "0.0.190",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",