@dbcdk/react-components 0.0.88 → 0.0.90

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/components/accordion/Accordion.d.ts +1 -0
  2. package/dist/components/accordion/components/AccordionRow.js +1 -1
  3. package/dist/components/avatar/Avatar.js +16 -10
  4. package/dist/components/avatar/Avatar.module.css +33 -12
  5. package/dist/components/button/Button.js +8 -1
  6. package/dist/components/button/Button.module.css +2 -1
  7. package/dist/components/card/Card.d.ts +1 -5
  8. package/dist/components/card/Card.js +29 -4
  9. package/dist/components/card/Card.module.css +86 -98
  10. package/dist/components/card-container/CardContainer.d.ts +2 -1
  11. package/dist/components/card-container/CardContainer.js +2 -2
  12. package/dist/components/card-container/CardContainer.module.css +10 -9
  13. package/dist/components/clear-button/ClearButton.d.ts +2 -1
  14. package/dist/components/clear-button/ClearButton.js +6 -2
  15. package/dist/components/clear-button/ClearButton.module.css +6 -0
  16. package/dist/components/divider/Divider.d.ts +5 -0
  17. package/dist/components/divider/Divider.js +12 -0
  18. package/dist/components/forms/input/Input.d.ts +2 -1
  19. package/dist/components/forms/input/Input.js +6 -2
  20. package/dist/components/forms/input/Input.module.css +32 -0
  21. package/dist/components/forms/select/Select.d.ts +2 -1
  22. package/dist/components/forms/select/Select.js +2 -2
  23. package/dist/components/forms/typeahead/Typeahead.d.ts +2 -1
  24. package/dist/components/forms/typeahead/Typeahead.js +180 -118
  25. package/dist/components/forms/typeahead/Typeahead.module.css +4 -0
  26. package/dist/components/grid/Grid.d.ts +23 -0
  27. package/dist/components/grid/Grid.js +23 -0
  28. package/dist/components/grid/Grid.module.css +35 -0
  29. package/dist/components/headline/CollapsibleHeadline.d.ts +21 -0
  30. package/dist/components/headline/CollapsibleHeadline.js +29 -0
  31. package/dist/components/headline/Headline.d.ts +7 -5
  32. package/dist/components/headline/Headline.js +7 -6
  33. package/dist/components/headline/Headline.module.css +80 -8
  34. package/dist/components/nav-bar/NavBar.module.css +6 -2
  35. package/dist/components/overlay/modal/Modal.d.ts +2 -1
  36. package/dist/components/overlay/modal/Modal.js +5 -3
  37. package/dist/components/overlay/modal/provider/ModalProvider.js +2 -0
  38. package/dist/components/overlay/side-panel/SidePanel.d.ts +2 -1
  39. package/dist/components/overlay/side-panel/SidePanel.js +2 -2
  40. package/dist/components/page/Page.d.ts +5 -1
  41. package/dist/components/page/Page.js +6 -2
  42. package/dist/components/page/Page.module.css +54 -4
  43. package/dist/components/panel/Panel.d.ts +2 -1
  44. package/dist/components/panel/Panel.js +2 -2
  45. package/dist/components/popover/Popover.js +1 -1
  46. package/dist/components/stack/Stack.d.ts +16 -0
  47. package/dist/components/stack/Stack.js +19 -0
  48. package/dist/components/state-page/StatePage.d.ts +2 -1
  49. package/dist/components/state-page/StatePage.js +2 -2
  50. package/dist/components/table/Table.d.ts +1 -1
  51. package/dist/components/table/Table.js +22 -4
  52. package/dist/components/table/Table.module.css +14 -0
  53. package/dist/components/table/Table.types.d.ts +1 -0
  54. package/dist/components/tabs/Tabs.d.ts +3 -1
  55. package/dist/components/tabs/Tabs.js +4 -2
  56. package/dist/components/tabs/Tabs.module.css +4 -0
  57. package/dist/components/theme-button/ThemeButton.d.ts +1 -0
  58. package/dist/components/theme-button/ThemeButton.js +5 -1
  59. package/dist/components/toast/Toast.d.ts +2 -1
  60. package/dist/components/toast/Toast.js +2 -2
  61. package/dist/hooks/useViewportFill.d.ts +2 -6
  62. package/dist/hooks/useViewportFill.js +29 -24
  63. package/dist/index.d.ts +5 -0
  64. package/dist/index.js +5 -0
  65. package/dist/styles/css-helper-classes/flex.css +12 -0
  66. package/dist/styles/css-helper-classes/spacing.css +5 -0
  67. package/dist/styles/styles.css +154 -66
  68. package/dist/styles/themes/dbc/colors.css +10 -0
  69. package/dist/styles.css +154 -66
  70. package/package.json +1 -1
