@vitreajs/vitrea 0.1.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/LICENSE +202 -0
- package/NOTICE +36 -0
- package/README.md +359 -0
- package/dist/chunk-ST6GFEQT.js +502 -0
- package/dist/chunk-ST6GFEQT.js.map +1 -0
- package/dist/dist-FGJI5LQM.js +3573 -0
- package/dist/dist-FGJI5LQM.js.map +1 -0
- package/dist/index.d.ts +2450 -0
- package/dist/index.js +1001 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
NOTICE — vitrea
|
|
2
|
+
================
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Minhyeok Kim
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
7
|
+
use these files except in compliance with the License. You may obtain a copy
|
|
8
|
+
of the License in the LICENSE file distributed with this package, or at
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
This package is original work. The internal packages bundled into it
|
|
12
|
+
(@vitrea/geometry, @vitrea/motion, @vitrea/renderer-webgpu) are part of the
|
|
13
|
+
same project and carry the same copyright and license.
|
|
14
|
+
|
|
15
|
+
Trademarks
|
|
16
|
+
-----------
|
|
17
|
+
"Liquid Glass" is the name of Apple Inc.'s design language. It is referenced
|
|
18
|
+
here descriptively — to state what material this library replicates and what
|
|
19
|
+
its fidelity is measured against — never as a claim of origin, endorsement, or
|
|
20
|
+
association. "Apple", "macOS", "SwiftUI", "Safari" and "Metal" are trademarks
|
|
21
|
+
of Apple Inc., and appear only in that descriptive sense.
|
|
22
|
+
|
|
23
|
+
vitrea is not affiliated with, endorsed by, or sponsored by Apple Inc. It is
|
|
24
|
+
not an Apple product, not built on Apple frameworks, and not a port of Apple
|
|
25
|
+
code. It is an independent open-source reimplementation of a published visual
|
|
26
|
+
material, calibrated against screen captures of Apple's own rendering on
|
|
27
|
+
macOS 26.5.
|
|
28
|
+
|
|
29
|
+
Other names appearing in this project's documentation ("Chromium", "Chrome",
|
|
30
|
+
"Firefox", "WebKit", "Figma") are trademarks of their respective owners and
|
|
31
|
+
are used only in descriptive reference.
|
|
32
|
+
|
|
33
|
+
Contact
|
|
34
|
+
-------
|
|
35
|
+
Minhyeok Kim <kimmi@l1ngual.com>
|
|
36
|
+
https://github.com/SSFSKIM/designer
|
package/README.md
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# vitrea
|
|
2
|
+
|
|
3
|
+
**A production-oriented, reference-calibrated material compositor for semantic web
|
|
4
|
+
controls.**
|
|
5
|
+
|
|
6
|
+
vitrea replicates Apple's Liquid Glass material and interaction system — WWDC25's
|
|
7
|
+
`glassEffect`, `GlassEffectContainer`, `interactive()`, `glassEffectID` — on the
|
|
8
|
+
web, in TypeScript. Not a blur preset: real-time size-parameterized lensing,
|
|
9
|
+
per-element adaptation of tint and foreground to the live backdrop,
|
|
10
|
+
container-scoped sampling, and shape-to-shape morphing.
|
|
11
|
+
|
|
12
|
+
This is not the first WebGPU glass demo, and it does not claim to be. Prior art
|
|
13
|
+
exists and is good at what it does. What vitrea is built for is the part the
|
|
14
|
+
demos leave out: explicit backdrop contracts, shared sampling groups, coherent
|
|
15
|
+
cross-element morphing, adaptive accessibility, progressive fidelity tiers that
|
|
16
|
+
report what they actually resolved to, and fidelity numbers backed by a versioned
|
|
17
|
+
harness that diffs against native captures instead of against a screenshot
|
|
18
|
+
somebody eyeballed.
|
|
19
|
+
|
|
20
|
+
The label on every glass control stays real DOM. A `GlassButton` is a `<button>`:
|
|
21
|
+
selectable, focusable, IME-capable, and announced by a screen reader as a button.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @vitreajs/vitrea @vitreajs/vitrea-react
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The library is called vitrea and publishes under the npm scope `@vitreajs`.
|
|
32
|
+
`@vitreajs/vitrea` is the framework-agnostic runtime, `@vitreajs/vitrea-react`
|
|
33
|
+
the declarative surface. These two are the only published packages: the
|
|
34
|
+
geometry kernel, the motion kernel, the DOM host layer and the WebGPU renderer
|
|
35
|
+
are internal and bundled into them at publish time, so an app installs two
|
|
36
|
+
packages and gets zero transitive runtime dependencies beyond React itself.
|
|
37
|
+
|
|
38
|
+
### Which package you actually import from
|
|
39
|
+
|
|
40
|
+
| You are… | Install | Import |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| writing a React app | `@vitreajs/vitrea @vitreajs/vitrea-react` | `@vitreajs/vitrea-react` for components, `@vitreajs/vitrea` for types |
|
|
43
|
+
| reading the resolved capability state | either | `@vitreajs/vitrea` |
|
|
44
|
+
| writing a Vue/Svelte/WC adapter | `@vitreajs/vitrea` | not yet supported — see below |
|
|
45
|
+
|
|
46
|
+
**One honest limit up front.** `vitrea` contains no DOM code at all, by design
|
|
47
|
+
(the purity law: the core, geometry and motion packages never touch `window`,
|
|
48
|
+
`document` or `HTMLElement`). The browser host layer — element registration,
|
|
49
|
+
plane management, backdrop proxies, the CSS-tier renderer, the WebGPU lifecycle —
|
|
50
|
+
ships bundled *inside* `vitrea-react`. So in v1 the only way to render glass in a
|
|
51
|
+
browser is through the React bindings. `vitrea` on its own gives you the scene
|
|
52
|
+
model, the capability and tier resolver, the material and accessibility policy,
|
|
53
|
+
and the frame-scheduler contract; it does not give you a mounted root. A
|
|
54
|
+
framework-agnostic host entry point is post-v1 work, not a thing you can reach
|
|
55
|
+
today by installing `vitrea` alone.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Quickstart
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { GlassRoot, GlassGroup, GlassToolbar, GlassButton, useGlassCapabilities } from "@vitreajs/vitrea-react";
|
|
63
|
+
|
|
64
|
+
export function App() {
|
|
65
|
+
return (
|
|
66
|
+
<GlassRoot renderer="webgpu">
|
|
67
|
+
{/* Your page. Ordinary DOM, and it stays ordinary DOM. */}
|
|
68
|
+
<YourPage />
|
|
69
|
+
|
|
70
|
+
{/* A toolbar creates its own sampling group; `hint` tells the runtime what
|
|
71
|
+
is behind it, because vitrea never pretends to analyse arbitrary DOM. */}
|
|
72
|
+
<GlassToolbar
|
|
73
|
+
aria-label="Actions"
|
|
74
|
+
groupProps={{ hint: { tone: "dark", luminance: 0.18 } }}
|
|
75
|
+
style={{ position: "fixed", bottom: 32, left: "50%", transform: "translateX(-50%)" }}
|
|
76
|
+
>
|
|
77
|
+
<GlassButton onClick={share}>Share</GlassButton>
|
|
78
|
+
<GlassButton onClick={save}>Save</GlassButton>
|
|
79
|
+
</GlassToolbar>
|
|
80
|
+
</GlassRoot>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Surfaces that are not toolbar members go in an explicit group. A group is the
|
|
86
|
+
sampling unit — one backdrop proxy, one blur, shared between its members:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<GlassGroup id="hero" hint={{ tone: "light" }}>
|
|
90
|
+
<GlassSurface radius={20} thickness={10}>
|
|
91
|
+
<h1>Anything you like in here</h1>
|
|
92
|
+
</GlassSurface>
|
|
93
|
+
</GlassGroup>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
And to see what the runtime actually resolved to, rather than what you asked for:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
function TierReadout() {
|
|
100
|
+
const state = useGlassCapabilities("hero");
|
|
101
|
+
if (state === undefined) return null;
|
|
102
|
+
return (
|
|
103
|
+
<p>
|
|
104
|
+
configured {state.configuredSource}, drawing on {state.activeRenderer},
|
|
105
|
+
sampling {state.samplingBackend}, refraction {state.refraction}
|
|
106
|
+
{state.health === "demoted" ? ` — demoted: ${state.demotionReason}` : ""}
|
|
107
|
+
</p>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Run the demo app in this repository to see all of it working, including the
|
|
113
|
+
side-by-side native reference pairs:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pnpm install && pnpm -r build
|
|
117
|
+
pnpm --filter demo dev # http://localhost:5173, add ?renderer=css to force the tier
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## The capability model: the honesty contract, as a feature
|
|
123
|
+
|
|
124
|
+
Most glass libraries have one quality knob and fail quietly when the platform
|
|
125
|
+
cannot honour it. vitrea separates what your app **configures** from what the
|
|
126
|
+
runtime **resolves**, and the resolved state is a closed set of legal
|
|
127
|
+
combinations rather than a free product of axes — because a free product admits
|
|
128
|
+
states that are meaningless (a registered GPU texture with no WebGPU; a
|
|
129
|
+
CORS-tainted video reported as exact analysis).
|
|
130
|
+
|
|
131
|
+
Every group reports:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
interface GlassGroupState {
|
|
135
|
+
configuredSource: "texture" | "dom"; // what you declared — never mutated
|
|
136
|
+
activeRenderer: "webgpu" | "css"; // what is actually drawing
|
|
137
|
+
samplingBackend: "gpu-texture" | "css-backdrop" | "none";
|
|
138
|
+
refraction: "true" | "approximate" | "none";
|
|
139
|
+
analysis: "exact" | "hint" | "none";
|
|
140
|
+
health: "ok" | "demoted";
|
|
141
|
+
demotionReason?: "no-webgpu" | "no-backdrop-filter" | "tainted-source"
|
|
142
|
+
| "incompatible-texture" | "device-lost" | "probe-failed"
|
|
143
|
+
| "governor";
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Three properties are worth knowing, because they are the reason the model exists:
|
|
148
|
+
|
|
149
|
+
**`configuredSource` survives demotion.** You can always see what you asked for
|
|
150
|
+
next to what you got. Nothing silently rewrites your intent.
|
|
151
|
+
|
|
152
|
+
**Every demotion names a reason and a recovery.** `device-lost` recovers when a
|
|
153
|
+
device is restored; `tainted-source` when the source is replaced;
|
|
154
|
+
`probe-failed` when the probe re-passes. `no-webgpu` names its recovery as
|
|
155
|
+
`"none"` — honestly unrecoverable inside the session, rather than implying a
|
|
156
|
+
retry that will never succeed.
|
|
157
|
+
|
|
158
|
+
**Choosing the CSS tier is not a fault.** A root that never requested WebGPU
|
|
159
|
+
resolves its groups to `activeRenderer: "css"` with `health: "ok"` and no
|
|
160
|
+
demotion reason. Labelling deliberate intent as a fault would invert the whole
|
|
161
|
+
point.
|
|
162
|
+
|
|
163
|
+
### The three healthy configurations
|
|
164
|
+
|
|
165
|
+
| Configuration | What you get |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| **texture + exact** — you register an image, video, canvas or procedural texture as the group's backdrop | Full refraction. Edge lensing visibly bends the backdrop; a larger surface lenses deeper than a small one over the same content. Luminance, variance and edge-density analysis run on the GPU. |
|
|
168
|
+
| **dom + hint** — arbitrary page content, plus a `hint` (or an estimator provider) | The browser compositor does the blur through a masked backdrop proxy; the GPU renders rim lensing, tint, glow and morphs. Adaptation comes from your hint. |
|
|
169
|
+
| **dom + none** — arbitrary page content, no hint (the default) | Fixed regular material, geometry-driven rim and specular, foreground from tokens or `color-scheme`. |
|
|
170
|
+
|
|
171
|
+
vitrea does not automatically pixel-analyse arbitrary DOM, and never claims to.
|
|
172
|
+
There is a built-in best-effort estimator that reads known background colours and
|
|
173
|
+
images where CORS permits, and it is documented as an estimator every place it
|
|
174
|
+
appears — not as pixel analysis, because that is not what it is.
|
|
175
|
+
|
|
176
|
+
### Tiers degrade within themselves before they switch
|
|
177
|
+
|
|
178
|
+
The quality governor first reduces refraction resolution, adaptation cadence and
|
|
179
|
+
edge analysis *inside* the current tier. Switching tiers happens only with long
|
|
180
|
+
hysteresis and a cooldown, and never mid-interaction. Intra-tier degradation is
|
|
181
|
+
not a state change, so it does not churn your readouts.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Fidelity
|
|
186
|
+
|
|
187
|
+
vitrea's material is tuned against real captures of Apple's material, not against
|
|
188
|
+
recollection. `apps/reference-apple` is a SwiftUI harness running the actual
|
|
189
|
+
`glassEffect` API; `packages/calibration` captures both sides over identical
|
|
190
|
+
pre-rendered raster backgrounds and diffs them on shape, material, motion and
|
|
191
|
+
perceptual axes, keyed by native profile × web cell.
|
|
192
|
+
|
|
193
|
+
The full record is
|
|
194
|
+
[`docs/doperpowers/specs/c9a-fidelity-claims.md`](https://github.com/SSFSKIM/designer/blob/main/docs/doperpowers/specs/c9a-fidelity-claims.md).
|
|
195
|
+
The claims, in the words that document states them:
|
|
196
|
+
|
|
197
|
+
### The texture tier
|
|
198
|
+
|
|
199
|
+
> **Reference-calibrated against macOS 26.5 captures.** vitrea's WebGPU texture
|
|
200
|
+
> tier — its own shader math over a GPU-owned backdrop — was calibrated against
|
|
201
|
+
> 30 ScreenCaptureKit captures of Apple's `glassEffect` material on macOS 26.5,
|
|
202
|
+
> in the cell *Chromium 151, `gpu-texture` backend, Apple Metal-3 adapter, sRGB,
|
|
203
|
+
> 1× scale*. Across the six scenes held out of tuning, the rendered result
|
|
204
|
+
> reaches a silhouette IoU of 0.9924 mean / 0.9612 worst, a contour distance of
|
|
205
|
+
> 0.18 px mean / 0.56 px worst-cell-mean, SSIM 0.9475 mean / 0.9007 worst, and
|
|
206
|
+
> OKLab ΔE 0.0320 mean / 0.0548 worst. Tuning improved every one of those axes
|
|
207
|
+
> over the untuned defaults. It is not pixel-identical to Apple's material and
|
|
208
|
+
> two named gaps remain open.
|
|
209
|
+
|
|
210
|
+
### The CSS (dom) tier
|
|
211
|
+
|
|
212
|
+
> **No cross-engine pixel-wise fidelity claim is made for the dom tier, and none
|
|
213
|
+
> can be. On Chromium, in the same cell with `renderer: css` and
|
|
214
|
+
> `samplingBackend: css-backdrop`: OKLab ΔE 0.0091 mean / 0.0240 worst and SSIM
|
|
215
|
+
> 0.9700 mean / 0.9304 worst over the 12 light calibration cells, ΔE 0.0108 /
|
|
216
|
+
> 0.0273 over the 6 validation cells, and ΔE 0.0291 mean / 0.0560 worst with SSIM
|
|
217
|
+
> 0.9373 / 0.9205 on the six scenes held out of all tuning. Silhouette IoU 0.9424
|
|
218
|
+
> mean over the calibration cells and 0.9684 on holdout, with a 1.06 px mean
|
|
219
|
+
> contour distance.**
|
|
220
|
+
|
|
221
|
+
This tier does not hold a material of its own: it **converts** the one the root
|
|
222
|
+
carries, through a mapping whose single fitted constant is tuned against the
|
|
223
|
+
cross-tier difference rather than against the fixtures. That is a deliberate
|
|
224
|
+
trade, recorded rather than hidden — a CSS tier fitted independently against
|
|
225
|
+
Apple is free to drift from the GPU tier the moment either is retuned, while a
|
|
226
|
+
converted one inherits the GPU tier's fidelity by construction. The price is now
|
|
227
|
+
0.0099 against Apple where an independent fit reached 0.0094.
|
|
228
|
+
|
|
229
|
+
> **Tier coherence, and only in this wording.** On Chromium, a group that demotes
|
|
230
|
+
> from the WebGPU texture tier to the CSS tier keeps the same material to within
|
|
231
|
+
> 1.3% of its interior level in the mean and 11% on the worst measured cell, at a
|
|
232
|
+
> cross-tier OKLab ΔE of 0.0063 mean / 0.0124 worst over the fitted sets and
|
|
233
|
+
> 0.0188 / 0.0313 over the held-out ones. It is **not** the same rendering —
|
|
234
|
+
> refraction is absent on the CSS tier by contract (`refraction: "none"`) — but
|
|
235
|
+
> the material's opacity, tint and frost do not change visibly on demotion.
|
|
236
|
+
|
|
237
|
+
Exact coherence is unreachable, and the arithmetic says so before any capture
|
|
238
|
+
does: the renderer applies its transfer function *after* the blend and the page
|
|
239
|
+
applies it *before*, so matching the two composites needs a different CSS alpha at
|
|
240
|
+
every backdrop level (0.761 at linear 0.05, 0.635 at 0.8). One scalar is exact at
|
|
241
|
+
one level and necessarily wrong either side of it. What remains is a property of
|
|
242
|
+
`backdrop-filter`, not a residual anyone can tune away.
|
|
243
|
+
|
|
244
|
+
The cross-engine absence is not laziness. Gecko and WebKit render
|
|
245
|
+
`backdrop-filter` as a complete no-op in every automatable capture path — headless
|
|
246
|
+
and headed Playwright, retail `--screenshot`, WebDriver BiDi, WKWebView
|
|
247
|
+
`takeSnapshot` — while rendering it correctly live. A screenshot comparison on
|
|
248
|
+
those engines measures a blank image. Their visual behaviour is verified by a
|
|
249
|
+
manual self-scoring page instead, and that is a release gate rather than a CI
|
|
250
|
+
check.
|
|
251
|
+
|
|
252
|
+
### What is *not* claimed
|
|
253
|
+
|
|
254
|
+
- **Never "pixel-identical to Apple."** Every figure above is scoped to one
|
|
255
|
+
native profile and one web cell, and says so.
|
|
256
|
+
- **No press-state fidelity claim.** Apple's `Glass.interactive(true)` opts the
|
|
257
|
+
material into *responding* to press input rather than posing it pressed, and
|
|
258
|
+
Apple exposes no declarative pressed pose — so the native "pressed" captures
|
|
259
|
+
are byte-identical to their rest counterparts (verified by SHA-256, all four).
|
|
260
|
+
Those cells compare vitrea's pressed pose against Apple's rest pose. They were
|
|
261
|
+
also excluded from the tuning decision.
|
|
262
|
+
- **No adopted pass/fail thresholds.** The thresholds in the claims document are
|
|
263
|
+
*proposals for a human gate*, not self-certification.
|
|
264
|
+
- **1× only.** The capture machine reports `backingScaleFactor` 1.0, so every
|
|
265
|
+
figure is a 1× figure. The two accessibility-mode profiles have no captures at
|
|
266
|
+
all yet; macOS exposes those display modes as read-only, so each needs its own
|
|
267
|
+
capture run.
|
|
268
|
+
- **The glass-over-glass cells are a mixed-backend claim.** Natively the upper
|
|
269
|
+
`glassEffect` samples the lower one's rendered output; on the web that
|
|
270
|
+
relationship *is* the plane sandwich, so those cells resolve to
|
|
271
|
+
`gpu-texture + css-backdrop` with `refraction: "approximate"` even on the GPU
|
|
272
|
+
tier. They are counted in the holdout numbers, and they are the two lowest
|
|
273
|
+
SSIM figures in that set.
|
|
274
|
+
- **Tier coherence is a Chromium measurement of a material's level**, on one
|
|
275
|
+
profile, at 1×. It does not say the two tiers are identical, and it does not
|
|
276
|
+
hold on Gecko or WebKit — nothing measurable does there.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Browser support
|
|
281
|
+
|
|
282
|
+
Two tiers, and the CSS tier is a hard requirement rather than a courtesy —
|
|
283
|
+
WebGPU is not everywhere, and pretending otherwise is what the capability model
|
|
284
|
+
exists to prevent.
|
|
285
|
+
|
|
286
|
+
| Engine | WebGPU (texture tier) | CSS tier |
|
|
287
|
+
| --- | --- | --- |
|
|
288
|
+
| **Chromium** (Chrome, Edge) | Default-on from 113 on desktop, 121 on Android | Yes. Byte-exact backdrop-proxy sampling equivalence, measured across 122 capture variants |
|
|
289
|
+
| **Safari / WebKit** | Default-on from Safari 26 | Yes, manually verified — automated capture cannot observe `backdrop-filter` on this engine |
|
|
290
|
+
| **Firefox / Gecko** | Default-on from 141 on Windows, 145 on ARM Mac; **still flagged on Linux** | Yes, manually verified — same automated-capture blindness |
|
|
291
|
+
|
|
292
|
+
Where WebGPU is missing, every group resolves to `activeRenderer: "css"` with
|
|
293
|
+
`demotionReason: "no-webgpu"`, renders presentable CSS-tier glass, and logs no
|
|
294
|
+
errors. Asking for the GPU tier is not the same as getting it, and
|
|
295
|
+
`useGlassCapabilities()` is how you find out which happened.
|
|
296
|
+
|
|
297
|
+
### Contract limits you should know before designing around it
|
|
298
|
+
|
|
299
|
+
- All glass lives inside `GlassRoot`'s managed planes. v1 ships exactly two —
|
|
300
|
+
base and one overlay — and menus portal internally to the overlay plane.
|
|
301
|
+
Arbitrary interleaving with foreign stacking contexts is out of contract.
|
|
302
|
+
- Two glass surfaces must not overlap **within one plane**. This is a dev-mode
|
|
303
|
+
error rather than an assumption: the paint sandwich cannot place one surface's
|
|
304
|
+
body above another surface's DOM label. Overlap across planes is the supported
|
|
305
|
+
case and is what the morph uses.
|
|
306
|
+
- Glass hosts must not sit beneath an ancestor whose `filter`, `opacity`, `mask`
|
|
307
|
+
or `clip` changes the backdrop root. The relevant CSS specification explicitly
|
|
308
|
+
lacks working-group consensus here, so engines may legitimately differ — which
|
|
309
|
+
is why a startup conformance probe validates the proxy topology and demotes a
|
|
310
|
+
group to the CSS tier when sampling proves non-equivalent, rather than trusting
|
|
311
|
+
a support query.
|
|
312
|
+
- v1 corner radii are uniform. The `radii` API keeps its four-component shape,
|
|
313
|
+
but a non-uniform set is a dev-mode error; per-corner algebra is post-v1.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Accessibility
|
|
318
|
+
|
|
319
|
+
Accessibility is policy in `vitrea`, applied by the host layer through media
|
|
320
|
+
queries, with per-root prop overrides. It is resolved, not bolted on: each
|
|
321
|
+
preference has a declared consequence for the material or the motion, and the
|
|
322
|
+
strictest active preference wins.
|
|
323
|
+
|
|
324
|
+
| Preference | What changes |
|
|
325
|
+
| --- | --- |
|
|
326
|
+
| `prefers-reduced-motion` | No elastic overshoot, no deformation, no shimmer travel. Morphs become non-elastic interpolation. Direct-manipulation positional continuity is preserved — reduced motion is not *no* motion. |
|
|
327
|
+
| `prefers-reduced-transparency` | More frost, less refraction, higher occlusion. |
|
|
328
|
+
| `prefers-contrast: more` | Stronger borders, near-monochrome foregrounds, reduced ambient tint. |
|
|
329
|
+
| `forced-colors: active` | System colours, borders, **no glass** — every optical axis goes with it. |
|
|
330
|
+
|
|
331
|
+
The first three are overridable per root:
|
|
332
|
+
|
|
333
|
+
```tsx
|
|
334
|
+
<GlassRoot reducedTransparency={true} increasedContrast="system" />
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
`forced-colors` deliberately has **no** override prop, and its absence is
|
|
338
|
+
enforced in the type system: an operating-system colour mandate is not an app's
|
|
339
|
+
to switch off.
|
|
340
|
+
|
|
341
|
+
`prefers-reduced-transparency` is not Baseline across engines. On a platform that
|
|
342
|
+
cannot answer the query, leaving it on `"system"` silently resolves it to false
|
|
343
|
+
and the user's preference is lost — so vitrea emits a diagnostic saying exactly
|
|
344
|
+
that. The explicit override is load-bearing, not a courtesy.
|
|
345
|
+
|
|
346
|
+
One documented obligation on your side: content that vitrea portals into a plane
|
|
347
|
+
leaves its original DOM position, so if that content was inside a landmark
|
|
348
|
+
region, you own re-establishing the landmark. A `role`/landmark seam on the morph
|
|
349
|
+
component is deferred post-v1 API work.
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## License
|
|
354
|
+
|
|
355
|
+
Apache License 2.0. See [`LICENSE`](https://github.com/SSFSKIM/designer/blob/main/LICENSE).
|
|
356
|
+
|
|
357
|
+
"Liquid Glass" is the name of Apple Inc.'s design language, referenced here
|
|
358
|
+
descriptively to say what this library replicates. vitrea is not affiliated with,
|
|
359
|
+
endorsed by, or sponsored by Apple Inc. See [`NOTICE`](https://github.com/SSFSKIM/designer/blob/main/NOTICE).
|