@dbcdk/react-components 0.0.209 → 0.0.211

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 (58) hide show
  1. package/dist/client.cjs +10 -0
  2. package/dist/client.d.ts +4 -0
  3. package/dist/client.js +2 -0
  4. package/dist/components/forms/markdown-editor/MarkdownEditor.cjs +475 -0
  5. package/dist/components/forms/markdown-editor/MarkdownEditor.d.ts +68 -0
  6. package/dist/components/forms/markdown-editor/MarkdownEditor.js +468 -0
  7. package/dist/components/forms/markdown-editor/MarkdownEditor.module.css +202 -0
  8. package/dist/components/forms/markdown-editor/MarkdownViewer.cjs +29 -0
  9. package/dist/components/forms/markdown-editor/MarkdownViewer.d.ts +27 -0
  10. package/dist/components/forms/markdown-editor/MarkdownViewer.js +23 -0
  11. package/dist/components/forms/markdown-editor/MarkdownViewer.module.css +97 -0
  12. package/dist/components/forms/markdown-editor/markdown.utils.cjs +325 -0
  13. package/dist/components/forms/markdown-editor/markdown.utils.d.ts +66 -0
  14. package/dist/components/forms/markdown-editor/markdown.utils.js +310 -0
  15. package/dist/components/listbox/Listbox.cjs +2 -2
  16. package/dist/components/listbox/Listbox.d.ts +2 -2
  17. package/dist/components/listbox/Listbox.js +2 -2
  18. package/dist/components/meta-bar/MetaBar.cjs +2 -2
  19. package/dist/components/meta-bar/MetaBar.d.ts +2 -1
  20. package/dist/components/meta-bar/MetaBar.js +2 -2
  21. package/dist/components/meta-bar/MetaBar.module.css +7 -0
  22. package/dist/components/nav-bar/NavBar.d.ts +2 -1
  23. package/dist/components/overlay/tooltip/TooltipProvider.cjs +10 -1
  24. package/dist/components/overlay/tooltip/TooltipProvider.js +11 -2
  25. package/dist/components/overlay/tooltip/useTooltipTrigger.cjs +9 -2
  26. package/dist/components/overlay/tooltip/useTooltipTrigger.js +9 -2
  27. package/dist/components/sidebar/Sidebar.cjs +2 -1
  28. package/dist/components/sidebar/Sidebar.js +2 -1
  29. package/dist/components/sidebar/components/SidebarItem.cjs +34 -13
  30. package/dist/components/sidebar/components/SidebarItem.d.ts +4 -2
  31. package/dist/components/sidebar/components/SidebarItem.js +30 -13
  32. package/dist/components/sidebar/components/SidebarItem.module.css +16 -0
  33. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.cjs +41 -116
  34. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.d.ts +4 -5
  35. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +42 -117
  36. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.module.css +17 -25
  37. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +1 -1
  38. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +1 -1
  39. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +0 -1
  40. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.cjs +1 -2
  41. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.d.ts +1 -2
  42. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +1 -2
  43. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.module.css +4 -10
  44. package/dist/components/sidebar/components/sidebar-items/SidebarItems.cjs +11 -19
  45. package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +11 -19
  46. package/dist/components/sidebar/components/sidebar-items/SidebarItems.module.css +0 -1
  47. package/dist/components/sidebar/providers/SidebarProvider.cjs +9 -7
  48. package/dist/components/sidebar/providers/SidebarProvider.d.ts +2 -1
  49. package/dist/components/sidebar/providers/SidebarProvider.js +9 -7
  50. package/dist/components/tabs/Tabs.cjs +83 -69
  51. package/dist/components/tabs/Tabs.d.ts +5 -1
  52. package/dist/components/tabs/Tabs.js +83 -69
  53. package/dist/components/tabs/Tabs.module.css +39 -0
  54. package/dist/index.cjs +213 -208
  55. package/dist/index.css +2 -0
  56. package/dist/index.d.ts +2 -0
  57. package/dist/index.js +1 -0
  58. package/package.json +4 -1
@@ -26,27 +26,17 @@ function SidebarItems({ activeLink }) {
26
26
  ] }, key);
27
27
  }
