@threadlabs/looma 0.10.0 → 0.10.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -1,36 +1,83 @@
1
1
  /* Generated by HTML Next 1.0.0-alpha.3. Do not edit. */
2
2
  @scope ([data-component~="ui-editor-toolbar"]) to ([data-component], [data-slotted]) {
3
3
  :scope {
4
+ /* The colour the edge fades blend into: whatever the toolbar is painted with. */
5
+ --_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
6
+
4
7
  position: sticky;
5
8
  top: 0;
6
9
  z-index: var(--ui-editor-toolbar-z-index, 10);
7
10
  display: flex;
8
11
  align-items: center;
9
- justify-content: flex-start;
10
- gap: var(--ui-editor-toolbar-gap, 2px);
11
12
  padding: var(--ui-editor-toolbar-padding-block, 6px) var(--ui-editor-toolbar-padding-inline, 12px);
12
13
  min-height: var(--ui-editor-toolbar-min-height, 48px);
13
- /* More controls than the column is wide is normal at a readable measure, so the row wraps.
14
- Scrolling hid the tail behind an invisible scrollbar. */
15
- flex-wrap: wrap;
16
- row-gap: var(--ui-editor-toolbar-row-gap, var(--ui-editor-toolbar-gap, 2px));
17
14
  background: var(--ui-editor-toolbar-surface, var(--ui-surface));
18
15
  border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
19
16
  }
20
17
 
21
- :scope::-webkit-scrollbar {
18
+ /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than
19
+ wrapping into several lines, and a fade at each edge that has more to show says so. */
20
+ .strip {
21
+ display: flex;
22
+ flex: 1 1 auto;
23
+ align-items: center;
24
+ justify-content: flex-start;
25
+ gap: var(--ui-editor-toolbar-gap, 2px);
26
+ min-width: 0;
27
+ overflow-x: auto;
28
+ overflow-y: hidden;
29
+ overscroll-behavior-inline: contain;
30
+ scrollbar-width: none;
31
+ }
32
+
33
+ .strip::-webkit-scrollbar {
22
34
  display: none;
23
35
  }
24
36
 
37
+ /* The fades are mattes laid over the strip in the toolbar's own colour, not a mask, so a floating
38
+ toolbar's border and shadow stay whole. Each appears only while that edge hides controls. */
39
+ :scope::before,
40
+ :scope::after {
41
+ position: absolute;
42
+ z-index: 1;
43
+ inset-block: 0;
44
+ inline-size: var(--ui-editor-toolbar-fade-size, 32px);
45
+ content: "";
46
+ opacity: 0;
47
+ pointer-events: none;
48
+ transition: opacity var(--ui-motion-fast, 120ms) var(--ui-motion-ease, ease);
49
+ }
50
+
51
+ :scope::before {
52
+ inset-inline-start: 0;
53
+ background: linear-gradient(to right, var(--_matte), transparent);
54
+ }
55
+
56
+ :scope::after {
57
+ inset-inline-end: 0;
58
+ background: linear-gradient(to left, var(--_matte), transparent);
59
+ }
60
+
61
+ :scope:dir(rtl)::before {
62
+ background: linear-gradient(to left, var(--_matte), transparent);
63
+ }
64
+
65
+ :scope:dir(rtl)::after {
66
+ background: linear-gradient(to right, var(--_matte), transparent);
67
+ }
68
+
69
+ :scope[data-ui-editor-toolbar-state~="overflowStart"]::before,
70
+ :scope[data-ui-editor-toolbar-state~="overflowEnd"]::after {
71
+ opacity: 1;
72
+ }
73
+
25
74
  :scope[data-ui-editor-toolbar-state~="floating"] {
26
- flex-wrap: nowrap;
27
- position: static;
75
+ position: relative;
28
76
  top: auto;
29
77
  width: max-content;
30
78
  max-width: min(calc(100vw - 24px), 100%);
31
79
  min-height: auto;
32
80
  padding: var(--ui-editor-toolbar-floating-padding, 4px);
33
- overflow-x: visible;
34
81
  background: color-mix(in srgb, var(--ui-editor-toolbar-surface, var(--ui-surface)) 96%, transparent);
35
82
  border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
36
83
  border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));
@@ -52,7 +99,7 @@
52
99
  }