@@ -0,0 +1,23 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ export type GridGap = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
3
+ export interface GridProps {
4
+ children?: ReactNode;
5
+ gap?: GridGap;
6
+ /** Stretch direct children so cards/items in the same row get equal height */
7
+ equalHeight?: boolean;
8
+ className?: string;
9
+ style?: CSSProperties;
10
+ }
11
+ export declare function Grid({ children, gap, equalHeight, className, style }: GridProps): import("react/jsx-runtime").JSX.Element;
12
+ export interface GridItemProps {
13
+ children?: ReactNode;
14
+ /** Default span: <768px */
15
+ base?: number;
16
+ /** Medium span: ≥768px */
17
+ md?: number;
18
+ /** Large span: ≥1200px */
19
+ lg?: number;
20
+ className?: string;
21
+ style?: CSSProperties;
22
+ }
23
+ export declare function GridItem({ children, base, md, lg, className, style }: GridItemProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import styles from './Grid.module.css';
3
+ const GAP_TOKEN = {
4
+ none: '0',
5
+ xs: 'var(--spacing-xs)',
6
+ sm: 'var(--spacing-sm)',
7
+ md: 'var(--spacing-md)',
8
+ lg: 'var(--spacing-lg)',
9
+ xl: 'var(--spacing-xl)',
10
+ };
11
+ export function Grid({ children, gap = 'md', equalHeight = false, className, style }) {
12
+ return (_jsx("div", { className: [styles.grid, equalHeight && styles.equalHeight, className]
13
+ .filter(Boolean)
14
+ .join(' '), style: { gap: GAP_TOKEN[gap], ...style }, children: children }));
15
+ }
16
+ export function GridItem({ children, base = 12, md, lg, className, style }) {
17
+ return (_jsx("div", { className: [styles.item, className].filter(Boolean).join(' '), style: {
18
+ '--span-base': base,
19
+ ...(md != null ? { '--span-md': md } : {}),
20
+ ...(lg != null ? { '--span-lg': lg } : {}),
21
+ ...style,
22
+ }, children: children }));
23
+ }
@@ -0,0 +1,35 @@
1
+ .grid {
2
+ display: grid;
3
+ grid-template-columns: repeat(12, minmax(0, 1fr));
4
+ align-items: start;
5
+ }
6
+
7
+ .equalHeight {
8
+ align-items: stretch;
9
+ }
10
+
11
+ .item {
12
+ grid-column: span var(--span-base, 12);
13
+ min-inline-size: 0;
14
+ }
15
+
16
+ .equalHeight .item {
17
+ display: flex;
18
+ }
19
+
20
+ .equalHeight .item > * {
21
+ flex: 1;
22
+ min-inline-size: 0;
23
+ }
24
+
25
+ @media (min-width: 768px) {
26
+ .item {
27
+ grid-column: span var(--span-md, var(--span-base, 12));
28
+ }
29
+ }
30
+
31
+ @media (min-width: 1200px) {
32
+ .item {
33
+ grid-column: span var(--span-lg, var(--span-md, var(--span-base, 12)));
34
+ }
35
+ }
@@ -0,0 +1,21 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ import type { HeadlineProps } from './Headline';
3
+ export interface CollapsibleHeadlineProps extends Omit<HeadlineProps, 'addition' | 'children'> {
4
+ /** The headline text — always visible. */
5
+ header: React.ReactNode;
6
+ /** Controlled expanded state. Required when `storageKey` is not set. */
7
+ expanded?: boolean;
8
+ /** Called when the toggle is clicked. */
9
+ onToggle?: () => void;
10
+ /** id of the panel element, used for aria-controls. Generated automatically if omitted. */
11
+ controls?: string;
12
+ /** Extra content rendered between the headline text and the toggle button. */
13
+ addition?: React.ReactNode;
14
+ /**
15
+ * When set the component manages its own expanded state, persisted to
16
+ * localStorage under this key. `expanded` is used as the initial value
17
+ * if nothing is stored yet; `onToggle` is still called after each toggle.
18
+ */
19
+ storageKey?: string;
20
+ }
21
+ export declare function CollapsibleHeadline({ header, expanded, onToggle, controls, addition, storageKey, children, size, variant, weight, ...headlineProps }: PropsWithChildren<CollapsibleHeadlineProps>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ChevronDown } from 'lucide-react';
4
+ import { useId, useState } from 'react';
5
+ import { Headline } from './Headline';
6
+ import styles from './Headline.module.css';
7
+ import { Button } from '../button/Button';
8
+ export function CollapsibleHeadline({ header, expanded, onToggle, controls, addition, storageKey, children, size = 2, variant = 'muted', weight = 400, ...headlineProps }) {
9
+ const generatedId = useId();
10
+ const panelId = controls !== null && controls !== void 0 ? controls : generatedId;
11
+ const [internalExpanded, setInternalExpanded] = useState(() => {
12
+ if (!storageKey || typeof window === 'undefined')
13
+ return expanded !== null && expanded !== void 0 ? expanded : false;
14
+ const stored = localStorage.getItem(storageKey);
15
+ return stored !== null ? stored === 'true' : (expanded !== null && expanded !== void 0 ? expanded : false);
16
+ });
17
+ const isExpanded = storageKey ? internalExpanded : (expanded !== null && expanded !== void 0 ? expanded : false);
18
+ const handleToggle = () => {
19
+ if (storageKey) {
20
+ const next = !internalExpanded;
21
+ setInternalExpanded(next);
22
+ localStorage.setItem(storageKey, String(next));
23
+ }
24
+ onToggle === null || onToggle === void 0 ? void 0 : onToggle();
25
+ };
26
+ return (_jsxs("div", { className: styles.collapsibleRoot, children: [_jsxs(Headline, { ...headlineProps, variant: variant, weight: weight, size: size, addition: addition, children: [header, _jsx(Button, { shape: "round", type: "button", variant: "inline", "aria-expanded": isExpanded, "aria-controls": panelId, onClick: handleToggle, children: _jsx(ChevronDown, { "aria-hidden": true, className: [styles.toggleChevron, isExpanded ? styles.toggleChevronExpanded : '']
27
+ .filter(Boolean)
28
+ .join(' ') }) })] }), isExpanded && (_jsx("div", { id: panelId, className: styles.collapsiblePanel, children: children }))] }));
29
+ }
@@ -1,17 +1,19 @@
1
- import React, { JSX, PropsWithChildren } from 'react';
1
+ import React, { PropsWithChildren } from 'react';
2
2
  import { Severity } from '../../constants/severity.types';
3
3
  type HeadlineTone = 'dark' | 'light';
4
- interface HeadlineProps extends React.AriaAttributes {
4
+ type HeadlineVariant = 'default' | 'muted';
5
+ export interface HeadlineProps extends React.AriaAttributes {
5
6
  size?: 1 | 2 | 3 | 4 | 5 | 6;
6
7
  marker?: boolean;
7
8
  disableMargin?: boolean;
8
9
  severity?: Severity;
9
- weight?: 500 | 600 | 700;
10
- subHeadline?: string | JSX.Element;
10
+ weight?: 400 | 500 | 600 | 700;
11
+ subheader?: React.ReactNode;
11
12
  addition?: React.ReactNode;
12
13
  icon?: React.ReactNode;
13
14
  allowWrap?: boolean;
14
15
  tone?: HeadlineTone;
16
+ variant?: HeadlineVariant;
15
17
  }
16
- export declare function Headline({ size, marker, disableMargin, children, severity, weight, subHeadline, addition, icon, tone, allowWrap, }: PropsWithChildren<HeadlineProps>): React.ReactNode;
18
+ export declare function Headline({ size, marker, disableMargin, children, severity, weight, subheader, addition, icon, tone, variant, allowWrap, }: PropsWithChildren<HeadlineProps>): React.JSX.Element;
17
19
  export {};
@@ -1,9 +1,9 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import styles from './Headline.module.css';
4
4
  import { SeverityBgColor } from '../../constants/severity';
5
5
  import { Icon } from '../icon/Icon';
6
- export function Headline({ size = 2, marker, disableMargin, children, severity, weight = 600, subHeadline, addition, icon, tone, allowWrap = true, }) {
6
+ export function Headline({ size = 2, marker, disableMargin, children, severity, weight = 600, subheader, addition, icon, tone, variant, allowWrap = true, }) {
7
7
  const Tag = `h${size}`;
8
8
  const containerClassName = [styles.headlineContainer, tone ? styles[`tone-${tone}`] : '']
9
9
  .filter(Boolean)
@@ -12,14 +12,15 @@ export function Headline({ size = 2, marker, disableMargin, children, severity,
12
12
  styles.headline,
13
13
  disableMargin ? styles.noMargin : '',
14
14
  marker ? styles.marker : '',
15
+ variant === 'muted' ? styles['variant-muted'] : '',
15
16
  ]
16
17
  .filter(Boolean)
17
18
  .join(' ');
18
19
  const textClassName = [styles.text, allowWrap ? styles.wrap : styles.truncate]
19
20
  .filter(Boolean)
20
21
  .join(' ');
21
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: containerClassName, children: [_jsxs(Tag, { style: {
22
- '--font-weight': weight,
23
- '--marker-color': severity ? SeverityBgColor[severity] : undefined,
24
- }, className: headlineClassName, children: [icon || (severity && !marker) ? (_jsx("span", { className: styles.icon, children: _jsx(Icon, { customIcon: icon, severity: severity }) })) : null, _jsx("span", { className: textClassName, children: children })] }), addition] }), subHeadline && _jsx("div", { className: styles.subHeadline, children: subHeadline })] }));
22
+ return (_jsx("div", { className: containerClassName, children: _jsxs("div", { className: styles.headlineBlock, children: [_jsxs("div", { className: styles.headlineRow, children: [_jsxs(Tag, { style: {
23
+ '--font-weight': weight,
24
+ '--marker-color': severity ? SeverityBgColor[severity] : undefined,
25
+ }, className: headlineClassName, children: [icon || (severity && !marker) ? (_jsx("span", { className: styles.icon, children: _jsx(Icon, { customIcon: icon, severity: severity }) })) : null, _jsx("span", { className: textClassName, children: children })] }), addition ? _jsx("div", { className: styles.addition, children: addition }) : null] }), subheader ? _jsx("div", { className: styles.subheader, children: subheader }) : null] }) }));
25
26
  }