28
28
  if (item.type === "expandable") {
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;
39
29
  return /* @__PURE__ */ jsxRuntime.jsx(
40
30
  ExpandableSidebarItem.ExpandableSidebarItem,
41
31
  {
42
- items: children,
43
- label: label2,
44
- icon: icon2,
45
- badge: badge2,
46
- href: href2,
47
- iconWidth: iconWidth2,
48
- truncateLabel: truncateLabel2,
49
- component: Component2
32
+ label: item.label,
33
+ icon: item.icon,
34
+ badge: item.badge,
35
+ href: item.href,
36
+ iconWidth: item.iconWidth,
37
+ truncateLabel: item.truncateLabel,
38
+ enabled: item.enabled,
39
+ children: item.children.map((child, idx) => renderItem(child, `${key}-c${idx}`))
50
40
  },
51
41
  key
52
42
  );
@@ -61,7 +51,9 @@ function SidebarItems({ activeLink }) {
61
51
  badge,
62
52
  href,
63
53
  iconWidth,
64
- truncateLabel
54
+ truncateLabel,
55
+ enabled: item.enabled,
56
+ external: item.external
65
57
  },
66
58
  key
67
59
  );
@@ -20,27 +20,17 @@ function SidebarItems({ activeLink }) {
20
20
  ] }, key);
21
21
  }
22
22
  if (item.type === "expandable") {
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;
33
23
  return /* @__PURE__ */ jsx(
34
24
  ExpandableSidebarItem,
35
25
  {
36
- items: children,
37
- label: label2,
38
- icon: icon2,
39
- badge: badge2,
40
- href: href2,
41
- iconWidth: iconWidth2,
42
- truncateLabel: truncateLabel2,
43
- component: Component2
26
+ label: item.label,
27
+ icon: item.icon,
28
+ badge: item.badge,
29
+ href: item.href,
30
+ iconWidth: item.iconWidth,
31
+ truncateLabel: item.truncateLabel,
32
+ enabled: item.enabled,
33
+ children: item.children.map((child, idx) => renderItem(child, `${key}-c${idx}`))
44
34
  },
45
35
  key
46
36
  );
@@ -55,7 +45,9 @@ function SidebarItems({ activeLink }) {
55
45
  badge,
56
46
  href,
57
47
  iconWidth,
58
- truncateLabel
48
+ truncateLabel,
49
+ enabled: item.enabled,
50
+ external: item.external
59
51
  },
60
52
  key
61
53
  );
@@ -1,7 +1,6 @@
1
1
  .group {
2
2
  display: flex;
3
3
  flex-direction: column;
4
- gap: var(--spacing-xxs);
5
4
  margin-top: var(--spacing-xs);
6
5
  }
7
6
 