53
100
 
54
101
  :scope[data-ui-editor-toolbar-state~="floating"] {
55
- position: static;
102
+ position: relative;
56
103
  inset: auto;
57
104
  min-height: auto;
58
105
  border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
@@ -63,9 +110,10 @@
63
110
 
64
111
  /* Inside LoomaEditor's sticky shell, the shell is the sticky surface. */
65
112
  .looma-editor__sticky-toolbar-shell :scope {
66
- position: static;
113
+ --_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
114
+
115
+ position: relative;
67
116
  min-height: var(--ui-editor-toolbar-min-height, 48px);
68
- overscroll-behavior-inline: contain;
69
117
  background: transparent;
70
118
  border: 0;
71
119
  box-shadow: none;
@@ -77,10 +125,6 @@
77
125
  max-width: none;
78
126
  min-height: 100%;
79
127
  padding: 0;
80
- overflow-x: auto;
81
- overflow-y: hidden;
82
- overscroll-behavior-inline: contain;
83
- scroll-snap-type: x mandatory;
84
128
  background: transparent;
85
129
  border: 0;
86
130
  border-radius: 0;
@@ -88,16 +132,26 @@
88
132
  backdrop-filter: none;
89
133
  }
90
134
 
135
+ .looma-editor__mobile-toolbar-shell :scope[data-ui-editor-toolbar-state~="floating"] .strip {
136
+ scroll-snap-type: x mandatory;
137
+ }
138
+
91
139
  /* A component that sets its display still honours the hidden attribute on its root. */
92
140
  :scope[hidden] {
93
141
  display: none;
94
142
  }
95
143
  }