@@ -1,11 +1,24 @@
1
1
  .headlineContainer {
2
2
  display: flex;
3
- align-items: center;
3
+ align-items: flex-start;
4
4
  gap: var(--spacing-lg);
5
- flex-wrap: wrap;
6
5
  max-width: 100%;
6
+ min-width: 0;
7
+ }
8
+
9
+ .headlineBlock {
10
+ display: flex;
11
+ flex-direction: column;
7
12
  flex: 1 1 auto;
8
13
  min-width: 0;
14
+ gap: var(--spacing-xxs);
15
+ }
16
+
17
+ .headlineRow {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--spacing-lg);
21
+ min-width: 0;
9
22
  }
10
23
 
11
24
  /* Base headline */
@@ -17,7 +30,7 @@
17
30
  margin-block: var(--spacing-xs);
18
31
 
19
32
  /* Typography */
20
- font-weight: var(--font-weight-medium, 500);
33
+ font-weight: var(--font-weight, 600);
21
34
  letter-spacing: var(--letter-spacing-tight);
22
35
  line-height: var(--line-height-tight);
23
36
  color: inherit;
@@ -27,6 +40,56 @@
27
40
  min-width: 0; /* required for truncation inside flex */
28
41
  }
29
42
 
43
+ /* CollapsibleHeadline wrapper */
44
+ .collapsibleRoot {
45
+ display: flex;
46
+ flex-direction: column;
47
+ }
48
+
49
+ .collapsiblePanel {
50
+ display: contents;
51
+ }
52
+
53
+ /* CollapsibleHeadline toggle button */
54
+ .toggleButton {
55
+ all: unset;
56
+ box-sizing: border-box;
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ flex: 0 0 auto;
61
+ padding: var(--spacing-2xs);
62
+ border-radius: var(--border-radius-sm);
63
+ cursor: pointer;
64
+ color: var(--color-fg-subtle);
65
+ transition: color var(--transition-fast) var(--ease-standard);
66
+ }
67
+
68
+ .toggleButton:hover {
69
+ color: var(--color-fg-default);
70
+ }
71
+
72
+ .toggleButton:focus-visible {
73
+ outline: none;
74
+ box-shadow: var(--focus-ring);
75
+ }
76
+
77
+ .toggleChevron {
78
+ display: block;
79
+ width: var(--icon-size-md);
80
+ height: var(--icon-size-md);
81
+ transition: transform var(--transition-normal) var(--ease-standard);
82
+ }
83
+
84
+ .toggleChevronExpanded {
85
+ transform: rotate(180deg);
86
+ }
87
+
88
+ /* Variant overrides */
89
+ .variant-muted {
90
+ color: var(--color-fg-subtle);
91
+ }
92
+
30
93
  /* Tone overrides */
