@qtoggle/qui 1.20.0-alpha.4 → 1.20.0-alpha.5

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.
@@ -9,8 +9,8 @@ div.qui-global-glass {
9
9
  left: 0;
10
10
  right: 0;
11
11
  bottom: 0;
12
+ /* backdrop-filter is set once below and never changes, so listing it here only ever cost a property to watch */
12
13
  transition: opacity @transition-duration ease,
13
- backdrop-filter @transition-duration linear,
14
14
  margin-top @transition-duration linear;
15
15
  opacity: 0;
16
16
  display: flex;
package/less/lists.less CHANGED
@@ -29,10 +29,15 @@ div.qui-list-child {
29
29
 
30
30
  div.qui-list-child.qui-list-item {
31
31
 
32
- /* Nothing inside an item is ever painted outside of it, since div.qui-list-child above already clips with
33
- * overflow: hidden. Containment is therefore visually inert here, but it lets the engine scope layout and style
34
- * invalidation to the single row that changed, instead of the whole list, and skip painting off-screen rows. */
35
- contain: layout style paint;
32
+ /* No `contain` here, deliberately. Layout or paint containment makes each row an independent unit for pixel
33
+ * snapping, and the separator below is a 0.0625em border -- one device pixel at the default font size, but a
34
+ * fractional one as soon as the page is zoomed or the root font size is not 16px. Snapped per row rather than
35
+ * across the list, some of those borders round away to nothing and the separator simply vanishes for a few rows.
36
+ * Reproduced at a 53.6px row pitch: 7 of 10 separators drawn with containment, 10 of 10 without. `contain: paint`
37
+ * alone and `contain: layout style` alone each do it; only `contain: style` is safe, and that buys nothing.
38
+ *
39
+ * The off-screen saving is not lost: content-visibility on the icon-label view below implies containment on that
40
+ * element, which carries no border of its own. */
36
41
 
37
42
  &.hidden {
38
43
  opacity: 0;
package/less/main-ui.less CHANGED
@@ -24,11 +24,13 @@ div.qui-main-container-glass {
24
24
  right: 0;
25
25
  bottom: 0;
26
26
  left: 0;
27
- transition: backdrop-filter @transition-duration linear;
28
- }
27
+ opacity: 0;
29
28
 
30
- div.qui-main-container-glass.visible {
29
+ /* The filter is constant and only the opacity of the filtered layer is animated. Transitioning backdrop-filter
30
+ * itself gives the compositor a different filter to apply on every frame, across the whole viewport, and nothing
31
+ * it can cache. There is no cost while hidden: VisibilityManager sets display: none once the fade has finished. */
31
32
  backdrop-filter: @modal-background-filter;
33
+ transition: opacity @transition-duration linear;
32
34
 
33
35
  /* Workaround for Firefox that doesn't support backdrop-filter property */
34
36
  @supports (-moz-appearance:none) {
@@ -36,6 +38,10 @@ div.qui-main-container-glass.visible {
36
38
  }
37
39
  }
38
40
 
41
+ div.qui-main-container-glass.visible {
42
+ opacity: 1;
43
+ }
44
+
39
45
  div.qui-pages-container {
40
46
  height: 100%;
41
47
  }
@@ -27,10 +27,36 @@ div.qui-page.visible {
27
27
  z-index: 1;
28
28
  }
29
29
 
30
- body.small-screen > div.qui-main-container > div.qui-pages-container > div.qui-page.visible,
31
- body.small-screen > div.qui-global-glass > div.qui-global-glass-container > div.qui-page.visible {
30
+ /* On a small screen a page is always exactly as wide as its container, so translateX(100%) lands in the very same
31
+ * place as left: 100% -- but on the compositor, instead of relayouting and repainting both page subtrees on every
32
+ * frame of the slide.
33
+ *
34
+ * The resting state is deliberately `transform: none` and not `translateX(0)`: any transform other than `none` makes
35
+ * the page a containing block for its `position: fixed` descendants, which would unpin the form button bar (see
36
+ * forms/form.less). Interpolating out of `none` animates perfectly well, and while a page is actually sliding, its
37
+ * button bar travelling with it is what one wants anyway.
38
+ *
39
+ * The desktop column layout deliberately stays on `left`/`width`: there a page is narrower than its container, so
40
+ * translateX(100%) would not carry it clear of the viewport, and the slide distance would have to be computed per
41
+ * page against its own width. */
42
+ body.small-screen > div.qui-main-container > div.qui-pages-container > div.qui-page,
43
+ body.small-screen > div.qui-global-glass > div.qui-global-glass-container > div.qui-page {
32
44
  width: 100% !important;
33
45
  left: 0 !important;
46
+ transform: translateX(100%);
47
+ transition: opacity @transition-duration ease-out,
48
+ transform @transition-duration ease;
49
+
50
+ &.attached {
51
+ transform: translateX(-100%);
52
+ }
53
+
54
+ /* Popups fade in place; they never slide */
55
+ &.popup,
56
+ &.visible {
57
+ transform: none;
58
+ }
59
+
34
60
  }
35
61
 
36
62
  div.qui-page.current {
@@ -20,7 +20,7 @@ div.qui-check-button {
20
20
  transition+: background @transition-duration ease,
21
21
  color @transition-duration ease,
22
22
  opacity @transition-duration ease,
23
- border @transition-duration ease;
23
+ border-color @transition-duration ease;
24
24
  .qui-focusable-widget();
25
25
 
26
26
  &:FOCUS {
@@ -4,11 +4,14 @@
4
4
  @import (reference) "common";
5
5
 
6
6
 
7
+ /* border-color, not the border shorthand: the width and style of these borders are set once and never animate, so
8
+ * naming the colour keeps the fade while leaving border-width and border-style -- the two that would cost layout --
9
+ * out of the transition entirely. */
7
10
  .qui-base-button {
8
11
  transition: background @transition-duration ease,
9
12
  color @transition-duration ease,
10
13
  opacity @transition-duration ease,
11
- border @transition-duration ease;
14
+ border-color @transition-duration ease;
12
15
  box-sizing: border-box;
13
16
  cursor: pointer;
14
17
  .noselect;
@@ -73,7 +76,7 @@
73
76
  transition+: background @transition-duration ease,
74
77
  color @transition-duration ease,
75
78
  opacity @transition-duration ease,
76
- border @transition-duration ease;
79
+ border-color @transition-duration ease;
77
80
  .qui-focusable-widget();
78
81
 
79
82
  &:FOCUS {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qtoggle/qui",
3
3
  "description": "A JavaScript UI library with batteries included.",
4
- "version": "1.20.0-alpha.4",
4
+ "version": "1.20.0-alpha.5",
5
5
  "author": {
6
6
  "name": "Calin Crisan",
7
7
  "email": "ccrisan@gmail.com"
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "qui-server"
3
- version = "1.20.0-alpha.4"
3
+ version = "1.20.0-alpha.5"
4
4
  description = "A fully fledged qToggle implementation written in Python"
5
5
  authors = [
6
6
  {name = "Calin Crisan", email = "ccrisan@gmail.com"},