96
144
  @scope ([data-component~="ui-editor-toolbar"]) to ([data-component]) {
97
- :scope > :where([data-slotted], [data-slotted] *):is(*) {
145
+ /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than
146
+ wrapping into several lines, and a fade at each edge that has more to show says so. */
147
+
148
+ .strip > :where([data-slotted], [data-slotted] *):is(*) {
98
149
  flex: 0 0 auto;
99
150
  }
100
151
 
152
+ /* The fades are mattes laid over the strip in the toolbar's own colour, not a mask, so a floating
153
+ toolbar's border and shadow stay whole. Each appears only while that edge hides controls. */
154
+
101
155
  :where([data-slotted], [data-slotted] *):is(.divider) {
102
156
  width: 1px;
103
157
  height: 20px;
@@ -1,11 +1,13 @@
1
1
  // Generated by HTML Next 1.0.0-alpha.3 for Vanilla DOM. Do not edit.
2
- import { manageGeneratedProps } from "@nextwebwg/html-next/generated-runtime";
2
+ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
+ import * as controller from "../components/ui-editor-toolbar/ui-editor-toolbar.js";
3
4
  import "../styles/ui-editor-toolbar.css";
4
5
 
6
+ const definition = {...{"contract":{"tag":"ui-editor-toolbar","props":{"floating":{"type":"boolean","required":false,"target":{"attribute":"floating"},"default":false}}},"template":{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"role","value":"toolbar"},{"kind":"literal","name":"aria-label","value":"Editor toolbar"}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"strip"}],"children":[{"kind":"slot"}],"ref":"strip"}]},"declarations":[{"kind":"state","name":"overflowStart","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"state","name":"overflowEnd","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}}],"root":{"kind":"native","element":"div","choices":["div"]}},source:{file:import.meta.url},css:""};
7
+
5
8
  export function createUiEditorToolbar(options = {}) {
6
9
  const { attributes = {}, children = [], slots = {}, as, ...componentProps } = options;
7
10
  const projected = [];
8
- const prop0 = componentProps["floating"] === undefined ? false : componentProps["floating"];
9
11
  const element = document.createElement("div");
10
12
  for (const [name, value] of Object.entries(attributes)) {
11
13
  if (value === null || value === undefined || value === false) continue;
@@ -14,17 +16,20 @@ export function createUiEditorToolbar(options = {}) {
14
16
  if (!element.hasAttribute("role")) element.setAttribute("role", "toolbar");
15
17
  if (!element.hasAttribute("aria-label")) element.setAttribute("aria-label", "Editor toolbar");
16
18
  element.setAttribute("data-component", "ui-editor-toolbar");
19
+ const element0 = document.createElement("div");
20
+ element0.setAttribute("class", "strip");
17
21
  if (children.length > 0) {
18
22
  for (const child of children) {
19
23
  const node = typeof child === "string" ? document.createTextNode(child) : child;
20
24
  projected.push([node, ""]);
21
- element.append(node);
25
+ element0.append(node);
22
26
  }
23
27
  } else {
24
28
  }
25
- manageGeneratedProps(element, [
26
- { name: "floating", attribute: "data-floating", value: componentProps["floating"], default: false, type: "boolean", required: false },
27
- ]);
29
+ element.append(element0);
30
+ manageComponentLifecycle(element, definition, { props: componentProps, projected,
31
+ controller,
32
+ });
28
33
  return element;
29
34
  }
30
35
 
@@ -1,6 +1,8 @@
1
1
  <!-- Generated by HTML Next 1.0.0-alpha.3 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { computed } from 'vue'
3
+ import { computed, ref, useTemplateRef } from 'vue'
4
+ import * as controllerModule from '../components/ui-editor-toolbar/ui-editor-toolbar.js'
5
+ import { createDispatch, useComponentHost } from './host'
4
6
 
5
7
  defineOptions({ inheritAttrs: false })
6
8
 
@@ -13,12 +15,29 @@ const props = withDefaults(
13
15
  },
14
16
  )
15
17
 
18
+ const root = ref<HTMLElement | null>(null)
19
+ const stripElement = useTemplateRef<HTMLElement>('strip')
20
+ const overflowStart = ref(false)
21
+ const overflowEnd = ref(false)
22
+
16
23
  /** The values the styles' :host-state() rules test. */
17
24
  const hostState = computed(() =>
18
25
  [
26
+ overflowStart.value && 'overflowStart',
27
+ overflowEnd.value && 'overflowEnd',
19
28
  props.floating && 'floating',
20
29
  ].filter(Boolean).join(' ')
21
30
  )
31
+
32
+ const dispatch = createDispatch(root)
33
+
34
+ useComponentHost(controllerModule.default, {
35
+ root,
36
+ dispatch,
37
+ props,
38
+ refs: { strip: stripElement },
39
+ state: { overflowStart, overflowEnd },
40
+ })
22
41
  </script>
23
42
 
24
43
  <template>
@@ -28,39 +47,89 @@ const hostState = computed(() =>
28
47
  aria-label="Editor toolbar"
29
48
  v-bind="$attrs"
30
49
  :data-ui-editor-toolbar-state="hostState || undefined"
50
+ ref="root"
31
51
  >
32
- <slot />
52
+ <div class="strip" ref="strip"><slot /></div>
33
53
  </div>
34
54
  </template>
35
55
 
36
56
  <style scoped>
37
57
  [data-component~="ui-editor-toolbar"] {
58
+ /* The colour the edge fades blend into: whatever the toolbar is painted with. */
59
+ --_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
60
+
38
61
  position: sticky;
39
62
  top: 0;
40
63
  z-index: var(--ui-editor-toolbar-z-index, 10);
41
64
  display: flex;
42
65
  align-items: center;
43
- justify-content: flex-start;
44
- gap: var(--ui-editor-toolbar-gap, 2px);
45
66
  padding: var(--ui-editor-toolbar-padding-block, 6px)
46
67
  var(--ui-editor-toolbar-padding-inline, 12px);
47
68
  min-height: var(--ui-editor-toolbar-min-height, 48px);
48
- /* More controls than the column is wide is normal at a readable measure, so the row wraps.
49
- Scrolling hid the tail behind an invisible scrollbar. */
50
- flex-wrap: wrap;
51
- row-gap: var(--ui-editor-toolbar-row-gap, var(--ui-editor-toolbar-gap, 2px));
52
69
  background: var(--ui-editor-toolbar-surface, var(--ui-surface));
53
70
  border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
54
71
  }
55
72
 
56
- [data-component~="ui-editor-toolbar"]::-webkit-scrollbar {
73
+ /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than
74
+ wrapping into several lines, and a fade at each edge that has more to show says so. */
75
+ .strip {
76
+ display: flex;
77
+ flex: 1 1 auto;
78
+ align-items: center;
79
+ justify-content: flex-start;
80
+ gap: var(--ui-editor-toolbar-gap, 2px);
81
+ min-width: 0;
82
+ overflow-x: auto;
83
+ overflow-y: hidden;
84
+ overscroll-behavior-inline: contain;
85
+ scrollbar-width: none;
86
+ }
87
+
88
+ .strip::-webkit-scrollbar {
57
89
  display: none;
58
90
  }
59
91
 
60
- [data-component~="ui-editor-toolbar"] > :slotted(*) {
92
+ .strip > :slotted(*) {
61
93
  flex: 0 0 auto;
62
94
  }
63
95
 
96
+ /* The fades are mattes laid over the strip in the toolbar's own colour, not a mask, so a floating
97
+ toolbar's border and shadow stay whole. Each appears only while that edge hides controls. */
98
+ [data-component~="ui-editor-toolbar"]::before,
99
+ [data-component~="ui-editor-toolbar"]::after {
100
+ position: absolute;
101
+ z-index: 1;
102
+ inset-block: 0;
103
+ inline-size: var(--ui-editor-toolbar-fade-size, 32px);
104
+ content: "";
105
+ opacity: 0;
106
+ pointer-events: none;
107
+ transition: opacity var(--ui-motion-fast, 120ms) var(--ui-motion-ease, ease);
108
+ }
109
+
110
+ [data-component~="ui-editor-toolbar"]::before {
111
+ inset-inline-start: 0;
112
+ background: linear-gradient(to right, var(--_matte), transparent);
113
+ }
114
+
115
+ [data-component~="ui-editor-toolbar"]::after {
116
+ inset-inline-end: 0;
117
+ background: linear-gradient(to left, var(--_matte), transparent);
118
+ }
119
+
120
+ [data-component~="ui-editor-toolbar"]:dir(rtl)::before {
121
+ background: linear-gradient(to left, var(--_matte), transparent);
122
+ }
123
+
124
+ [data-component~="ui-editor-toolbar"]:dir(rtl)::after {
125
+ background: linear-gradient(to right, var(--_matte), transparent);
126
+ }
127
+
128
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="overflowStart"]::before,
129
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="overflowEnd"]::after {
130
+ opacity: 1;
131
+ }
132
+
64
133
  :slotted(.divider) {
65
134
  width: 1px;
66
135
  height: 20px;
@@ -70,14 +139,12 @@ const hostState = computed(() =>
70
139
  }
71
140
 
72
141
  [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"] {
73
- flex-wrap: nowrap;
74
- position: static;
142
+ position: relative;
75
143
  top: auto;
76
144
  width: max-content;
77
145
  max-width: min(calc(100vw - 24px), 100%);
78
146
  min-height: auto;
79
147
  padding: var(--ui-editor-toolbar-floating-padding, 4px);
80
- overflow-x: visible;
81
148
  background: color-mix(
82
149
  in srgb,
83
150
  var(--ui-editor-toolbar-surface, var(--ui-surface)) 96%,
@@ -106,7 +173,7 @@ const hostState = computed(() =>
106
173
  }
107
174
 
108
175
  [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"] {
109
- position: static;
176
+ position: relative;
110
177
  inset: auto;
111
178
  min-height: auto;
112
179
  border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
@@ -120,9 +187,10 @@ const hostState = computed(() =>
120
187
 
121
188
  /* Inside LoomaEditor's sticky shell, the shell is the sticky surface. */
122
189
  .looma-editor__sticky-toolbar-shell [data-component~="ui-editor-toolbar"] {
123
- position: static;
190
+ --_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
191
+
192
+ position: relative;
124
193
  min-height: var(--ui-editor-toolbar-min-height, 48px);
125
- overscroll-behavior-inline: contain;
126
194
  background: transparent;
127
195
  border: 0;
128
196
  box-shadow: none;
@@ -135,10 +203,6 @@ const hostState = computed(() =>
135
203
  max-width: none;
136
204
  min-height: 100%;
137
205
  padding: 0;
138
- overflow-x: auto;
139
- overflow-y: hidden;
140
- overscroll-behavior-inline: contain;
141
- scroll-snap-type: x mandatory;
142
206
  background: transparent;
143
207
  border: 0;
144
208
  border-radius: 0;
@@ -146,6 +210,12 @@ const hostState = computed(() =>
146
210
  backdrop-filter: none;
147
211
  }
148
212
 
213
+ .looma-editor__mobile-toolbar-shell
214
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"]
215
+ .strip {
216
+ scroll-snap-type: x mandatory;
217
+ }
218
+
149
219
  /* A component that sets its display still honours the hidden attribute on its root. */
150
220
  [data-component~="ui-editor-toolbar"][hidden] {
151
221
  display: none;
@@ -1,7 +1,13 @@
1
+ import { n as useComponentHost, t as createDispatch } from "./host.js";
1
2
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
2
- import { computed, createElementBlock, defineComponent, mergeProps, openBlock, renderSlot } from "vue";
3
+ import { computed, createElementBlock, createElementVNode, defineComponent, mergeProps, openBlock, ref, renderSlot, useTemplateRef } from "vue";
4
+ import * as controllerModule from "@threadlabs/looma/components/ui-editor-toolbar/ui-editor-toolbar.js";
3
5
  //#region .build/vue/UiEditorToolbar.vue?vue&type=script&setup=true&lang.ts
4
6
  var _hoisted_1 = ["data-ui-editor-toolbar-state"];
7
+ var _hoisted_2 = {
8
+ class: "strip",
9
+ ref: "strip"
10
+ };
5
11
  //#endregion
6
12
  //#region .build/vue/UiEditorToolbar.vue
7
13
  var UiEditorToolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -13,16 +19,39 @@ var UiEditorToolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
13
19
  } },
14
20
  setup(__props) {
15
21
  const props = __props;
22
+ const root = ref(null);
23
+ const stripElement = useTemplateRef("strip");
24
+ const overflowStart = ref(false);
25
+ const overflowEnd = ref(false);
16
26
  /** The values the styles' :host-state() rules test. */
17
- const hostState = computed(() => [props.floating && "floating"].filter(Boolean).join(" "));
27
+ const hostState = computed(() => [
28
+ overflowStart.value && "overflowStart",
29
+ overflowEnd.value && "overflowEnd",
30
+ props.floating && "floating"
31
+ ].filter(Boolean).join(" "));
32
+ const dispatch = createDispatch(root);
33
+ useComponentHost(controllerModule.default, {
34
+ root,
35
+ dispatch,
36
+ props,
37
+ refs: { strip: stripElement },
38
+ state: {
39
+ overflowStart,
40
+ overflowEnd
41
+ }
42
+ });
18
43
  return (_ctx, _cache) => {
19
44
  return openBlock(), createElementBlock("div", mergeProps({
20
45
  "data-component": "ui-editor-toolbar",
21
46
  role: "toolbar",
22
47
  "aria-label": "Editor toolbar"
23
- }, _ctx.$attrs, { "data-ui-editor-toolbar-state": hostState.value || void 0 }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_1);
48
+ }, _ctx.$attrs, {
49
+ "data-ui-editor-toolbar-state": hostState.value || void 0,
50
+ ref_key: "root",
51
+ ref: root
52
+ }), [createElementVNode("div", _hoisted_2, [renderSlot(_ctx.$slots, "default")], 512)], 16, _hoisted_1);
24
53
  };
25
54
  }
26
- }), [["__scopeId", "data-v-b71db5ba"]]);
55
+ }), [["__scopeId", "data-v-e776f060"]]);
27
56
  //#endregion