31
94
  .tone-dark .headline {
32
95
  color: var(--color-fg-default);
@@ -58,15 +121,21 @@
58
121
  pointer-events: none;
59
122
  }
60
123
 
61
- /* Subheadline */
62
- .subHeadline {
63
- color: inherit;
64
- opacity: 0.85;
65
- font-size: var(--font-size-md);
124
+ /* Subheader */
125
+ .subheader {
126
+ font-size: var(--font-size-sm);
66
127
  margin-block-start: calc(var(--spacing-2xs) * -1);
128
+ color: var(--color-fg-subtle);
67
129
  line-height: var(--line-height-normal);
68
130
  }
69
131
 
132
+ .addition {
133
+ display: flex;
134
+ flex: 1 1 auto;
135
+ min-width: 0;
136
+ align-items: center;
137
+ }
138
+
70
139
  /* Icon */
71
140
  .icon {
72
141
  flex: 0 0 auto;
@@ -90,4 +159,7 @@
90
159
  .wrap {
91
160
  white-space: normal;
92
161
  overflow: visible;
162
+ display: flex;
163
+ align-items: center;
164
+ gap: var(--spacing-xxs);
93
165
  }
@@ -156,7 +156,6 @@
156
156
 
157
157
  /* Hover + focus */
158
158
  .link:hover {
159
- background-color: var(--color-bg-hover-subtle);
160
159
  color: var(--color-fg-default);
161
160
  }
162
161
  .link:focus-visible {
@@ -178,13 +177,18 @@
178
177
  inset-block-end: 0;
179
178
  inline-size: 0;
180
179
  block-size: 2px;
181
- background-color: var(--color-brand);
180
+ background-color: var(--color-border-strong);
182
181
  transition: inline-size var(--transition-fast) var(--ease-standard);
183
182
  }
184
183
 
184
+ .link:hover::after {
185
+ inline-size: 100%;
186
+ }
187
+
185
188
  .link.active::after,
186
189
  .link[aria-current='page']::after {
187
190
  inline-size: 100%;
191
+ background-color: var(--color-brand);
188
192
  }
189
193
 
190
194
  /* Icons/images inside links */
@@ -13,6 +13,7 @@ export type ModalProps = {
13
13
  isOpen: boolean;
14
14
  onRequestClose: () => void;
15
15
  header?: ReactNode;
16
+ subheader?: ReactNode;
16
17
  content?: ReactNode;
17
18
  children?: ReactNode;
18
19
  primaryAction?: ModalActionConfig;
@@ -23,4 +24,4 @@ export type ModalProps = {
23
24
  dataCy?: string;
24
25
  width?: number | string;
25
26
  };
26
- export declare function Modal({ isOpen, onRequestClose, header, content, children, primaryAction, secondaryAction, closeOnOverlayClick, severity, disableContentSpacing, isLoading, dataCy, width, }: ModalProps): React.ReactNode;
27
+ export declare function Modal({ isOpen, onRequestClose, header, subheader, content, children, primaryAction, secondaryAction, closeOnOverlayClick, severity, disableContentSpacing, isLoading, dataCy, width, }: ModalProps): React.ReactNode;
@@ -6,7 +6,7 @@ import { createPortal } from 'react-dom';
6
6
  import { Button } from '../../../components/button/Button';
7
7
  import { Headline } from '../../../components/headline/Headline';
8
8
  import styles from './Modal.module.css';
9
- export function Modal({ isOpen, onRequestClose, header, content, children, primaryAction, secondaryAction, closeOnOverlayClick = true, severity, disableContentSpacing = false, isLoading, dataCy, width, }) {
9
+ export function Modal({ isOpen, onRequestClose, header, subheader, content, children, primaryAction, secondaryAction, closeOnOverlayClick = true, severity, disableContentSpacing = false, isLoading, dataCy, width, }) {
10
10
  const titleId = useId();
11
11
  const dialogRef = useRef(null);
12
12
  const lastActiveElementRef = useRef(null);
@@ -103,11 +103,13 @@ export function Modal({ isOpen, onRequestClose, header, content, children, prima
103
103
  const stopPropagation = e => {
104
104
  e.stopPropagation();
105
105
  };
106
- const resolvedSecondaryAction = secondaryAction !== null && secondaryAction !== void 0 ? secondaryAction : (primaryAction ? { label: 'Luk', onClick: onRequestClose } : undefined);
106
+ const resolvedSecondaryAction = primaryAction || secondaryAction
107
+ ? { label: 'Luk', onClick: onRequestClose, ...secondaryAction }
108
+ : undefined;
107
109
  const shouldRenderFooter = Boolean(primaryAction || resolvedSecondaryAction);
108
110
  const body = children !== null && children !== void 0 ? children : content;
109
111
  const resolvedWidth = typeof width === 'number' ? `${width}px` : typeof width === 'string' ? width : undefined;
110
112
  return createPortal(_jsx("div", { className: styles.overlay, onClick: handleOverlayClick, children: _jsxs("div", { "data-cy": dataCy, ref: dialogRef, className: `${styles.modal} ${disableContentSpacing ? '' : styles.contentSpacing}`, style: resolvedWidth
111
113
  ? { ['--modal-width']: resolvedWidth }
112
- : undefined, onClick: stopPropagation, role: "dialog", "aria-modal": "true", "aria-labelledby": header ? titleId : undefined, tabIndex: -1, children: [_jsxs("div", { className: styles.header, children: [header && (_jsx(Headline, { severity: severity, size: 3, disableMargin: true, children: header })), _jsx(Button, { type: "button", variant: "inline", onClick: () => onRequestCloseRef.current(), "aria-label": "Luk", shape: "round", icon: _jsx(X, {}) })] }), _jsx("div", { className: styles.body, children: body }), shouldRenderFooter && (_jsxs("div", { className: styles.footer, children: [resolvedSecondaryAction && (_jsxs(Button, { type: "button", onClick: resolvedSecondaryAction.onClick, disabled: isLoading, children: [resolvedSecondaryAction.icon && (_jsx("span", { className: styles.icon, children: resolvedSecondaryAction.icon })), _jsx("span", { children: resolvedSecondaryAction.label })] })), primaryAction && (_jsxs(Button, { type: "button", variant: primaryAction.severity || 'primary', onClick: primaryAction.onClick, disabled: primaryAction.disabled || isLoading, loading: isLoading, children: [primaryAction.icon && _jsx("span", { className: styles.icon, children: primaryAction.icon }), _jsx("span", { children: primaryAction.label })] }))] }))] }) }), document.body);
114
+ : undefined, onClick: stopPropagation, role: "dialog", "aria-modal": "true", "aria-labelledby": header ? titleId : undefined, tabIndex: -1, children: [_jsxs("div", { className: styles.header, children: [header && (_jsx(Headline, { severity: severity, size: 3, disableMargin: true, subheader: subheader, children: header })), _jsx(Button, { type: "button", variant: "inline", onClick: () => onRequestCloseRef.current(), "aria-label": "Luk", shape: "round", icon: _jsx(X, {}) })] }), _jsx("div", { className: styles.body, children: body }), shouldRenderFooter && (_jsxs("div", { className: styles.footer, children: [resolvedSecondaryAction && (_jsxs(Button, { type: "button", onClick: resolvedSecondaryAction.onClick, disabled: isLoading, children: [resolvedSecondaryAction.icon && (_jsx("span", { className: styles.icon, children: resolvedSecondaryAction.icon })), _jsx("span", { children: resolvedSecondaryAction.label })] })), primaryAction && (_jsxs(Button, { type: "button", variant: primaryAction.severity || 'primary', onClick: primaryAction.onClick, disabled: primaryAction.disabled || isLoading, loading: isLoading, children: [primaryAction.icon && _jsx("span", { className: styles.icon, children: primaryAction.icon }), _jsx("span", { children: primaryAction.label })] }))] }))] }) }), document.body);
113
115
  }
@@ -47,12 +47,14 @@ export function ModalProvider({ children }) {
47
47
  severity: confirmConfig.confirmButtonSeverity || 'primary',
48
48
  onClick: () => {
49
49
  resolvePending(true);
50
+ closeModal();
50
51
  },
51
52
  },
52
53
  secondaryAction: {
53
54
  label: cancelLabel,
54
55
  onClick: () => {
55
56
  resolvePending(false);
57
+ closeModal();
56
58
  },
57
59
  },
58
60
  });
