visual-feedback 0.3.3 → 0.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/AGENTS.md +4 -1
- package/CHANGELOG.md +14 -0
- package/README.md +8 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.mjs +1 -1
- package/dist/{widget-IwlLFJCu.mjs → widget-BoohIxqp.mjs} +30 -9
- package/dist/{widget-Z1KOUKjx.d.mts → widget-Cxcm3h1Z.d.mts} +1 -1
- package/docs/API.md +1 -1
- package/docs/SPEC.md +21 -15
- package/docs/THEMING.md +6 -6
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -36,7 +36,10 @@ comes before the first report in step 6.
|
|
|
36
36
|
recipe adds. In a React or Next.js app, render `<Feedback endpoint="/api/feedback" />` from
|
|
37
37
|
`visual-feedback/react` instead, once, in the root layout; its props are the same options, and
|
|
38
38
|
a function prop such as `onSubmit` needs a `"use client"` file (`docs/API.md`). Every option is in `docs/API.md`; the look is in
|
|
39
|
-
`docs/THEMING.md`.
|
|
39
|
+
`docs/THEMING.md`. Fit the button to the app's own design: read its layout and pick
|
|
40
|
+
`trigger` and `position`, and `--vf-offset` where the default spot would cover something the app shows, and the
|
|
41
|
+
`--vf-*` colours and corners where the widget does not take them from the page already. Tell the
|
|
42
|
+
developer where it sits and why.
|
|
40
43
|
3. On the server: copy the recipe's route as it is written. Its test runs that code, with only the
|
|
41
44
|
marked parts below filled in, so do not change how it stores a report. If the app is not a Next.js App Router app, keep the logic and
|
|
42
45
|
change only how the route is mounted.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 (2026-10-13)
|
|
4
|
+
|
|
5
|
+
- Breaking: the trigger is a tab by default, in the corner `position` names, with a flag icon. It
|
|
6
|
+
has no border: the text colour fills it, and on hover the colours swap. `--vf-offset` lifts the
|
|
7
|
+
tab along its side edge, and no longer moves it off that edge. `trigger: "button"` keeps the
|
|
8
|
+
round button, 16px from both edges, filled the same way (SPEC §3).
|
|
9
|
+
- Breaking: the trigger has no `title`. Its tooltip is the widget's own: it shows at once on hover
|
|
10
|
+
or keyboard focus, beside the trigger with an arrow pointing at it, and has its own part,
|
|
11
|
+
`trigger-tooltip`. Screen readers still hear it as the description.
|
|
12
|
+
- The README starts with a prompt to give a coding agent, naming the package by its npm page, and AGENTS.md asks the agent to fit the
|
|
13
|
+
button to the app's design.
|
|
14
|
+
- The demo styles the tooltip as its "Click here" hint, and fades that hint while the tooltip
|
|
15
|
+
shows.
|
|
16
|
+
|
|
3
17
|
## 0.3.3 (2026-10-13)
|
|
4
18
|
|
|
5
19
|
- The trigger stands out more: a swirl icon that fills it, in place of the speech bubble, ringed
|
package/README.md
CHANGED
|
@@ -8,6 +8,14 @@ any design.
|
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
+
Ask your coding agent:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Install the visual-feedback npm package (https://www.npmjs.com/package/visual-feedback) and add it to this app by following its AGENTS.md. Place its button where it covers nothing, and match its position, colours and corners to our design.
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or the old-school way, by hand:
|
|
18
|
+
|
|
11
19
|
```sh
|
|
12
20
|
npm install visual-feedback
|
|
13
21
|
```
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as FeedbackWidget, c as CaptureOptions, i as FeedbackStrings, n as FeedbackEvents, o as createFeedback, r as FeedbackOptions, s as discardDraft, t as FeedbackEvent } from "./widget-
|
|
2
|
+
import { a as FeedbackWidget, c as CaptureOptions, i as FeedbackStrings, n as FeedbackEvents, o as createFeedback, r as FeedbackOptions, s as discardDraft, t as FeedbackEvent } from "./widget-Cxcm3h1Z.mjs";
|
|
3
3
|
import { n as Mark, r as Screenshot, t as FeedbackReport } from "./report-CaJegYyg.mjs";
|
|
4
4
|
export { type CaptureOptions, type FeedbackEvent, type FeedbackEvents, type FeedbackOptions, type FeedbackReport, type FeedbackStrings, type FeedbackWidget, type Mark, type Screenshot, createFeedback, discardDraft };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
export { t as createFeedback, n as discardDraft } from "./widget-
|
|
2
|
+
export { t as createFeedback, n as discardDraft } from "./widget-BoohIxqp.mjs";
|
package/dist/react.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { r as FeedbackOptions } from "./widget-
|
|
2
|
+
import { r as FeedbackOptions } from "./widget-Cxcm3h1Z.mjs";
|
|
3
3
|
//#region src/react/index.d.ts
|
|
4
4
|
export type FeedbackProps = FeedbackOptions;
|
|
5
5
|
export declare function Feedback(props: FeedbackProps): null;
|
package/dist/react.mjs
CHANGED
|
@@ -162,23 +162,24 @@ function sheet(text) {
|
|
|
162
162
|
return result;
|
|
163
163
|
}
|
|
164
164
|
function variables() {
|
|
165
|
-
return `.vf{--_r:var(--vf-radius,var(--_pr,16px));--_s:var(--vf-surface,var(--_ps,Canvas));--_t:var(--vf-text,var(--_pt,CanvasText));--_m:var(--vf-muted,var(--_pm,color-mix(in srgb,var(--_t) 60%,transparent)));--_b:var(--vf-border,color-mix(in srgb,var(--_t) 15%,transparent));--_a:var(--vf-accent,var(--_pa,${CSS.supports("color", "AccentColor") ? "AccentColor" : "#0b57d0"}));--_at:var(--vf-accent-text,#fff);--_f:var(--vf-focus,var(--_a));--_mark:var(--vf-mark,#e5243b);--_bd:var(--vf-backdrop,rgb(0 0 0/45%));--_sh:var(--vf-shadow,0 12px 32px -12px rgb(0 0 0/35%));--_size:var(--vf-trigger-size,2.5em);--_off:var(--vf-offset,16px);--_z:var(--vf-z,2147483000)}`;
|
|
165
|
+
return `.vf{--_r:var(--vf-radius,var(--_pr,16px));--_s:var(--vf-surface,var(--_ps,Canvas));--_t:var(--vf-text,var(--_pt,CanvasText));--_m:var(--vf-muted,var(--_pm,color-mix(in srgb,var(--_t) 60%,transparent)));--_b:var(--vf-border,color-mix(in srgb,var(--_t) 15%,transparent));--_a:var(--vf-accent,var(--_pa,${CSS.supports("color", "AccentColor") ? "AccentColor" : "#0b57d0"}));--_at:var(--vf-accent-text,#fff);--_f:var(--vf-focus,var(--_a));--_mark:var(--vf-mark,#e5243b);--_bd:var(--vf-backdrop,rgb(0 0 0/45%));--_sh:var(--vf-shadow,0 12px 32px -12px rgb(0 0 0/35%));--_size:var(--vf-trigger-size,2.5em);--_off:var(--vf-offset,16px);--_toff:var(--vf-offset,0px);--_z:var(--vf-z,2147483000)}`;
|
|
166
166
|
}
|
|
167
|
-
const LAYOUT = `.vf{display:contents;font-family:var(--vf-font,inherit);color-scheme:light dark}.trigger{font:inherit;position:fixed;z-index:var(--_z);box-sizing:border-box;height:var(--_size);margin:0;padding:0 14px 0 12px;display:flex;align-items:center;gap:8px;white-space:nowrap}.trigger[data-icon]{width:var(--_size);padding:0;justify-content:center}.trigger[data-icon]
|
|
168
|
-
const THEME = `.trigger{font-weight:600;border:
|
|
169
|
-
function icon() {
|
|
167
|
+
const LAYOUT = `.vf{display:contents;font-family:var(--vf-font,inherit);color-scheme:light dark}.trigger{font:inherit;position:fixed;z-index:var(--_z);box-sizing:border-box;height:var(--_size);margin:0;padding:0 14px 0 12px;display:flex;align-items:center;gap:8px;white-space:nowrap}.trigger[data-icon]{width:var(--_size);padding:0;justify-content:center}.trigger[data-icon]>svg{width:62.5%;height:62.5%}[data-y=bottom]{bottom:calc(var(--_off) + env(safe-area-inset-bottom,0px))}[data-y=top]{top:calc(var(--_off) + env(safe-area-inset-top,0px))}[data-x=right]{right:calc(var(--_off) + env(safe-area-inset-right,0px))}[data-x=left]{left:calc(var(--_off) + env(safe-area-inset-left,0px))}.trigger:where([data-tab][data-y=bottom]){bottom:calc(var(--_toff) + env(safe-area-inset-bottom,0px))}.trigger:where([data-tab][data-y=top]){top:calc(var(--_toff) + env(safe-area-inset-top,0px))}.trigger:where([data-tab][data-x=right]){right:env(safe-area-inset-right,0px)}.trigger:where([data-tab][data-x=left]){left:env(safe-area-inset-left,0px)}.trigger>svg{width:1.15em;height:1.15em}.tip{position:absolute;top:50%;translate:0 -50%;direction:ltr;box-sizing:border-box;width:max-content;max-width:calc(100vw - 100% - 2 * var(--_off) - 10px);white-space:normal;display:flex;align-items:center;gap:4px;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .15s,visibility .15s}[data-x=right]>.tip{right:calc(100% + 10px)}[data-x=left]>.tip{left:calc(100% + 10px);flex-direction:row-reverse}[data-x=left]>.tip svg{rotate:180deg}.tip svg{width:1.15em;height:1.15em;flex:none}.trigger:focus-visible>.tip{visibility:inherit;opacity:1}@media (hover:hover){.trigger:hover>.tip{visibility:inherit;opacity:1}}.capturing,.capturing .backdrop{visibility:hidden}.capturing .tip{transition:none}.still .trigger{transition:none!important}:focus-visible{outline:2px solid var(--_f);outline-offset:2px}@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}`;
|
|
168
|
+
const THEME = `.trigger{font-weight:600;border:0;border-radius:999px;background:var(--_t);color:var(--_s);box-shadow:var(--_sh);cursor:pointer;transition:background-color .15s,color .15s}@media (hover:hover){.trigger:hover{background:var(--_s);color:var(--_t)}}.tip{padding:6px 8px 6px 14px;border-radius:999px;background:var(--_t);color:var(--_s);font-weight:700;box-shadow:var(--_sh)}[data-x=left]>.tip{padding:6px 14px 6px 8px}.trigger:where([data-tab]){--_tr:clamp(0px,var(--_toff) * 1000,var(--_r));border-radius:var(--_r)}.trigger:where([data-tab][data-y=bottom]){border-bottom-left-radius:var(--_tr);border-bottom-right-radius:var(--_tr)}.trigger:where([data-tab][data-y=top]){border-top-left-radius:var(--_tr);border-top-right-radius:var(--_tr)}.trigger:where([data-tab][data-x=right]){border-top-right-radius:0;border-bottom-right-radius:0}.trigger:where([data-tab][data-x=left]){border-top-left-radius:0;border-bottom-left-radius:0}`;
|
|
169
|
+
function icon(d, attributes) {
|
|
170
170
|
const svg = document.createElementNS(SVG, "svg");
|
|
171
171
|
const path = document.createElementNS(SVG, "path");
|
|
172
172
|
for (const [name, value] of Object.entries({
|
|
173
173
|
viewBox: "0 0 24 24",
|
|
174
174
|
"aria-hidden": "true",
|
|
175
|
-
|
|
176
|
-
part: "trigger-icon"
|
|
175
|
+
...attributes
|
|
177
176
|
})) svg.setAttribute(name, value);
|
|
178
|
-
path.setAttribute("d",
|
|
177
|
+
path.setAttribute("d", d);
|
|
179
178
|
svg.append(path);
|
|
180
179
|
return svg;
|
|
181
180
|
}
|
|
181
|
+
const FLAG = "M4 3a1 1 0 0 1 2 0v18a1 1 0 0 1-2 0zM7 4c2.5-1.5 5-1.5 7 0s4 1.5 6 0v10c-2 1.5-4 1.5-6 0s-4.5-1.5-7 0z";
|
|
182
|
+
const ARROW = "M5 12h14m-6-6 6 6-6 6";
|
|
182
183
|
function field(element) {
|
|
183
184
|
return element.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(element.tagName);
|
|
184
185
|
}
|
|
@@ -289,6 +290,9 @@ function createFeedback(options = {}) {
|
|
|
289
290
|
let pending;
|
|
290
291
|
let trigger;
|
|
291
292
|
let label;
|
|
293
|
+
const tip = document.createElement("span");
|
|
294
|
+
tip.dir = "auto";
|
|
295
|
+
tip.setAttribute("part", "trigger-tooltip-text");
|
|
292
296
|
let unlisten;
|
|
293
297
|
function listen(shortcut) {
|
|
294
298
|
const parsed = parse(shortcut);
|
|
@@ -340,18 +344,35 @@ function createFeedback(options = {}) {
|
|
|
340
344
|
trigger.setAttribute("part", "trigger");
|
|
341
345
|
label = document.createElement("span");
|
|
342
346
|
label.setAttribute("part", "trigger-text");
|
|
343
|
-
|
|
347
|
+
const tooltip = document.createElement("span");
|
|
348
|
+
tooltip.className = "tip";
|
|
349
|
+
tooltip.id = "vf-tip";
|
|
350
|
+
tooltip.setAttribute("part", "trigger-tooltip");
|
|
351
|
+
tooltip.setAttribute("aria-hidden", "true");
|
|
352
|
+
tooltip.append(tip, icon(ARROW, {
|
|
353
|
+
fill: "none",
|
|
354
|
+
stroke: "currentColor",
|
|
355
|
+
"stroke-width": "2.4",
|
|
356
|
+
"stroke-linecap": "round",
|
|
357
|
+
part: "icon"
|
|
358
|
+
}));
|
|
359
|
+
trigger.setAttribute("aria-describedby", tooltip.id);
|
|
360
|
+
trigger.append(icon(FLAG, {
|
|
361
|
+
fill: "currentColor",
|
|
362
|
+
part: "trigger-icon"
|
|
363
|
+
}), label, tooltip);
|
|
344
364
|
trigger.addEventListener("click", start);
|
|
345
365
|
wrapper.prepend(trigger);
|
|
346
366
|
}
|
|
347
367
|
const [y, x] = (options.position ?? "bottom-right").split("-");
|
|
348
368
|
trigger.dataset.y = y;
|
|
349
369
|
trigger.dataset.x = x;
|
|
370
|
+
trigger.toggleAttribute("data-tab", options.trigger !== "button");
|
|
350
371
|
const { trigger: name, triggerText } = options.strings ?? {};
|
|
351
372
|
const accessible = name || triggerText || "Send feedback";
|
|
352
373
|
trigger.setAttribute("aria-label", accessible);
|
|
353
374
|
const keys = options.shortcut ? spoken(options.shortcut) : void 0;
|
|
354
|
-
|
|
375
|
+
tip.textContent = keys ? `${accessible} (${keys})` : accessible;
|
|
355
376
|
trigger.toggleAttribute("data-icon", !triggerText);
|
|
356
377
|
if (label) {
|
|
357
378
|
label.textContent = triggerText ?? "";
|
|
@@ -37,7 +37,7 @@ type FeedbackOptions = {
|
|
|
37
37
|
requireNote?: boolean;
|
|
38
38
|
redactUrl?: boolean;
|
|
39
39
|
context?: () => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
40
|
-
trigger?: "button" | "none";
|
|
40
|
+
trigger?: "tab" | "button" | "none";
|
|
41
41
|
position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
42
42
|
shortcut?: string | false;
|
|
43
43
|
strings?: Partial<FeedbackStrings>;
|
package/docs/API.md
CHANGED
|
@@ -37,7 +37,7 @@ const feedback = createFeedback({
|
|
|
37
37
|
| `onSubmit` | `(report) => Promise<void>` | – | Sends the report. A throw shows the send error state, using the error's message. Give this or `endpoint`; with both, `onSubmit` is used. |
|
|
38
38
|
| `endpoint` | `string` | – | POSTs `multipart/form-data` with a `report` part (JSON, each screenshot without its image) and one part per screenshot, `image0`, `image1` and on, named `<id>-<n>.webp` or `<id>-<n>.png`. An answer that is not 2xx, a redirect included, shows the send error state with the default `error` text. It is a same-origin `fetch`, so it sends cookies only to the page's own origin; another origin needs CORS on its server and a `connect-src` that allows it. |
|
|
39
39
|
| `headers` | `Record<string, string>` or `() => Record<string, string>` | – | Extra headers for `endpoint`. A function is called at Send; a throw shows the send error state, using the error's message. |
|
|
40
|
-
| `trigger` | `"button" \| "none"` | `"
|
|
40
|
+
| `trigger` | `"tab" \| "button" \| "none"` | `"tab"` | `"tab"` touches the side edge, `"button"` is round, in the corner (SPEC §3). `"none"` draws no trigger; the host calls `open()`. A kept draft's bar still shows. |
|
|
41
41
|
| `position` | `"bottom-right" \| "bottom-left" \| "top-right" \| "top-left"` | `"bottom-right"` | Corner of the trigger. |
|
|
42
42
|
| `shortcut` | `string \| false` | `false` | For example `"Alt+Shift+F"`: any of `Alt`, `Shift`, `Control` and `Meta`, then one key, a letter, a digit or a key name such as `F2`, joined by `+`. The modifiers must match exactly, AltGr never matches, and any other modifier name, or no key, makes it match nothing. Without `Control` or `Meta` it does not fire while focus is in a form field (`input`, `textarea`, `select`) or editable content. It does nothing while the dialog is open or a draft is kept in the draft bar. The trigger's tooltip names it (SPEC §3). Opt-in; it is the widget's only listener on `window` or `document`, one `keydown` on `window` (SPEC §9 names what else the widget watches, and what the capture library keeps). |
|
|
43
43
|
| `tools` | `("pen" \| "box" \| "arrow" \| "text" \| "select")[]` | all five | Order is the toolbar order, and the first drawing tool is the one selected at open. Repeats and unknown names are ignored; an empty list, or Select alone, shows no toolbar. The Delete button is there only with Select. |
|
package/docs/SPEC.md
CHANGED
|
@@ -15,8 +15,8 @@ idle --open--> capturing --image ready--> annotating --Send--> sending --ok--> s
|
|
|
15
15
|
+--Esc / Keep as draft / Add screenshot--> draft
|
|
16
16
|
annotating, draft --Cancel (it may ask first, below) / Discard--> idle
|
|
17
17
|
```
|
|
18
|
-
- **idle:** the trigger
|
|
19
|
-
where the host calls `open()`).
|
|
18
|
+
- **idle:** the trigger shows, a tab (`trigger: "tab"`) or a round button (`trigger: "button"`), or
|
|
19
|
+
nothing shows (`trigger: "none"`, where the host calls `open()`).
|
|
20
20
|
- **capturing:** the trigger and any open panel are hidden, so they are not in the image. The
|
|
21
21
|
screen is captured (SPEC §5), and a screen reader is told the `capturing` text.
|
|
22
22
|
- **capture error:** the `captureError` text, with "Try again" (back to capturing), "Send without
|
|
@@ -48,19 +48,25 @@ annotating, draft --Cancel (it may ask first, below) / Discard--> idle
|
|
|
48
48
|
the same question when it would throw work away, close the dialog, and the draft goes with it.
|
|
49
49
|
|
|
50
50
|
## 3. The trigger
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
- By default it is a small tab, 2.5em square (40 px on a 16 px site), in the corner `position`
|
|
52
|
+
names, square on both edges there, with a flag icon and the `trigger` accessible name.
|
|
53
|
+
`--vf-offset` lifts it along its side edge, and then its end side is rounded too.
|
|
54
|
+
`trigger: "button"` makes it a round button in that corner instead, 16 px from both edges.
|
|
55
|
+
Either has no border: the text colour fills it, and the icon and label take the background
|
|
56
|
+
colour. On hover, on a device that can hover, the two swap back.
|
|
57
|
+
A host that gives `triggerText` gets that short label beside a small icon, in a wider tab, or a
|
|
58
|
+
pill as a button; with only `triggerText` given, that text is the name too. A host that sets
|
|
59
|
+
both keeps `triggerText` inside `trigger`, so speech control can say what it sees. It has no
|
|
60
|
+
badge, and it does not move or pulse.
|
|
61
|
+
- Its tooltip is its own, not the browser's `title`: a pill beside it, on the page's side, with an
|
|
62
|
+
arrow pointing at it. It fades in at once on keyboard focus, or on hover where the device can
|
|
63
|
+
hover, and out at the same speed.
|
|
64
|
+
It reads the name. With a `shortcut` that can match, it is the name and the keys, each modifier
|
|
65
|
+
once, joined by ` + `, as the platform's keyboards name them: Option, Command, Control and Shift
|
|
66
|
+
on a Mac, iPhone or iPad (`navigator.platform`), as in `Send feedback (Option + Shift + F)`;
|
|
67
|
+
Alt, Win, Ctrl and Shift on Windows; Alt, Super, Ctrl and Shift elsewhere. A screen reader reads
|
|
68
|
+
the tooltip as the description.
|
|
69
|
+
- It respects `env(safe-area-inset-*)`.
|
|
64
70
|
- It is hidden while there is a draft, whether the dialog is open or kept in the draft bar.
|
|
65
71
|
- It does not move to keep clear of the page's content. The host moves it off its own content
|
|
66
72
|
with `position` or `--vf-offset`.
|
package/docs/THEMING.md
CHANGED
|
@@ -39,8 +39,8 @@ Set these on `visual-feedback` (or on any ancestor). Custom properties cross the
|
|
|
39
39
|
|---|---|---|
|
|
40
40
|
| `--vf-font` | `inherit` | font family of all text, such as `Inter, sans-serif` |
|
|
41
41
|
| `--vf-radius` | from the page's button corners, so the widget's buttons match them up to 15px (this is 1.6 times theirs, up to `24px`), else `16px` | panel and composer, and a share of it for buttons and the image |
|
|
42
|
-
| `--vf-surface` | with `theme: "auto"` the page's background, else `Canvas` | panel, tool rail and composer background |
|
|
43
|
-
| `--vf-text` | with `theme: "auto"` the page's text colour, else `CanvasText` | text,
|
|
42
|
+
| `--vf-surface` | with `theme: "auto"` the page's background, else `Canvas` | panel, tool rail and composer background, the trigger's icon and label, its fill on hover, and the text of its tooltip |
|
|
43
|
+
| `--vf-text` | with `theme: "auto"` the page's text colour, else `CanvasText` | text, the trigger's fill, its icon and label on hover, and its tooltip's background |
|
|
44
44
|
| `--vf-muted` | text at 60%, more on a page whose text would make that too faint | hints, counters |
|
|
45
45
|
| `--vf-border` | text at 15% | hairlines |
|
|
46
46
|
| `--vf-accent` | the page's accent, else `AccentColor`, or `#0b57d0` where the browser has no `AccentColor` | Send button and its menu button, "Capture this view", active tool, chosen screenshot |
|
|
@@ -48,9 +48,9 @@ Set these on `visual-feedback` (or on any ancestor). Custom properties cross the
|
|
|
48
48
|
| `--vf-focus` | `--vf-accent` | focus ring |
|
|
49
49
|
| `--vf-mark` | `#e5243b` | marks on the screenshot |
|
|
50
50
|
| `--vf-backdrop` | `rgb(0 0 0 / 45%)` | overlay behind the image |
|
|
51
|
-
| `--vf-shadow` | `0 12px 32px -12px rgb(0 0 0 / 35%)` | trigger, panel and draft bar |
|
|
51
|
+
| `--vf-shadow` | `0 12px 32px -12px rgb(0 0 0 / 35%)` | trigger, its tooltip, panel and draft bar |
|
|
52
52
|
| `--vf-trigger-size` | `2.5em`, 40px on a 16px site | trigger height, and its width when it shows the icon alone |
|
|
53
|
-
| `--vf-offset` | `16px`
|
|
53
|
+
| `--vf-offset` | `16px`, and `0px` for the tab; a length, not a percentage | draft bar and round trigger distance from the edges; the tab keeps to its side edge, and this lifts it along it |
|
|
54
54
|
| `--vf-z` | `2147483000` | stacking |
|
|
55
55
|
|
|
56
56
|
```css
|
|
@@ -62,8 +62,8 @@ visual-feedback {
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
## 3. `::part()`
|
|
65
|
-
Every visible element has a part name: `trigger`, `trigger-icon`, `trigger-text`, `
|
|
66
|
-
`dialog`, `header`, `title`, `minimise`, `body`, `stage`, `image`, `toolbar`, `tool`, `tool-active`,
|
|
65
|
+
Every visible element has a part name: `trigger`, `trigger-icon`, `trigger-text`, `trigger-tooltip`,
|
|
66
|
+
`trigger-tooltip-text`, `backdrop`, `dialog`, `header`, `title`, `minimise`, `body`, `stage`, `image`, `toolbar`, `tool`, `tool-active`,
|
|
67
67
|
`divider`, `undo`, `clear`, `remove`, `icon`, `text-input`, `selection`, `strip`, `thumb`,
|
|
68
68
|
`thumb-pick`, `thumb-image`, `thumb-number`, `thumb-remove`, `add`, `label`, `composer`, `note`,
|
|
69
69
|
`composer-bar`, `category`, `footer`, `split`, `send-more`, `menu`, `save-pdf`, `actions`, `cancel`,
|
package/package.json
CHANGED