@olenbetong/appframe-ds 1.3.7 → 1.4.0
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.
- package/CHANGELOG.md +13 -0
- package/package.json +4 -4
- package/src/AfLookup/Lookup.css +2 -1
- package/src/AfLookup/LookupCombobox.css +6 -12
- package/src/AfLookup/LookupCombobox.tsx +1 -1
- package/src/AfLookup/LookupGrid.css +7 -12
- package/src/container/Container.tsx +7 -6
- package/src/filter/FilterBuilder.tsx +1 -1
- package/src/layout/AppMenuDrawer.css +2 -1
- package/src/layout/DialogMotion.css +77 -0
- package/src/layout/PageContainer.css +5 -5
- package/src/layout/PageContainer.tsx +2 -2
- package/src/layout/index.tsx +1 -0
- package/src/page/Page.css +5 -1
- package/src/page/PageBlock.css +8 -8
- package/src/page/PageBlock.tsx +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @olenbetong/appframe-ds
|
|
2
2
|
|
|
3
|
+
## 1.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8ec7b62: One open and close motion for centred dialogs: Designsystemet's `Dialog` (the filter builder and every other centred one) and anything with the new `ob-dialog-motion` class now fade and rise in over 180 ms and play the same motion in reverse over 140 ms when closed, using transitions with `@starting-style` and `allow-discrete` instead of Designsystemet's open-only keyframes. Reduced motion keeps the fade and drops the movement. The filter builder now closes on a backdrop click, and the page content slides back when a docked `AppMenuDrawer` closes instead of jumping.
|
|
8
|
+
|
|
9
|
+
## 1.3.8
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 2c36a7c: The `Page.Block`, `Container` and `PageContainer` widths are resized for the 2026 site's 14px root font size (87.5%), and stay in rem so they follow the browser's font size: `text` 41rem, `md` 55rem, `lg` 73rem, `xl` 110rem - 574, 770, 1022 and 1540px, the MUI-era widths the apps were laid out for. At 16px-based rem they had come out an eighth narrower, and `xl` (80rem) at 1120px against MUI's 1536px. `Page.Block width="2xl"` (90rem) would now be narrower than `xl`, so it is deprecated and renders the same as `xl`.
|
|
14
|
+
- 2d14c97: `AfLookup`, `AfLookupEdit` and the lookup grid follow dark mode: the dialog, list, borders and the hover and keyboard-active rows use Designsystemet colour tokens instead of hard-coded light colours, so item text is no longer white on white. On desktop the rows get 4px of vertical padding, so the items no longer sit flush against each other.
|
|
15
|
+
|
|
3
16
|
## 1.3.7
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olenbetong/appframe-ds",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Components that bind Designsystemet components to Appframe data objects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./es/index.d.ts",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"@atlaskit/pragmatic-drag-and-drop": "4.0.0",
|
|
64
64
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "3.0.0",
|
|
65
65
|
"@base-ui/react": "1.8.0",
|
|
66
|
-
"@olenbetong/appframe-core": "2.15.
|
|
67
|
-
"@olenbetong/appframe-data": "1.8.2",
|
|
68
|
-
"@olenbetong/appframe-react": "2.2.7",
|
|
66
|
+
"@olenbetong/appframe-core": "^2.15.2",
|
|
67
|
+
"@olenbetong/appframe-data": "^1.8.2",
|
|
68
|
+
"@olenbetong/appframe-react": "^2.2.7",
|
|
69
69
|
"clsx": "^2.1.1",
|
|
70
70
|
"dockview-react": "8.3.1",
|
|
71
71
|
"localforage": "^1.10.0",
|
package/src/AfLookup/Lookup.css
CHANGED
|
@@ -15,13 +15,12 @@
|
|
|
15
15
|
.ObCombobox-listWrap {
|
|
16
16
|
overflow: hidden;
|
|
17
17
|
min-height: 0;
|
|
18
|
-
border: 1px solid
|
|
18
|
+
border: 1px solid var(--ds-color-neutral-border-subtle);
|
|
19
19
|
border-radius: 0.25rem;
|
|
20
|
-
background-color:
|
|
20
|
+
background-color: var(--ds-color-neutral-background-default);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.ObCombobox-list {
|
|
24
|
-
border: 1px solid rgb(0 0 0 / 0.06);
|
|
25
24
|
height: 100%;
|
|
26
25
|
overflow-y: hidden;
|
|
27
26
|
overscroll-behavior: contain;
|
|
@@ -31,23 +30,18 @@
|
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
.ObCombobox-input {
|
|
34
|
-
background-color:
|
|
33
|
+
background-color: var(--ds-color-neutral-background-default);
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
.ObCombobox-listItem {
|
|
38
|
-
--active-color: oklch(from var(--brand-secondary, #999) l c h / 50%);
|
|
39
37
|
cursor: pointer;
|
|
40
38
|
|
|
41
39
|
&.active {
|
|
42
|
-
background-color: var(--
|
|
40
|
+
background-color: var(--ds-color-neutral-surface-active);
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
&:hover {
|
|
46
|
-
background-color:
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
&.active:hover {
|
|
50
|
-
background-color: oklch(from var(--active-color) calc(l + 0.1) calc(c - 0.04) h);
|
|
44
|
+
background-color: var(--ds-color-neutral-surface-hover);
|
|
51
45
|
}
|
|
52
46
|
}
|
|
53
47
|
|
|
@@ -55,7 +49,7 @@
|
|
|
55
49
|
position: relative;
|
|
56
50
|
height: 4px;
|
|
57
51
|
overflow: hidden;
|
|
58
|
-
background-color:
|
|
52
|
+
background-color: var(--ds-color-neutral-surface-tinted);
|
|
59
53
|
}
|
|
60
54
|
|
|
61
55
|
.ObCombobox-progress-bar {
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
height: 100%;
|
|
3
3
|
overflow: hidden;
|
|
4
4
|
overscroll-behavior: contain;
|
|
5
|
-
border: 1px solid
|
|
5
|
+
border: 1px solid var(--ds-color-neutral-border-subtle);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
.ObLookupGrid-header {
|
|
9
9
|
display: grid;
|
|
10
10
|
height: 40px;
|
|
11
11
|
align-items: center;
|
|
12
|
-
border-bottom: 1px solid
|
|
13
|
-
background-color:
|
|
12
|
+
border-bottom: 1px solid var(--ds-color-neutral-border-default);
|
|
13
|
+
background-color: var(--ds-color-neutral-background-tinted);
|
|
14
14
|
font-weight: 600;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -22,22 +22,17 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
.ObLookupGrid-row {
|
|
25
|
-
--active-color: oklch(from var(--brand-secondary, #999) l c h / 50%);
|
|
26
25
|
display: grid;
|
|
27
26
|
align-items: center;
|
|
28
27
|
cursor: pointer;
|
|
29
|
-
border-bottom: 1px solid
|
|
28
|
+
border-bottom: 1px solid var(--ds-color-neutral-border-subtle);
|
|
30
29
|
|
|
31
30
|
&.active {
|
|
32
|
-
background-color: var(--
|
|
31
|
+
background-color: var(--ds-color-neutral-surface-active);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
&:hover {
|
|
36
|
-
background-color:
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
&.active:hover {
|
|
40
|
-
background-color: oklch(from var(--active-color) calc(l + 0.1) calc(c - 0.04) h);
|
|
35
|
+
background-color: var(--ds-color-neutral-surface-hover);
|
|
41
36
|
}
|
|
42
37
|
}
|
|
43
38
|
|
|
@@ -51,7 +46,7 @@
|
|
|
51
46
|
white-space: nowrap;
|
|
52
47
|
|
|
53
48
|
&.active {
|
|
54
|
-
outline: 2px solid
|
|
49
|
+
outline: 2px solid var(--ds-color-neutral-border-strong);
|
|
55
50
|
outline-offset: -2px;
|
|
56
51
|
}
|
|
57
52
|
}
|
|
@@ -14,13 +14,14 @@ const maxWidthToBlockWidth: Record<ContainerMaxWidth, PageBlockWidth> = {
|
|
|
14
14
|
|
|
15
15
|
export type ContainerProps = Omit<PageBlockProps, "width"> & {
|
|
16
16
|
/**
|
|
17
|
-
* Predefined max-width,
|
|
18
|
-
* horizontally centered.
|
|
17
|
+
* Predefined max-width, with the MUI `Container` names on the `Page.Block` scale. Content is
|
|
18
|
+
* horizontally centered. Pixel widths are at the 2026 site's 14px root font size; the
|
|
19
|
+
* rem values follow the browser's font size setting.
|
|
19
20
|
*
|
|
20
|
-
* - `xs`/`sm`:
|
|
21
|
-
* - `md`:
|
|
22
|
-
* - `lg`:
|
|
23
|
-
* - `xl`:
|
|
21
|
+
* - `xs`/`sm`: 41rem (574px) — recommended line-length for running text
|
|
22
|
+
* - `md`: 55rem (770px)
|
|
23
|
+
* - `lg`: 73rem (1022px)
|
|
24
|
+
* - `xl`: 110rem (1540px)
|
|
24
25
|
* - `false`: no max-width
|
|
25
26
|
*
|
|
26
27
|
* @default "lg"
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
background-color: var(--ds-color-neutral-background-default, #fff);
|
|
19
19
|
color: var(--ds-color-neutral-text-default, #1e2b3c);
|
|
20
20
|
transform: translateX(-100%);
|
|
21
|
-
|
|
21
|
+
/* Same timing as the content offset in Page.css, so the two edges move together. */
|
|
22
|
+
transition: transform 225ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
22
23
|
overflow: hidden;
|
|
23
24
|
display: flex;
|
|
24
25
|
flex-direction: column;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* One open and close motion for every centred modal: Designsystemet's Dialog (the filter builder,
|
|
3
|
+
* the site search, the report launcher and any app's own dialogs) and anything else that opts in
|
|
4
|
+
* with the `ob-dialog-motion` class (the chrome's app menu, which is a plain <dialog>).
|
|
5
|
+
*
|
|
6
|
+
* Designsystemet animates the opening with keyframes only, 300 ms, and nothing on close. This
|
|
7
|
+
* replaces that with transitions, so the close plays the same motion in reverse:
|
|
8
|
+
* - @starting-style gives the first frame after showModal() something to transition from;
|
|
9
|
+
* - `display` and `overlay` transition with `allow-discrete`, which keeps the dialog in the top
|
|
10
|
+
* layer until the fade out has finished after close().
|
|
11
|
+
* Browsers without `overlay` (Firefox, Safari at the time of writing) still animate the opening
|
|
12
|
+
* and close without the fade; nothing breaks.
|
|
13
|
+
*
|
|
14
|
+
* A dialog only fades out when it is closed with close() and stays mounted. One that React
|
|
15
|
+
* removes on close disappears at once.
|
|
16
|
+
*
|
|
17
|
+
* Reduced motion keeps a short fade and drops the movement.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
--ob-dialog-enter-duration: 180ms;
|
|
22
|
+
--ob-dialog-exit-duration: 140ms;
|
|
23
|
+
--ob-dialog-offset: 1rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@media (prefers-reduced-motion: reduce) {
|
|
27
|
+
:root {
|
|
28
|
+
--ob-dialog-offset: 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.ds-dialog:is(:not([data-placement]), [data-placement="center"]),
|
|
33
|
+
.ob-dialog-motion {
|
|
34
|
+
opacity: 0;
|
|
35
|
+
translate: 0 var(--ob-dialog-offset);
|
|
36
|
+
transition-property: opacity, translate, overlay, display;
|
|
37
|
+
transition-duration: var(--ob-dialog-exit-duration);
|
|
38
|
+
transition-timing-function: ease-in;
|
|
39
|
+
transition-behavior: allow-discrete;
|
|
40
|
+
|
|
41
|
+
&[open] {
|
|
42
|
+
opacity: 1;
|
|
43
|
+
translate: 0 0;
|
|
44
|
+
/* Designsystemet's keyframes would play on top of the transition. */
|
|
45
|
+
animation: none;
|
|
46
|
+
transition-duration: var(--ob-dialog-enter-duration);
|
|
47
|
+
transition-timing-function: ease-out;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&::backdrop {
|
|
51
|
+
opacity: 0;
|
|
52
|
+
animation: none;
|
|
53
|
+
transition-property: opacity, overlay, display;
|
|
54
|
+
transition-duration: var(--ob-dialog-exit-duration);
|
|
55
|
+
transition-timing-function: ease-in;
|
|
56
|
+
transition-behavior: allow-discrete;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&[open]::backdrop {
|
|
60
|
+
opacity: 1;
|
|
61
|
+
transition-duration: var(--ob-dialog-enter-duration);
|
|
62
|
+
transition-timing-function: ease-out;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@starting-style {
|
|
67
|
+
.ds-dialog:is(:not([data-placement]), [data-placement="center"])[open],
|
|
68
|
+
.ob-dialog-motion[open] {
|
|
69
|
+
opacity: 0;
|
|
70
|
+
translate: 0 var(--ob-dialog-offset);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.ds-dialog:is(:not([data-placement]), [data-placement="center"])[open]::backdrop,
|
|
74
|
+
.ob-dialog-motion[open]::backdrop {
|
|
75
|
+
opacity: 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -23,21 +23,21 @@
|
|
|
23
23
|
height: 100%;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/* The content width on the
|
|
26
|
+
/* The content width on the Page.Block scale (rem for a 14px root); the gutters come on top. */
|
|
27
27
|
.ObPageContainer-inner.ObPageContainer-text {
|
|
28
|
-
max-width: calc(
|
|
28
|
+
max-width: calc(41rem + 2 * var(--ob-page-container-gutter));
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
.ObPageContainer-inner.ObPageContainer-md {
|
|
32
|
-
max-width: calc(
|
|
32
|
+
max-width: calc(55rem + 2 * var(--ob-page-container-gutter));
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.ObPageContainer-inner.ObPageContainer-lg {
|
|
36
|
-
max-width: calc(
|
|
36
|
+
max-width: calc(73rem + 2 * var(--ob-page-container-gutter));
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.ObPageContainer-inner.ObPageContainer-xl {
|
|
40
|
-
max-width: calc(
|
|
40
|
+
max-width: calc(110rem + 2 * var(--ob-page-container-gutter));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -8,8 +8,8 @@ export type PageContainerMaxWidth = "xs" | "sm" | "md" | "lg" | "xl" | false;
|
|
|
8
8
|
export type PageContainerProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
9
9
|
fullHeight?: boolean;
|
|
10
10
|
/**
|
|
11
|
-
* Predefined max-width of the content, on the
|
|
12
|
-
* `md`
|
|
11
|
+
* Predefined max-width of the content, on the `Page.Block` scale (`xs`/`sm` 41rem,
|
|
12
|
+
* `md` 55rem, `lg` 73rem, `xl` 110rem, plus the gutters). The content stays against the
|
|
13
13
|
* leading edge, as the MUI-era `PageContainer` did; `Page.Block`/`Container` centre it.
|
|
14
14
|
* @default max-width: 100%
|
|
15
15
|
*/
|
package/src/layout/index.tsx
CHANGED
package/src/page/Page.css
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
rather than the viewport. That is what keeps it clear of a site toolbar rendered
|
|
17
17
|
above the app, without needing to know the toolbar's height. */
|
|
18
18
|
position: relative;
|
|
19
|
+
/* On the base rule, not the drawer-open one below: the content has to slide back when the
|
|
20
|
+
drawer closes too, and a transition declared only where the padding is set stops
|
|
21
|
+
applying the moment that rule stops matching. Same timing as the drawer itself
|
|
22
|
+
(AppMenuDrawer.css), so the content edge follows the drawer edge. */
|
|
23
|
+
transition: padding-left 225ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
.ObPage-document {
|
|
@@ -35,7 +40,6 @@
|
|
|
35
40
|
/* Offset content when a docked Page.Header drawer is open (desktop) */
|
|
36
41
|
.ObPage-root:has(.ObPageHeader-drawer.ObPageHeader-drawerDocked.ObPageHeader-drawerOpen) {
|
|
37
42
|
padding-left: var(--ob-page-drawer-width, 20rem);
|
|
38
|
-
transition: padding-left 225ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
|
package/src/page/PageBlock.css
CHANGED
|
@@ -4,24 +4,24 @@
|
|
|
4
4
|
margin-inline: auto;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
/* The widths are in rem for a 14px root (the 2026 site's 87.5%), so they follow the browser's
|
|
8
|
+
font size: text 574px, md 770px, lg 1022px, xl 1540px at the default setting. */
|
|
7
9
|
.ObPageBlock-text {
|
|
8
|
-
max-width: calc(
|
|
10
|
+
max-width: calc(41rem + 2 * var(--ob-page-gutter, 0rem));
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
.ObPageBlock-md {
|
|
12
|
-
max-width:
|
|
14
|
+
max-width: 55rem;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
.ObPageBlock-lg {
|
|
16
|
-
max-width:
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.ObPageBlock-xl {
|
|
20
|
-
max-width: 80rem;
|
|
18
|
+
max-width: 73rem;
|
|
21
19
|
}
|
|
22
20
|
|
|
21
|
+
/* 2xl is a deprecated alias: at 90rem it had become narrower than xl. */
|
|
22
|
+
.ObPageBlock-xl,
|
|
23
23
|
.ObPageBlock-2xl {
|
|
24
|
-
max-width:
|
|
24
|
+
max-width: 110rem;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/* Against the leading edge instead of centred in the space left over. */
|
package/src/page/PageBlock.tsx
CHANGED
|
@@ -44,13 +44,14 @@ export type PageBlockProps = React.HTMLAttributes<HTMLElement> & {
|
|
|
44
44
|
*/
|
|
45
45
|
overflow?: "auto" | "hidden";
|
|
46
46
|
/**
|
|
47
|
-
* Predefined max-width. Content is horizontally centered.
|
|
47
|
+
* Predefined max-width. Content is horizontally centered. Pixel widths are at the 2026
|
|
48
|
+
* site's 14px root font size; the rem values follow the browser's font size setting.
|
|
48
49
|
*
|
|
49
|
-
* - `text`:
|
|
50
|
-
* - `md`:
|
|
51
|
-
* - `lg`:
|
|
52
|
-
* - `xl`:
|
|
53
|
-
* - `2xl`:
|
|
50
|
+
* - `text`: 41rem (574px) — recommended line-length for running text
|
|
51
|
+
* - `md`: 55rem (770px)
|
|
52
|
+
* - `lg`: 73rem (1022px)
|
|
53
|
+
* - `xl`: 110rem (1540px)
|
|
54
|
+
* - `2xl`: deprecated, the same as `xl`
|
|
54
55
|
*
|
|
55
56
|
* @default max-width: 100%
|
|
56
57
|
*/
|