@@ -3,6 +3,7 @@ import { Severity } from '../../../constants/severity.types';
3
3
  interface SidePanelProps {
4
4
  children?: ReactNode;
5
5
  header: ReactNode;
6
+ subheader?: ReactNode;
6
7
  headerAddition?: ReactNode;
7
8
  actions?: ReactNode;
8
9
  onClose: (event?: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<HTMLDivElement>) => void;
@@ -20,5 +21,5 @@ interface SidePanelProps {
20
21
  onCloseDetails?: () => void;
21
22
  detailsHeaderAddition?: ReactNode;
22
23
  }
23
- export declare function SidePanel({ isOpen, onClose, children, header, headerAddition, actions, showBackdrop, severity, showHeaderMarker, width, details, detailsHeader, detailsWidth, onCloseDetails, detailsHeaderAddition, ...props }: SidePanelProps & HTMLAttributes<HTMLElement>): ReactNode;
24
+ export declare function SidePanel({ isOpen, onClose, children, header, subheader, headerAddition, actions, showBackdrop, severity, showHeaderMarker, width, details, detailsHeader, detailsWidth, onCloseDetails, detailsHeaderAddition, ...props }: SidePanelProps & HTMLAttributes<HTMLElement>): ReactNode;
24
25
  export {};
@@ -6,7 +6,7 @@ import { Button } from '../../../components/button/Button';
6
6
  import { Headline } from '../../../components/headline/Headline';
7
7
  import { MOTION_MS } from '../../../styles/animation';
8
8
  import styles from './SidePanel.module.css';
9
- export function SidePanel({ isOpen, onClose, children, header, headerAddition, actions, showBackdrop = true, severity, showHeaderMarker = true, width = '400px', details, detailsHeader = 'Output', detailsWidth = '420px', onCloseDetails, detailsHeaderAddition, ...props }) {
9
+ export function SidePanel({ isOpen, onClose, children, header, subheader, headerAddition, actions, showBackdrop = true, severity, showHeaderMarker = true, width = '400px', details, detailsHeader = 'Output', detailsWidth = '420px', onCloseDetails, detailsHeaderAddition, ...props }) {
10
10
  const [mounted, setMounted] = useState(false);
11
11
  const [shouldRender, setShouldRender] = useState(isOpen);
12
12
  const [isActive, setIsActive] = useState(false);
@@ -76,7 +76,7 @@ export function SidePanel({ isOpen, onClose, children, header, headerAddition, a
76
76
  }, "data-cy": "details-panel", role: "dialog", "aria-modal": "true", children: [hasDetails ? (_jsxs("aside", { className: styles.detailsCol, "data-cy": "details-panel-details", children: [_jsxs("div", { className: styles.detailsHeader, children: [_jsx("div", { className: styles.detailsTitle, children: detailsHeader }), _jsxs("div", { className: styles.detailsHeaderActions, children: [detailsHeaderAddition, onCloseDetails ? (_jsx(Button, { type: "button", size: "sm", variant: "outlined", onClick: e => {
77
77
  e.stopPropagation();
78
78
  onCloseDetails();
79
- }, children: "Luk" })) : null] })] }), _jsx("div", { className: styles.detailsContent, children: details })] })) : null, _jsxs("section", { className: styles.mainCol, "data-cy": "details-panel-main", children: [_jsx("div", { className: styles.header, children: _jsxs("div", { className: "dbc-flex dbc-justify-between", children: [_jsx(Headline, { size: 3, disableMargin: true, severity: severity, marker: showHeaderMarker, children: header }), _jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xs", children: [headerAddition, _jsx(Button, { type: "button", size: "md", shape: "round", variant: "inline", onClick: e => {
79
+ }, children: "Luk" })) : null] })] }), _jsx("div", { className: styles.detailsContent, children: details })] })) : null, _jsxs("section", { className: styles.mainCol, "data-cy": "details-panel-main", children: [_jsx("div", { className: styles.header, children: _jsxs("div", { className: "dbc-flex dbc-justify-between", children: [_jsx(Headline, { size: 3, disableMargin: true, severity: severity, marker: showHeaderMarker, subheader: subheader, children: header }), _jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xs", children: [headerAddition, _jsx(Button, { type: "button", size: "md", shape: "round", variant: "inline", onClick: e => {
80
80
  e.stopPropagation();
81
81
  onClose(e);
82
82
  }, "aria-label": "Luk panel", "data-cy": "side-panel-close-button", children: _jsx(X, {}) })] })] }) }), _jsx("div", { className: styles.content, "data-cy": "details-panel-content", children: children }), actions && _jsx("div", { className: styles.actions, children: actions })] })] })] }), document.body);