28
57
  export { UiEditorToolbar_default as t };
@@ -2349,46 +2349,88 @@ svg[data-v-7b1048a0] {
2349
2349
  display: none;
2350
2350
  }
2351
2351
 
2352
- [data-component~="ui-editor-toolbar"][data-v-b71db5ba] {
2352
+ [data-component~="ui-editor-toolbar"][data-v-e776f060] {
2353
+ /* The colour the edge fades blend into: whatever the toolbar is painted with. */
2354
+ --_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
2355
+
2353
2356
  position: sticky;
2354
2357
  top: 0;
2355
2358
  z-index: var(--ui-editor-toolbar-z-index, 10);
2356
2359
  display: flex;
2357
2360
  align-items: center;
2358
- justify-content: flex-start;
2359
- gap: var(--ui-editor-toolbar-gap, 2px);
2360
2361
  padding: var(--ui-editor-toolbar-padding-block, 6px)
2361
2362
  var(--ui-editor-toolbar-padding-inline, 12px);
2362
2363
  min-height: var(--ui-editor-toolbar-min-height, 48px);
2363
- /* More controls than the column is wide is normal at a readable measure, so the row wraps.
2364
- Scrolling hid the tail behind an invisible scrollbar. */
2365
- flex-wrap: wrap;
2366
- row-gap: var(--ui-editor-toolbar-row-gap, var(--ui-editor-toolbar-gap, 2px));
2367
2364
  background: var(--ui-editor-toolbar-surface, var(--ui-surface));
2368
2365
  border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
2369
2366
  }
2370
- [data-component~="ui-editor-toolbar"][data-v-b71db5ba]::-webkit-scrollbar {
2367
+
2368
+ /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than
2369
+ wrapping into several lines, and a fade at each edge that has more to show says so. */
2370
+ .strip[data-v-e776f060] {
2371
+ display: flex;
2372
+ flex: 1 1 auto;
2373
+ align-items: center;
2374
+ justify-content: flex-start;
2375
+ gap: var(--ui-editor-toolbar-gap, 2px);
2376
+ min-width: 0;
2377
+ overflow-x: auto;
2378
+ overflow-y: hidden;
2379
+ overscroll-behavior-inline: contain;
2380
+ scrollbar-width: none;
2381
+ }
2382
+ .strip[data-v-e776f060]::-webkit-scrollbar {
2371
2383
  display: none;
2372
2384
  }
2373
- [data-component~="ui-editor-toolbar"] > [data-v-b71db5ba-s] {
2385
+ .strip > [data-v-e776f060-s] {
2374
2386
  flex: 0 0 auto;
2375
2387
  }
2376
- .divider[data-v-b71db5ba-s] {
2388
+
2389
+ /* The fades are mattes laid over the strip in the toolbar's own colour, not a mask, so a floating
2390
+ toolbar's border and shadow stay whole. Each appears only while that edge hides controls. */
2391
+ [data-component~="ui-editor-toolbar"][data-v-e776f060]::before,
2392
+ [data-component~="ui-editor-toolbar"][data-v-e776f060]::after {
2393
+ position: absolute;
2394
+ z-index: 1;
2395
+ inset-block: 0;
2396
+ inline-size: var(--ui-editor-toolbar-fade-size, 32px);
2397
+ content: "";
2398
+ opacity: 0;
2399
+ pointer-events: none;
2400
+ transition: opacity var(--ui-motion-fast, 120ms) var(--ui-motion-ease, ease);
2401
+ }
2402
+ [data-component~="ui-editor-toolbar"][data-v-e776f060]::before {
2403
+ inset-inline-start: 0;
2404
+ background: linear-gradient(to right, var(--_matte), transparent);
2405
+ }
2406
+ [data-component~="ui-editor-toolbar"][data-v-e776f060]::after {
2407
+ inset-inline-end: 0;
2408
+ background: linear-gradient(to left, var(--_matte), transparent);
2409
+ }
2410
+ [data-component~="ui-editor-toolbar"][data-v-e776f060]:dir(rtl)::before {
2411
+ background: linear-gradient(to left, var(--_matte), transparent);
2412
+ }
2413
+ [data-component~="ui-editor-toolbar"][data-v-e776f060]:dir(rtl)::after {
2414
+ background: linear-gradient(to right, var(--_matte), transparent);
2415
+ }
2416
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="overflowStart"][data-v-e776f060]::before,
2417
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="overflowEnd"][data-v-e776f060]::after {
2418
+ opacity: 1;
2419
+ }
2420
+ .divider[data-v-e776f060-s] {
2377
2421
  width: 1px;
2378
2422
  height: 20px;
2379
2423
  background: var(--ui-editor-toolbar-divider, var(--ui-border));
2380
2424
  flex-shrink: 0;
2381
2425
  margin: 0 var(--ui-editor-toolbar-divider-margin, 4px);
2382
2426
  }
2383
- [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"][data-v-b71db5ba] {
2384
- flex-wrap: nowrap;
2385
- position: static;
2427
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"][data-v-e776f060] {
2428
+ position: relative;
2386
2429
  top: auto;
2387
2430
  width: max-content;
2388
2431
  max-width: min(calc(100vw - 24px), 100%);
2389
2432
  min-height: auto;
2390
2433
  padding: var(--ui-editor-toolbar-floating-padding, 4px);
2391
- overflow-x: visible;
2392
2434
  background: color-mix(
2393
2435
  in srgb,
2394
2436
  var(--ui-editor-toolbar-surface, var(--ui-surface)) 96%,
@@ -2403,7 +2445,7 @@ svg[data-v-7b1048a0] {
2403
2445
  backdrop-filter: blur(10px);
2404
2446
  }
2405
2447
  @media (max-width: 767px) {
2406
- [data-component~="ui-editor-toolbar"][data-v-b71db5ba] {
2448
+ [data-component~="ui-editor-toolbar"][data-v-e776f060] {
2407
2449
  position: fixed;
2408
2450
  top: auto;
2409
2451
  bottom: env(safe-area-inset-bottom);
@@ -2414,8 +2456,8 @@ svg[data-v-7b1048a0] {
2414
2456
  border-bottom: none;
2415
2457
  box-shadow: var(--ui-editor-toolbar-mobile-shadow, 0 -2px 8px rgb(0 0 0 / 0.06));
2416
2458
  }
2417
- [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"][data-v-b71db5ba] {
2418
- position: static;
2459
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"][data-v-e776f060] {
2460
+ position: relative;
2419
2461
  inset: auto;
2420
2462
  min-height: auto;
2421
2463
  border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
@@ -2428,10 +2470,11 @@ svg[data-v-7b1048a0] {
2428
2470
  }
2429
2471
 
2430
2472
  /* Inside LoomaEditor's sticky shell, the shell is the sticky surface. */
2431
- .looma-editor__sticky-toolbar-shell [data-component~="ui-editor-toolbar"][data-v-b71db5ba] {
2432
- position: static;
2473
+ .looma-editor__sticky-toolbar-shell [data-component~="ui-editor-toolbar"][data-v-e776f060] {
2474
+ --_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
2475
+
2476
+ position: relative;
2433
2477
  min-height: var(--ui-editor-toolbar-min-height, 48px);
2434
- overscroll-behavior-inline: contain;
2435
2478
  background: transparent;
2436
2479
  border: 0;
2437
2480
  box-shadow: none;
@@ -2439,24 +2482,25 @@ svg[data-v-7b1048a0] {
2439
2482
 
2440
2483
  /* Inside LoomaEditor's mobile shell, the toolbar is a scroll-snapping strip. */
2441
2484
  .looma-editor__mobile-toolbar-shell
2442
- [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"][data-v-b71db5ba] {
2485
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"][data-v-e776f060] {
2443
2486
  width: 100%;
2444
2487
  max-width: none;
2445
2488
  min-height: 100%;
2446
2489
  padding: 0;
2447
- overflow-x: auto;
2448
- overflow-y: hidden;
2449
- overscroll-behavior-inline: contain;
2450
- scroll-snap-type: x mandatory;
2451
2490
  background: transparent;
2452
2491
  border: 0;
2453
2492
  border-radius: 0;
2454
2493
  box-shadow: none;
2455
2494
  backdrop-filter: none;
2456
2495
  }
2496
+ .looma-editor__mobile-toolbar-shell
2497
+ [data-component~="ui-editor-toolbar"][data-ui-editor-toolbar-state~="floating"]
2498
+ .strip[data-v-e776f060] {
2499
+ scroll-snap-type: x mandatory;
2500
+ }
2457
2501
 
2458
2502
  /* A component that sets its display still honours the hidden attribute on its root. */
2459
- [data-component~="ui-editor-toolbar"][hidden][data-v-b71db5ba] {
2503
+ [data-component~="ui-editor-toolbar"][hidden][data-v-e776f060] {
2460
2504
  display: none;
2461
2505
  }
2462
2506