@@ -17,10 +17,10 @@ const findExpandableParentChain = (targetHref, items) => {
17
17
  const dfs = (nodes, parentExpandables) => {
18
18
  for (const node of nodes) {
19
19
  const nodeHref = hasHref(node) ? normalizeHref(node.href) : null;
20
- const isExpandableParent = hasChildren(node) && hasHref(node);
20
+ const isExpandableParent = node.type === "expandable";
21
21
  const nextParents = isExpandableParent && nodeHref ? [...parentExpandables, nodeHref] : parentExpandables;
22
- if (nodeHref === target) {
23
- return isExpandableParent ? nextParents : parentExpandables;
22
+ if (node.type !== "expandable" && nodeHref === target) {
23
+ return parentExpandables;
24
24
  }
25
25
  if (hasChildren(node)) {
26
26
  const found = dfs(node.children, nextParents);
@@ -66,6 +66,7 @@ function SidebarProvider({
66
66
  children,
67
67
  items,
68
68
  initialQuery,
69
+ initialActiveLink = "",
69
70
  initialCollapsed = false,
70
71
  initialSidebarCollapsed
71
72
  }) {
@@ -73,8 +74,10 @@ function SidebarProvider({
73
74
  const [activeQuery, setActiveQuery] = react.useState(initialQuery != null ? initialQuery : "");
74
75
  const [wrapItemText, setWrapItemText] = react.useState(false);
75
76
  const [areItemsCollapsed, setItemsCollapsed] = react.useState(initialCollapsed);
76
- const [activeHref, setActiveHref] = react.useState("");
77
- const [expandedItems, setExpandedItems] = react.useState(/* @__PURE__ */ new Set());
77
+ const [activeHref, setActiveHref] = react.useState(initialActiveLink);
78
+ const [expandedItems, setExpandedItems] = react.useState(
79
+ () => new Set(findExpandableParentChain(initialActiveLink, items))
80
+ );
78
81
  const itemsRef = react.useRef(items);
79
82
  react.useEffect(() => {
80
83
  itemsRef.current = items;
@@ -121,8 +124,7 @@ function SidebarProvider({
121
124
  );
122
125
  react.useEffect(() => {
123
126
  if (!activeHref) return;
124
- const currentItems = itemsRef.current;
125
- const parents = findExpandableParentChain(activeHref, currentItems);
127
+ const parents = findExpandableParentChain(activeHref, itemsRef.current);
126
128
  if (parents.length === 0) return;
127
129
  setExpandedItems((prev) => {
128
130
  let changed = false;
@@ -24,11 +24,12 @@ export type SidebarContextValue = {
24
24
  type SidebarProviderProps = {
25
25
  children: React.ReactNode;
26
26
  items: NavBarItem[];
27
+ initialActiveLink?: string;
27
28
  initialQuery?: string | null;
28
29
  initialCollapsed?: boolean;
29
30
  initialCollapseChildren?: boolean;
30
31
  initialSidebarCollapsed?: boolean;
31
32
  };
32
- export declare function SidebarProvider({ children, items, initialQuery, initialCollapsed, initialSidebarCollapsed, }: SidebarProviderProps): JSX.Element;
33
+ export declare function SidebarProvider({ children, items, initialQuery, initialActiveLink, initialCollapsed, initialSidebarCollapsed, }: SidebarProviderProps): JSX.Element;
33
34
  export declare function useSidebar(): SidebarContextValue;
34
35
  export {};
@@ -15,10 +15,10 @@ const findExpandableParentChain = (targetHref, items) => {
15
15
  const dfs = (nodes, parentExpandables) => {
16
16
  for (const node of nodes) {
17
17
  const nodeHref = hasHref(node) ? normalizeHref(node.href) : null;
18
- const isExpandableParent = hasChildren(node) && hasHref(node);
18
+ const isExpandableParent = node.type === "expandable";
19
19
  const nextParents = isExpandableParent && nodeHref ? [...parentExpandables, nodeHref] : parentExpandables;
20
- if (nodeHref === target) {
21
- return isExpandableParent ? nextParents : parentExpandables;
20
+ if (node.type !== "expandable" && nodeHref === target) {
21
+ return parentExpandables;
22
22
  }
23
23
  if (hasChildren(node)) {
24
24
  const found = dfs(node.children, nextParents);
@@ -64,6 +64,7 @@ function SidebarProvider({
64
64
  children,
65
65
  items,
66
66
  initialQuery,
67
+ initialActiveLink = "",
67
68
  initialCollapsed = false,
68
69
  initialSidebarCollapsed
69
70
  }) {
@@ -71,8 +72,10 @@ function SidebarProvider({
71
72
  const [activeQuery, setActiveQuery] = useState(initialQuery != null ? initialQuery : "");
72
73
  const [wrapItemText, setWrapItemText] = useState(false);
73
74
  const [areItemsCollapsed, setItemsCollapsed] = useState(initialCollapsed);
74
- const [activeHref, setActiveHref] = useState("");
75
- const [expandedItems, setExpandedItems] = useState(/* @__PURE__ */ new Set());
75
+ const [activeHref, setActiveHref] = useState(initialActiveLink);
76
+ const [expandedItems, setExpandedItems] = useState(
77
+ () => new Set(findExpandableParentChain(initialActiveLink, items))
78
+ );
76
79
  const itemsRef = useRef(items);
77
80
  useEffect(() => {
78
81
  itemsRef.current = items;
@@ -119,8 +122,7 @@ function SidebarProvider({
119
122
  );
120
123
  useEffect(() => {
121
124
  if (!activeHref) return;
122
- const currentItems = itemsRef.current;
123
- const parents = findExpandableParentChain(activeHref, currentItems);
125
+ const parents = findExpandableParentChain(activeHref, itemsRef.current);
124
126
  if (parents.length === 0) return;
125
127
  setExpandedItems((prev) => {
126
128
  let changed = false;
@@ -49,6 +49,8 @@ function Tabs({
49
49
  subheader,
50
50
  variant,
51
51
  panelStyle = false,
52
+ flushContent = false,
53
+ stackTabListAdditionOnMobile = false,
52
54
  tabs,
53
55
  value,
54
56
  defaultValue,
@@ -148,79 +150,91 @@ function Tabs({
148
150
  children: /* @__PURE__ */ jsxRuntime.jsx(Headline.Headline, { disableMargin: true, size: 2, subheader, addition, children: header })
149
151
  }
150
152
  ) : null,
151
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.tabs} ${styles__default.default[variant]} ${panelStyle ? styles__default.default.panelStyle : ""}`, children: [
152
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabList, children: [
153
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabStrip, children: [
153
+ /* @__PURE__ */ jsxRuntime.jsxs(
154
+ "div",
155
+ {
156
+ className: [
157
+ styles__default.default.tabs,
158
+ styles__default.default[variant],
159
+ panelStyle && styles__default.default.panelStyle,
160
+ flushContent && styles__default.default.flushContent,
161
+ stackTabListAdditionOnMobile && styles__default.default.stackTabListAdditionOnMobile
162
+ ].filter(Boolean).join(" "),
163
+ children: [
164
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabList, children: [
165
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabStrip, children: [
166
+ /* @__PURE__ */ jsxRuntime.jsx(
167
+ "div",
168
+ {
169
+ className: onAddTab ? styles__default.default.tabButtons : `${styles__default.default.tabButtons} ${styles__default.default.tabButtonsEnd}`,
170
+ role: "tablist",
171
+ "aria-label": header != null ? header : "Tabs",
172
+ children: visibleTabs.map((tab, index) => {
173
+ const selected = index === activeIndex;
174
+ const tabDomId = `${uid}-tab-${String(tab.id)}`;
175
+ const panelDomId = `${uid}-panel-${String(tab.id)}`;
176
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.tab} ${selected ? styles__default.default.active : ""}`, children: [
177
+ /* @__PURE__ */ jsxRuntime.jsxs(
178
+ "button",
179
+ {
180
+ id: tabDomId,
181
+ type: "button",
182
+ className: styles__default.default.tabButton,
183
+ role: "tab",
184
+ "aria-selected": selected,
185
+ "aria-controls": panelDomId,
186
+ tabIndex: selected ? 0 : -1,
187
+ disabled: tab.disabled,
188
+ onClick: () => setValue(tab.id),
189
+ onKeyDown: (e) => onKeyDownTab(e, index),
190
+ children: [
191
+ tab.headerIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, children: tab.headerIcon }) : null,
192
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: tab.header }),
193
+ tab.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badge, children: /* @__PURE__ */ jsxRuntime.jsx(Chip.Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
194
+ ]
195
+ }
196
+ ),
197
+ tab.removable && onRemoveTab ? /* @__PURE__ */ jsxRuntime.jsx(
198
+ "button",
199
+ {
200
+ type: "button",
201
+ className: styles__default.default.removeTabButton,
202
+ "aria-label": `Fjern fane ${tab.header}`,
203
+ disabled: tab.disabled,
204
+ onClick: () => onRemoveTab(tab.id, tab, index),
205
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
206
+ }
207
+ ) : null
208
+ ] }, tab.id);
209
+ })
210
+ }
211
+ ),
212
+ onAddTab ? /* @__PURE__ */ jsxRuntime.jsx(
213
+ "button",
214
+ {
215
+ type: "button",
216
+ className: styles__default.default.addTabButton,
217
+ onClick: onAddTab,
218
+ "aria-label": "Tilf\xF8j fane",
219
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { "aria-hidden": "true" })
220
+ }
221
+ ) : null
222
+ ] }),
223
+ tabListAddition ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.tabListAddition, children: tabListAddition }) : null
224
+ ] }),
154
225
  /* @__PURE__ */ jsxRuntime.jsx(
155
226
  "div",
156
227
  {
157
- className: onAddTab ? styles__default.default.tabButtons : `${styles__default.default.tabButtons} ${styles__default.default.tabButtonsEnd}`,
158
- role: "tablist",
159
- "aria-label": header != null ? header : "Tabs",
160
- children: visibleTabs.map((tab, index) => {
161
- const selected = index === activeIndex;
162
- const tabDomId = `${uid}-tab-${String(tab.id)}`;
163
- const panelDomId = `${uid}-panel-${String(tab.id)}`;
164
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.tab} ${selected ? styles__default.default.active : ""}`, children: [
165
- /* @__PURE__ */ jsxRuntime.jsxs(
166
- "button",
167
- {
168
- id: tabDomId,
169
- type: "button",
170
- className: styles__default.default.tabButton,
171
- role: "tab",
172
- "aria-selected": selected,
173
- "aria-controls": panelDomId,
174
- tabIndex: selected ? 0 : -1,
175
- disabled: tab.disabled,
176
- onClick: () => setValue(tab.id),
177
- onKeyDown: (e) => onKeyDownTab(e, index),
178
- children: [
179
- tab.headerIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, children: tab.headerIcon }) : null,
180
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: tab.header }),
181
- tab.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badge, children: /* @__PURE__ */ jsxRuntime.jsx(Chip.Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
182
- ]
183
- }
184
- ),
185
- tab.removable && onRemoveTab ? /* @__PURE__ */ jsxRuntime.jsx(
186
- "button",
187
- {
188
- type: "button",
189
- className: styles__default.default.removeTabButton,
190
- "aria-label": `Fjern fane ${tab.header}`,
191
- disabled: tab.disabled,
192
- onClick: () => onRemoveTab(tab.id, tab, index),
193
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
194
- }
195
- ) : null
196
- ] }, tab.id);
197
- })
228
+ id: activeTab ? `${uid}-panel-${String(activeTab.id)}` : void 0,
229
+ role: "tabpanel",
230
+ "aria-labelledby": activeTab ? `${uid}-tab-${String(activeTab.id)}` : void 0,
231
+ className: styles__default.default.tabContent,
232
+ children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.loadingContent, children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonLoader.SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : activeTab == null ? void 0 : activeTab.content
198
233
  }
199
- ),
200
- onAddTab ? /* @__PURE__ */ jsxRuntime.jsx(
201
- "button",
202
- {
203
- type: "button",
204
- className: styles__default.default.addTabButton,
205
- onClick: onAddTab,
206
- "aria-label": "Tilf\xF8j fane",
207
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { "aria-hidden": "true" })
208
- }
209
- ) : null
210
- ] }),
211
- tabListAddition ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.tabListAddition, children: tabListAddition }) : null
212
- ] }),
213
- /* @__PURE__ */ jsxRuntime.jsx(
214
- "div",
215
- {
216
- id: activeTab ? `${uid}-panel-${String(activeTab.id)}` : void 0,
217
- role: "tabpanel",
218
- "aria-labelledby": activeTab ? `${uid}-tab-${String(activeTab.id)}` : void 0,
219
- className: styles__default.default.tabContent,
220
- children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.loadingContent, children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonLoader.SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : activeTab == null ? void 0 : activeTab.content
221
- }
222
- )
223
- ] })
234
+ )
235
+ ]
236
+ }
237
+ )
224
238
  ] });
225
239
  }
226
240
  Tabs.Item = TabsItem;
@@ -16,6 +16,10 @@ export interface TabsProps {
16
16
  subheader?: ReactNode;
17
17
  variant: TabsVariant;
18
18
  panelStyle?: boolean;
19
+ /** Removes the built-in gap between the tab list and its content panel. */
20
+ flushContent?: boolean;
21
+ /** Moves tab-list additions below the tab buttons on narrow screens. */
22
+ stackTabListAdditionOnMobile?: boolean;
19
23
  /** Data-driven API */
20
24
  tabs?: TabItem[];
21
25
  /** Controlled */
@@ -53,7 +57,7 @@ type SlotName = 'Item';
53
57
  type TabsItemComponent = ((props: TabsItemProps) => JSX.Element) & {
54
58
  __TABS_SLOT__?: SlotName;
55
59
  };
56
- export declare function Tabs({ header, subheader, variant, panelStyle, tabs, value, defaultValue, storageKey, onValueChange, onRemoveTab, onAddTab, addition, tabListAddition, loading, children, }: TabsProps): JSX.Element;
60
+ export declare function Tabs({ header, subheader, variant, panelStyle, flushContent, stackTabListAdditionOnMobile, tabs, value, defaultValue, storageKey, onValueChange, onRemoveTab, onAddTab, addition, tabListAddition, loading, children, }: TabsProps): JSX.Element;
57
61
  export declare namespace Tabs {
58
62
  var Item: TabsItemComponent;
59
63
  }
@@ -43,6 +43,8 @@ function Tabs({
43
43
  subheader,
44
44
  variant,
45
45
  panelStyle = false,
46
+ flushContent = false,
47
+ stackTabListAdditionOnMobile = false,
46
48
  tabs,
47
49
  value,
48
50
  defaultValue,
@@ -142,79 +144,91 @@ function Tabs({
142
144
  children: /* @__PURE__ */ jsx(Headline, { disableMargin: true, size: 2, subheader, addition, children: header })
143
145
  }
144
146
  ) : null,
145
- /* @__PURE__ */ jsxs("div", { className: `${styles.tabs} ${styles[variant]} ${panelStyle ? styles.panelStyle : ""}`, children: [
146
- /* @__PURE__ */ jsxs("div", { className: styles.tabList, children: [
147
- /* @__PURE__ */ jsxs("div", { className: styles.tabStrip, children: [
147
+ /* @__PURE__ */ jsxs(
148
+ "div",
149
+ {
150
+ className: [
151
+ styles.tabs,
152
+ styles[variant],
153
+ panelStyle && styles.panelStyle,
154
+ flushContent && styles.flushContent,
155
+ stackTabListAdditionOnMobile && styles.stackTabListAdditionOnMobile
156
+ ].filter(Boolean).join(" "),
157
+ children: [
158
+ /* @__PURE__ */ jsxs("div", { className: styles.tabList, children: [
159
+ /* @__PURE__ */ jsxs("div", { className: styles.tabStrip, children: [
160
+ /* @__PURE__ */ jsx(
161
+ "div",
162
+ {
163
+ className: onAddTab ? styles.tabButtons : `${styles.tabButtons} ${styles.tabButtonsEnd}`,
164
+ role: "tablist",
165
+ "aria-label": header != null ? header : "Tabs",
166
+ children: visibleTabs.map((tab, index) => {
167
+ const selected = index === activeIndex;
168
+ const tabDomId = `${uid}-tab-${String(tab.id)}`;
169
+ const panelDomId = `${uid}-panel-${String(tab.id)}`;
170
+ return /* @__PURE__ */ jsxs("div", { className: `${styles.tab} ${selected ? styles.active : ""}`, children: [
171
+ /* @__PURE__ */ jsxs(
172
+ "button",
173
+ {
174
+ id: tabDomId,
175
+ type: "button",
176
+ className: styles.tabButton,
177
+ role: "tab",
178
+ "aria-selected": selected,
179
+ "aria-controls": panelDomId,
180
+ tabIndex: selected ? 0 : -1,
181
+ disabled: tab.disabled,
182
+ onClick: () => setValue(tab.id),
183
+ onKeyDown: (e) => onKeyDownTab(e, index),
184
+ children: [
185
+ tab.headerIcon ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: tab.headerIcon }) : null,
186
+ /* @__PURE__ */ jsx("span", { className: styles.label, children: tab.header }),
187
+ tab.badge ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
188
+ ]
189
+ }
190
+ ),
191
+ tab.removable && onRemoveTab ? /* @__PURE__ */ jsx(
192
+ "button",
193
+ {
194
+ type: "button",
195
+ className: styles.removeTabButton,
196
+ "aria-label": `Fjern fane ${tab.header}`,
197
+ disabled: tab.disabled,
198
+ onClick: () => onRemoveTab(tab.id, tab, index),
199
+ children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
200
+ }
201
+ ) : null
202
+ ] }, tab.id);
203
+ })
204
+ }
205
+ ),
206
+ onAddTab ? /* @__PURE__ */ jsx(
207
+ "button",
208
+ {
209
+ type: "button",
210
+ className: styles.addTabButton,
211
+ onClick: onAddTab,
212
+ "aria-label": "Tilf\xF8j fane",
213
+ children: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" })
214
+ }
215
+ ) : null
216
+ ] }),
217
+ tabListAddition ? /* @__PURE__ */ jsx("div", { className: styles.tabListAddition, children: tabListAddition }) : null
218
+ ] }),
148
219
  /* @__PURE__ */ jsx(
149
220
  "div",
150
221
  {
151
- className: onAddTab ? styles.tabButtons : `${styles.tabButtons} ${styles.tabButtonsEnd}`,
152
- role: "tablist",
153
- "aria-label": header != null ? header : "Tabs",
154
- children: visibleTabs.map((tab, index) => {
155
- const selected = index === activeIndex;
156
- const tabDomId = `${uid}-tab-${String(tab.id)}`;
157
- const panelDomId = `${uid}-panel-${String(tab.id)}`;
158
- return /* @__PURE__ */ jsxs("div", { className: `${styles.tab} ${selected ? styles.active : ""}`, children: [
159
- /* @__PURE__ */ jsxs(
160
- "button",
161
- {
162
- id: tabDomId,
163
- type: "button",
164
- className: styles.tabButton,
165
- role: "tab",
166
- "aria-selected": selected,
167
- "aria-controls": panelDomId,
168
- tabIndex: selected ? 0 : -1,
169
- disabled: tab.disabled,
170
- onClick: () => setValue(tab.id),
171
- onKeyDown: (e) => onKeyDownTab(e, index),
172
- children: [
173
- tab.headerIcon ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: tab.headerIcon }) : null,
174
- /* @__PURE__ */ jsx("span", { className: styles.label, children: tab.header }),
175
- tab.badge ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
176
- ]
177
- }
178
- ),
179
- tab.removable && onRemoveTab ? /* @__PURE__ */ jsx(
180
- "button",
181
- {
182
- type: "button",
183
- className: styles.removeTabButton,
184
- "aria-label": `Fjern fane ${tab.header}`,
185
- disabled: tab.disabled,
186
- onClick: () => onRemoveTab(tab.id, tab, index),
187
- children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
188
- }
189
- ) : null
190
- ] }, tab.id);
191
- })
222
+ id: activeTab ? `${uid}-panel-${String(activeTab.id)}` : void 0,
223
+ role: "tabpanel",
224
+ "aria-labelledby": activeTab ? `${uid}-tab-${String(activeTab.id)}` : void 0,
225
+ className: styles.tabContent,
226
+ children: loading ? /* @__PURE__ */ jsx("div", { className: styles.loadingContent, children: /* @__PURE__ */ jsx(SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : activeTab == null ? void 0 : activeTab.content
192
227
  }
193
- ),
194
- onAddTab ? /* @__PURE__ */ jsx(
195
- "button",
196
- {
197
- type: "button",
198
- className: styles.addTabButton,
199
- onClick: onAddTab,
200
- "aria-label": "Tilf\xF8j fane",
201
- children: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" })
202
- }
203
- ) : null
204
- ] }),
205
- tabListAddition ? /* @__PURE__ */ jsx("div", { className: styles.tabListAddition, children: tabListAddition }) : null
206
- ] }),
207
- /* @__PURE__ */ jsx(
208
- "div",
209
- {
210
- id: activeTab ? `${uid}-panel-${String(activeTab.id)}` : void 0,
211
- role: "tabpanel",
212
- "aria-labelledby": activeTab ? `${uid}-tab-${String(activeTab.id)}` : void 0,
213
- className: styles.tabContent,
214
- children: loading ? /* @__PURE__ */ jsx("div", { className: styles.loadingContent, children: /* @__PURE__ */ jsx(SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : activeTab == null ? void 0 : activeTab.content
215
- }
216
- )
217
- ] })
228
+ )
229
+ ]
230
+ }
231
+ )
218
232
  ] });
219
233
  }
220
234
  Tabs.Item = TabsItem;
@@ -337,6 +337,26 @@
337
337
  gap: var(--spacing-md);
338
338
  }
339
339
 
340
+ .flushContent.tabs {
341
+ gap: 0;
342
+ }
343
+
344
+ .flushContent > .tabList {
345
+ grid-template-rows: auto 0;
346
+ }
347
+
348
+ .flushContent > .tabList > .tabStrip {
349
+ grid-row: 1;
350
+ align-self: stretch;
351
+ }
352
+
353
+ .flushContent.filled > .tabContent {
354
+ border: 0;
355
+ border-radius: 0;
356
+ box-shadow: none;
357
+ padding: 0;
358
+ }
359
+
340
360
  .headerContainerOutlined {
341
361
  padding-block-end: var(--spacing-xs);
342
362
  }
@@ -413,4 +433,23 @@
413
433
  .panelStyle > .tabList {
414
434
  border: 0;
415
435
  }
436
+
437
+ .stackTabListAdditionOnMobile > .tabList {
438
+ grid-template-columns: minmax(0, 1fr);
439
+ grid-template-rows: auto auto;
440
+ }
441
+
442
+ .stackTabListAdditionOnMobile > .tabList > .tabStrip {
443
+ grid-column: 1;
444
+ grid-row: 1;
445
+ }
446
+
447
+ .stackTabListAdditionOnMobile > .tabList > .tabListAddition {
448
+ grid-column: 1;
449
+ grid-row: 2;
450
+ justify-content: flex-start;
451
+ margin-inline-start: 0;
452
+ padding-block: var(--spacing-xs);
453
+ padding-inline: 0;
454
+ }
416
455
  }