@@ -3,12 +3,16 @@ import { Severity } from '../../constants/severity.types';
3
3
  import { BreadcrumbItem } from '../breadcrumbs/Breadcrumbs';
4
4
  interface PageProps {
5
5
  header?: string;
6
+ subheader?: ReactNode;
6
7
  severity?: Severity;
7
8
  headerIcon?: ReactNode;
8
9
  children?: ReactNode;
9
10
  headerAddition?: ReactNode;
10
11
  disableContentBox?: boolean;
12
+ disableTopPadding?: boolean;
13
+ maxWidth?: 'sm' | 'md' | 'lg';
11
14
  breadcrumbs?: BreadcrumbItem[];
15
+ containScrolling?: boolean;
12
16
  }
13
- export declare function Page({ header, severity, headerIcon, headerAddition, breadcrumbs, disableContentBox, children, }: PageProps): ReactNode;
17
+ export declare function Page({ header, subheader, severity, headerIcon, headerAddition, breadcrumbs, disableContentBox, disableTopPadding, maxWidth, containScrolling, children, }: PageProps): ReactNode;
14
18
  export {};
@@ -2,6 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styles from './Page.module.css';
3
3
  import { Breadcrumbs } from '../breadcrumbs/Breadcrumbs';
4
4
  import { Headline } from '../headline/Headline';
5
- export function Page({ header, severity, headerIcon, headerAddition, breadcrumbs, disableContentBox, children, }) {
6
- return (_jsxs("div", { className: "grow-container", children: [_jsxs("div", { className: styles.headerContainer, children: [breadcrumbs ? (_jsx(Breadcrumbs, { items: breadcrumbs })) : (_jsx(Headline, { disableMargin: true, size: 2, severity: severity, icon: headerIcon, children: header })), headerAddition] }), _jsx("div", { className: `${styles.content} ${disableContentBox ? styles.disableContentBox : ''}`, children: children })] }));
5
+ export function Page({ header, subheader, severity, headerIcon, headerAddition, breadcrumbs, disableContentBox, disableTopPadding = true, maxWidth, containScrolling = false, children, }) {
6
+ const maxWidthClass = maxWidth
7
+ ? styles[`maxWidth${maxWidth.charAt(0).toUpperCase()}${maxWidth.slice(1)}`]
8
+ : '';
9
+ const hasHeadline = Boolean(header || subheader || headerAddition);
10
+ return (_jsxs("div", { className: `${styles.container} ${containScrolling ? styles.containScrolling : styles.documentScrolling} ${disableTopPadding ? styles.disableTopPadding : ''} ${maxWidthClass}`, children: [_jsx("div", { className: styles.headerContainer, children: _jsxs("div", { className: styles.headerMain, children: [breadcrumbs ? _jsx(Breadcrumbs, { items: breadcrumbs }) : null, hasHeadline ? (_jsx(Headline, { disableMargin: true, size: 2, severity: severity, icon: headerIcon, subheader: subheader, addition: headerAddition, children: header })) : null] }) }), _jsx("div", { className: `${styles.content} ${disableContentBox ? styles.disableContentBox : ''}`, children: children })] }));
7
11
  }
@@ -1,24 +1,74 @@
1
1
  .container {
2
- padding: var(--spacing-md);
3
2
  box-sizing: border-box;
4
3
  display: flex;
5
4
  flex-direction: column;
6
- gap: var(--spacing-md);
5
+ min-width: 0;
6
+ min-height: 0;
7
+ }
8
+
9
+ .maxWidthSm,
10
+ .maxWidthMd,
11
+ .maxWidthLg {
12
+ margin-inline: auto;
13
+ width: 100%;
14
+ }
15
+
16
+ .maxWidthSm {
17
+ max-width: 560px;
18
+ }
19
+ .maxWidthMd {
20
+ max-width: 768px;
21
+ }
22
+ .maxWidthLg {
23
+ max-width: 1024px;
24
+ }
25
+
26
+ .containScrolling {
7
27
  height: 100%;
28
+ overflow: hidden;
29
+ }
30
+
31
+ .documentScrolling {
32
+ height: auto;
33
+ overflow: visible;
8
34
  }
9
35
 
10
36
  .headerContainer {
11
37
  display: flex;
12
- justify-content: space-between;
13
- align-items: center;
38
+ align-items: flex-start;
14
39
  padding: var(--spacing-lg) 0;
40
+ gap: var(--spacing-md);
41
+ min-width: 0;
42
+ flex: 0 0 auto;
43
+ }
44
+
45
+ .disableTopPadding {
46
+ padding-block-start: 0;
47
+ }
48
+
49
+ .disableTopPadding .headerContainer {
50
+ padding-block-start: 0;
51
+ }
52
+
53
+ .headerMain {
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: var(--spacing-md);
57
+ flex: 1 1 auto;
58
+ min-width: 0;
15
59
  }
16
60
 
17
61
  .content {
18
62
  flex: 1 1 auto;
63
+ min-height: 0;
64
+ min-width: 0;
19
65
  overflow: auto;
20
66
  }
21
67
 
68
+ .documentScrolling .content {
69
+ overflow: visible;
70
+ }
71
+
22
72
  .content:not(.disableContentBox) {
23
73
  padding: var(--spacing-lg);
24
74
  border: 1px solid var(--color-border-default);
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode, JSX } from 'react';
2
2
  interface PanelProps {
3
3
  header: ReactNode;
4
+ subheader?: ReactNode;
4
5
  headerIcon?: ReactNode;
5
6
  headerAddition?: ReactNode;
6
7
  severity?: Severity;
@@ -8,5 +9,5 @@ interface PanelProps {
8
9
  size?: 'sm' | 'md' | 'lg';
9
10
  }
10
11
  import { Severity } from '../../constants/severity.types';
11
- export declare function Panel({ header, headerIcon, headerAddition, children, severity, size, }: PanelProps): JSX.Element;
12
+ export declare function Panel({ header, subheader, headerIcon, headerAddition, children, severity, size, }: PanelProps): JSX.Element;
12
13
  export {};
@@ -2,6 +2,6 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import styles from './Panel.module.css';
4
4
  import { Headline } from '../headline/Headline';
5
- export function Panel({ header, headerIcon, headerAddition, children, severity, size, }) {
6
- return (_jsxs("section", { className: `${styles.container} ${size ? styles[size] : ''}`, children: [_jsx("div", { className: styles.header, children: _jsx(Headline, { disableMargin: true, size: size === 'sm' ? 4 : 3, icon: headerIcon, addition: headerAddition, severity: severity, children: header }) }), _jsx("div", { className: styles.content, children: children })] }));
5
+ export function Panel({ header, subheader, headerIcon, headerAddition, children, severity, size, }) {
6
+ return (_jsxs("section", { className: `${styles.container} ${size ? styles[size] : ''}`, children: [_jsx("div", { className: styles.header, children: _jsx(Headline, { disableMargin: true, size: size === 'sm' ? 4 : 3, icon: headerIcon, addition: headerAddition, subheader: subheader, severity: severity, children: header }) }), _jsx("div", { className: styles.content, children: children })] }));
7
7
  }
@@ -219,7 +219,7 @@ export const Popover = forwardRef(function Popover({ trigger: Trigger, children,
219
219
  return;
220
220
  (_b = (_a = triggerElRef.current) === null || _a === void 0 ? void 0 : _a.focus) === null || _b === void 0 ? void 0 : _b.call(_a);
221
221
  }, [isOpen, returnFocus]);
222
- const icon = isOpen ? _jsx(ChevronUp, { size: 20 }) : _jsx(ChevronDown, { size: 20 });
222
+ const icon = isOpen ? (_jsx(ChevronUp, { className: "dbc-muted-text", size: 20 })) : (_jsx(ChevronDown, { className: "dbc-muted-text", size: 20 }));
223
223
  const setOverlayRef = React.useCallback((node) => {
224
224
  assignRef(overlayRef, node);
225
225
  }, [overlayRef]);
@@ -0,0 +1,16 @@
1
+ import React, { ElementType } from 'react';
2
+ type GapSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';
3
+ type StackOwnProps = {
4
+ direction?: 'row' | 'column';
5
+ gap?: GapSize;
6
+ align?: 'start' | 'center' | 'end';
7
+ justify?: 'start' | 'center' | 'end' | 'between';
8
+ grow?: boolean;
9
+ wrap?: boolean;
10
+ };
11
+ export type StackProps<C extends ElementType = 'div'> = StackOwnProps & {
12
+ as?: C;
13
+ } & Omit<React.ComponentPropsWithRef<C>, keyof StackOwnProps | 'as'>;
14
+ type StackComponent = <C extends ElementType = 'div'>(props: StackProps<C>) => React.ReactElement | null;
15
+ export declare const Stack: StackComponent;
16
+ export {};
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { forwardRef } from 'react';
4
+ export const Stack = forwardRef(function Stack({ as, direction, gap, align, justify, grow = false, wrap = false, className, ...rest }, ref) {
5
+ const Tag = (as !== null && as !== void 0 ? as : 'div');
6
+ const classes = [
7
+ 'dbc-flex',
8
+ direction === 'column' ? 'dbc-flex-column' : undefined,
9
+ gap ? `dbc-gap-${gap}` : undefined,
10
+ align ? `dbc-items-${align}` : undefined,
11
+ justify ? `dbc-justify-${justify}` : undefined,
12
+ grow ? 'dbc-flex-grow' : undefined,
13
+ wrap ? 'dbc-flex-wrap' : undefined,
14
+ className,
15
+ ]
16
+ .filter(Boolean)
17
+ .join(' ');
18
+ return _jsx(Tag, { ref: ref, className: classes, ...rest });
19
+ });
@@ -1,9 +1,10 @@
1
1
  import { ReactNode } from 'react';
2
2
  interface StatePageProps {
3
3
  header?: string;
4
+ subheader?: ReactNode;
4
5
  type: 'error' | 'empty' | 'info' | 'notfound';
5
6
  children?: ReactNode;
6
7
  actions?: ReactNode;
7
8
  }
8
- export declare function StatePage({ header, type, children, actions }: StatePageProps): ReactNode;
9
+ export declare function StatePage({ header, subheader, type, children, actions, }: StatePageProps): ReactNode;
9
10
  export {};