@godxjp/ui 28.13.0 → 29.0.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.
Files changed (159) hide show
  1. package/agent/START-HERE.md +29 -10
  2. package/agent/components/Anchor.json +6 -1
  3. package/agent/components/AppShell.json +1 -1
  4. package/agent/components/AreaChart.json +19 -1
  5. package/agent/components/BarChart.json +11 -1
  6. package/agent/components/Cascader.json +1 -1
  7. package/agent/components/CompactBarTrend.json +1 -1
  8. package/agent/components/DataState.json +1 -1
  9. package/agent/components/DataTable.json +4 -4
  10. package/agent/components/FormField.json +1 -1
  11. package/agent/components/InfiniteQueryState.json +1 -1
  12. package/agent/components/Input.json +1 -1
  13. package/agent/components/LineChart.json +20 -2
  14. package/agent/components/ListRow.json +1 -1
  15. package/agent/components/Masonry.json +1 -1
  16. package/agent/components/MasterDetail.json +1 -1
  17. package/agent/components/PasswordStrength.json +1 -1
  18. package/agent/components/PermissionMatrix.json +1 -1
  19. package/agent/components/Select.json +1 -0
  20. package/agent/components/Sidebar.json +1 -1
  21. package/agent/components/Table.json +8 -3
  22. package/agent/components/ThemeScope.json +49 -0
  23. package/agent/components/Topbar.json +1 -0
  24. package/agent/components/TopbarItem.json +2 -1
  25. package/agent/components/Transfer.json +1 -1
  26. package/agent/components/TreeSelect.json +1 -1
  27. package/agent/components/UploadCropDialog.json +1 -1
  28. package/agent/components/formatDate.json +1 -1
  29. package/agent/components-index.json +5 -0
  30. package/agent/components.json +138 -30
  31. package/agent/index.json +19 -9
  32. package/agent/llms.txt +10 -10
  33. package/agent/patterns/tenant-brand-color.json +28 -0
  34. package/agent/patterns-index.json +27 -0
  35. package/agent/patterns.json +28 -0
  36. package/agent/rules.json +15 -0
  37. package/agent/tokens.json +4965 -970
  38. package/dist/app/index.d.ts +3 -0
  39. package/dist/app/index.js +3 -0
  40. package/dist/app/tenant-theme.d.ts +80 -0
  41. package/dist/app/tenant-theme.js +154 -0
  42. package/dist/app/theme-axes.d.ts +14 -1
  43. package/dist/app/theme-axes.js +24 -31
  44. package/dist/components/charts/chart-cartesian.d.ts +5 -1
  45. package/dist/components/charts/chart-cartesian.js +15 -8
  46. package/dist/components/data-display/badge.d.ts +1 -1
  47. package/dist/components/data-display/badge.js +20 -2
  48. package/dist/components/data-display/carousel.js +4 -4
  49. package/dist/components/data-display/data-table.js +13 -2
  50. package/dist/components/data-display/permission-matrix.js +1 -1
  51. package/dist/components/data-display/table.d.ts +11 -2
  52. package/dist/components/data-display/table.js +18 -2
  53. package/dist/components/data-entry/control-appearance.d.ts +12 -6
  54. package/dist/components/data-entry/control-appearance.js +1 -1
  55. package/dist/components/data-entry/select.js +4 -3
  56. package/dist/components/feedback/dialog.js +6 -3
  57. package/dist/components/feedback/overlay-header-tone.d.ts +7 -0
  58. package/dist/components/feedback/overlay-header-tone.js +4 -4
  59. package/dist/components/feedback/sheet.d.ts +1 -1
  60. package/dist/components/feedback/sheet.js +6 -9
  61. package/dist/components/feedback/sonner.js +16 -3
  62. package/dist/components/general/button.js +22 -5
  63. package/dist/components/layout/affix.js +15 -1
  64. package/dist/components/layout/sidebar.js +7 -1
  65. package/dist/components/navigation/anchor.d.ts +1 -1
  66. package/dist/components/navigation/anchor.js +5 -4
  67. package/dist/components/navigation/app-setting-picker.js +1 -1
  68. package/dist/components/navigation/pagination.js +1 -1
  69. package/dist/components/navigation/tabs.js +15 -2
  70. package/dist/components/query/infinite-query-state.d.ts +22 -6
  71. package/dist/lib/control-styles.d.ts +31 -11
  72. package/dist/lib/control-styles.js +6 -6
  73. package/dist/lib/overlay-portal.d.ts +20 -0
  74. package/dist/lib/overlay-portal.js +93 -0
  75. package/dist/props/components/app.prop.d.ts +12 -0
  76. package/dist/props/components/charts.prop.d.ts +30 -0
  77. package/dist/props/components/index.d.ts +1 -1
  78. package/dist/props/components/navigation.prop.d.ts +21 -2
  79. package/dist/props/components/query.prop.d.ts +36 -2
  80. package/dist/props/registry.d.ts +46 -1
  81. package/dist/props/registry.js +38 -3
  82. package/dist/styles/alert-layout.css +34 -14
  83. package/dist/styles/badge-layout.css +10 -6
  84. package/dist/styles/base.css +14 -5
  85. package/dist/styles/card-layout.css +19 -8
  86. package/dist/styles/chart-layout.css +22 -3
  87. package/dist/styles/control.css +165 -59
  88. package/dist/styles/data-display-layout.css +129 -36
  89. package/dist/styles/data-entry-layout.css +23 -87
  90. package/dist/styles/dialog-layout.css +49 -19
  91. package/dist/styles/float-button-layout.css +5 -5
  92. package/dist/styles/focus-ring.css +9 -5
  93. package/dist/styles/layout.css +42 -15
  94. package/dist/styles/logo-layout.css +1 -1
  95. package/dist/styles/motion.css +1 -1
  96. package/dist/styles/navigation-layout.css +90 -29
  97. package/dist/styles/shell-layout.css +63 -40
  98. package/dist/styles/table-layout.css +56 -17
  99. package/dist/styles/text-layout.css +13 -4
  100. package/dist/styles/toggle.css +8 -2
  101. package/dist/tokens/components/actions.css +1 -1
  102. package/dist/tokens/components/attachments.css +4 -4
  103. package/dist/tokens/components/badge.css +4 -4
  104. package/dist/tokens/components/callout.css +1 -1
  105. package/dist/tokens/components/card.css +9 -4
  106. package/dist/tokens/components/chart.css +10 -1
  107. package/dist/tokens/components/chat-bubble.css +1 -1
  108. package/dist/tokens/components/control.css +28 -10
  109. package/dist/tokens/components/conversations.css +2 -1
  110. package/dist/tokens/components/data-display.css +12 -7
  111. package/dist/tokens/components/descriptions.css +1 -1
  112. package/dist/tokens/components/draggable-panel.css +1 -1
  113. package/dist/tokens/components/feedback.css +28 -8
  114. package/dist/tokens/components/float-button.css +1 -1
  115. package/dist/tokens/components/legal-document.css +1 -1
  116. package/dist/tokens/components/logo.css +1 -1
  117. package/dist/tokens/components/mega-menu.css +5 -3
  118. package/dist/tokens/components/navigation.css +21 -7
  119. package/dist/tokens/components/segmented.css +8 -3
  120. package/dist/tokens/components/shell.css +19 -5
  121. package/dist/tokens/components/table.css +9 -1
  122. package/dist/tokens/components/thought-chain.css +1 -1
  123. package/dist/tokens/components/toggle.css +2 -0
  124. package/dist/tokens/components/tree.css +3 -1
  125. package/dist/tokens/components/upload.css +6 -6
  126. package/dist/tokens/components/welcome.css +1 -1
  127. package/dist/tokens/foundation.css +28 -1
  128. package/docs/COMPOSITION-VS-COMPONENT.md +31 -0
  129. package/docs/CUSTOMER-THEMING.md +637 -1
  130. package/docs/FRAME-COVERAGE-REPORT.md +3 -2
  131. package/docs/GLASSMORPHISM-STANDARD.md +196 -0
  132. package/docs/THEME-API-COVERAGE.md +538 -0
  133. package/docs/TOKEN-RESOLUTION.md +195 -0
  134. package/docs/TOKENS.md +63 -24
  135. package/docs/asset-modules.d.ts +7 -0
  136. package/docs/data-display/charts.tsx +80 -0
  137. package/docs/data-display/data-table/index.tsx +30 -0
  138. package/docs/data-display/popover.tsx +1 -1
  139. package/docs/data-display/table.tsx +52 -0
  140. package/docs/feedback/sheet.tsx +10 -10
  141. package/docs/foundation/density.tsx +4 -4
  142. package/docs/i18n/messages/en.json +502 -0
  143. package/docs/i18n/messages/ja.json +502 -0
  144. package/docs/i18n/messages/vi.json +502 -0
  145. package/docs/layout/account-chip.tsx +2 -2
  146. package/docs/layout/responsive-grid.tsx +1 -1
  147. package/docs/navigation/toolbar.tsx +20 -12
  148. package/docs/providers/theme-scope.tsx +186 -0
  149. package/docs/showcase/caimono-price-comparison.tsx +911 -0
  150. package/docs/showcase/case4-login.tsx +2 -2
  151. package/docs/showcase/permission-matrix.tsx +13 -5
  152. package/docs/showcase/table-pagination.tsx +2 -1
  153. package/docs/showcase/tenant-brand-color.tsx +338 -0
  154. package/docs/showcase/theme-lab.tsx +2125 -0
  155. package/docs/themes/flat.css +462 -0
  156. package/docs/themes/glassmorphism.css +958 -0
  157. package/docs/themes/index.ts +200 -0
  158. package/package.json +4 -3
  159. package/scripts/explain-token.mjs +382 -0
@@ -3,8 +3,8 @@
3
3
  > Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
4
4
  > Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
5
5
 
6
- - Public components: **170**
7
- - With ≥1 frame: **149** · zero-frame: **21**
6
+ - Public components: **171**
7
+ - With ≥1 frame: **150** · zero-frame: **21**
8
8
  - Fully covered (every contract axis declared): **0**
9
9
 
10
10
  ## UNTESTED — no `/frame/**` route
@@ -129,6 +129,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
129
129
  | Toolbar | ✓ | N/A | · | N/A | · | · | · | · | · | · |
130
130
  | AppProvider | ✓ | · | · | · | · | · | · | · | · | · |
131
131
  | OverlayPortalProvider | **✗** | · | · | · | · | · | · | · | · | · |
132
+ | ThemeScope | ✓ | · | · | · | · | · | · | · | · | · |
132
133
  | formatDate | ✓ | · | · | · | · | · | · | · | · | · |
133
134
  | TimePicker | ✓ | · | · | · | · | · | · | · | · | · |
134
135
  | Cascader | ✓ | ✓ | · | · | · | · | · | · | · | · |
@@ -0,0 +1,196 @@
1
+ # Glassmorphism — the standard, and what this library must support
2
+
3
+ Written because the first attempt (`docs/themes/glassmorphism.css`, `/showcase/glassmorphism`)
4
+ produced grey-purple slabs on a muddy backdrop with 2.2:1 text, and the owner's verdict was
5
+ correct: _"màu không tương phản, màu trông rất ghê"_. This page is the target to build against,
6
+ not a description of what we shipped.
7
+
8
+ Sources are listed at the bottom. Nothing here is invented.
9
+
10
+ ---
11
+
12
+ ## 1. The recipe — namethatui.com, verbatim
13
+
14
+ ```css
15
+ background: rgba(255, 255, 255, 0.12);
16
+ backdrop-filter: blur(16px);
17
+ border: 1px solid rgba(255, 255, 255, 0.25);
18
+ border-radius: 16px;
19
+ ```
20
+
21
+ Fallback where `backdrop-filter` is unsupported: `background: rgba(30, 30, 40, 0.85)`.
22
+
23
+ **Four defining signals**, and a surface that drops any one of them is not glass:
24
+
25
+ 1. **Frosted translucent panels** — semi-transparent with a strong background blur; content behind is visible but softened.
26
+ 2. **A vivid backdrop showing through** — a gradient, photo or aurora behind the glass, _"its color bleeds through every panel and IS most of the palette."_
27
+ 3. **A thin light edge** — 1px semi-transparent white, often brighter on top, catching the rim and separating glass from glass.
28
+ 4. **Layered floating depth** — panels float above the backdrop and above each other with soft wide shadows; the stack of sheets is part of the look.
29
+
30
+ ### The number I got wrong, and it is the whole problem
31
+
32
+ **`0.12`.** The first build used **42–55% white**. At that opacity no backdrop colour bleeds through, so signal 2 is gone — and signal 2 is the one that says the palette comes from the backdrop. That is exactly why every pane came out the same grey no matter what else was tuned.
33
+
34
+ Going to `0.12` makes the contrast problem _harder_, not easier, which leads to the correction below.
35
+
36
+ ### Glassmorphism is not Liquid Glass
37
+
38
+ Glassmorphism applies the frosted treatment as a **decorative skin to any surface** — content cards, dashboards, panels, buttons, inputs. Apple's Liquid Glass reserves glass for the **control layer only** (bars, buttons, navigation) floating above opaque app content, with an adaptive material that lenses and retints.
39
+
40
+ The practical consequence here: **buttons and form fields are in scope.** A solid-purple primary button and an opaque white outline button on a glass page are the Liquid-Glass split applied backwards — the content is glass and the controls are not.
41
+
42
+ ## 2. The backdrop is part of the component
43
+
44
+ Glass is invisible on a flat colour. It needs something worth blurring: a photograph, or two or
45
+ three **saturated** colour blobs with room between them. A single dark-purple linear gradient —
46
+ what the first attempt used — gives the blur nothing to work with, which is why every pane came out
47
+ the same grey.
48
+
49
+ **Test for it:** if you replace the backdrop with a solid colour and the panes look the same, the
50
+ glass is doing nothing.
51
+
52
+ ## 3. Contrast — the rule that outranks the aesthetic
53
+
54
+ WCAG 2.2: **4.5:1 for body text**, **3:1 for large text and UI components**. Transparency and blur
55
+ both _reduce_ contrast, so on glass this is where the design fails first — and it is a requirement,
56
+ not a preference.
57
+
58
+ Concretely, for this library:
59
+
60
+ - **One ink ramp for the whole theme.** Every text token on glass resolves to the same
61
+ high-contrast family — near-white on dark glass, near-black on light glass. The owner's second
62
+ note, _"màu sắc chữ phải tương phản và đồng bộ"_, is this: a card that uses three different
63
+ greys for title, body and caption will have one that passes and two that fail.
64
+ - **The remedy is a SCRIM, not darker ink.** The source is explicit: _"measure text contrast against the worst backdrop region or add a translucent contrast scrim."_ My first fix darkened the ink ramp instead, which worked at 42% fill and will not survive `0.12` — at that opacity the text sits on whatever the backdrop is doing underneath, and a gradient has no single answer. A scrim behind the text block is the move that holds across the whole backdrop.
65
+ - **Measure against the WORST region the backdrop can produce**, not a convenient sample. A radial gradient has a light lobe and a dark one; the panel must be legible over both.
66
+ - **Muted/secondary text is the first casualty.** Our measurement: title 6.19:1 passed while five
67
+ secondary strings on the same card measured **2.19–3.05:1**. On glass, "muted" cannot mean
68
+ "lower contrast" — it must mean _smaller_ or _lighter weight_, at the same ratio.
69
+ - **Status colours do not survive translucency.** Success/warning/error ink measured 2.37–3.05:1
70
+ over glass. Either the chip gets a more opaque fill, or the status is carried by an icon plus
71
+ text rather than by hue.
72
+ - **Measure the composited pixel, not the declared colour.** A `rgba()` fill over a busy backdrop
73
+ is not the colour you wrote. Screenshot, sample the pixel under the text, compute the ratio.
74
+ - **A CLAMPED INK IS CLAMPED AGAINST ONE SURFACE, AND A DARK THEME MUST SAY WHICH.** The sharpest
75
+ thing measurement taught here, and no source above says it. A generator that walks an ink until it
76
+ clears 4.5:1 has to be told the ground: `tenantTheme(hex)` defaults to the package's LIGHT surface,
77
+ so on a dark theme it walks the ink the WRONG WAY — measured on glass/citron it emitted
78
+ rgb(124,103,0) over a #3b382b panel and read **2.09:1**, while the theme's own `--foreground` beside
79
+ it was near-white. Worse, it emits the result as a literal in `style`, which outranks the
80
+ `--text-link` the theme declared. Pass the theme's own surface (`options.surface`) — and pass the
81
+ surface that gives the LEAST contrast with the walked ink, which is **not the same one in both
82
+ polarities**:
83
+
84
+ | | the ink walks | so the hardest ground is | pass |
85
+ | ----------- | ------------- | ------------------------ | ---------------------------------------- |
86
+ | light theme | darker | the DARKEST surface | e.g. this package's `--accent` #ebe9e5 |
87
+ | dark theme | lighter | the LIGHTEST surface | e.g. the same theme's `--accent` #3c3a34 |
88
+
89
+ Clearing the hardest ground clears every other one, because the ink only gains contrast as the
90
+ ground moves away from it. I got this backwards the first time and it is an easy mistake: the rule
91
+ reads "lightest" in a dark theme and "darkest" in a light one, so a value measured under one
92
+ polarity is actively wrong under the other. The check that the method is right is that it
93
+ reproduces the two numbers the library already publishes — `INK_SURFACE_LIGHT = "#ebe9e5"`
94
+ (`src/app/tenant-theme.ts`) and the #3c3a34 its docblock names for the dark theme. Measure both
95
+ and compare before trusting a value for a theme of your own.
96
+
97
+ ## 4. Overlays — where this matters most
98
+
99
+ Dropdown, modal and drawer are the hardest cases and the owner flagged them by name.
100
+
101
+ - **Each pane must blur the REAL page behind it**, not a smeared copy of its parent. A dropdown
102
+ nested inside an already-blurred panel double-blurs and reads as dirty glass.
103
+ - **A modal's scrim is where the blur belongs**, not the dialog box. `backdrop-filter` on an
104
+ element makes it the containing block for its fixed descendants — this library already documents
105
+ that trap at `src/styles/shell-layout.css:1728`, where the app-launcher blur is deliberately on
106
+ the scrim.
107
+ - **A drawer covers content that must stay unreadable-but-present.** Keep its fill at the opaque
108
+ end of the range; a drawer you can read the page through is a drawer nobody can read.
109
+ - **A dropdown is small and sits over arbitrary content.** It needs the _most_ opaque fill of the
110
+ three, because a 7-line menu over a photograph is unreadable at `0.12`.
111
+
112
+ ## 4b. Form fields — where glassmorphism usually breaks
113
+
114
+ The owner asked for Input, Select and the rest to match. They are the hardest surface in the
115
+ system, and the literature is blunt about why: **a translucent input with a low-contrast border is
116
+ unusable.** An input has to read as a _place you can type_ before it reads as glass, and
117
+ translucency destroys exactly the two signals that say so — the boundary and the fill.
118
+
119
+ What a correct glass field has:
120
+
121
+ | | requirement |
122
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------------ |
123
+ | **fill** | frosted, but MORE opaque than the card it sits on. A field at the card's own alpha disappears into it. |
124
+ | **inner shadow** | `inset 0 1px 2px rgba(0,0,0,.15)` — the depth cue that says "recessed", replacing the border the glass just weakened |
125
+ | **border** | ≥ **3:1** against the surface behind it. WCAG 2.2 SC 1.4.11 covers the field boundary as a UI component. |
126
+ | **focus ring** | **2px, `:focus-visible`, and it must survive ANY backdrop.** A ring tinted to the glass is invisible over a light photo. |
127
+ | **placeholder** | 4.5:1 like any other text. Placeholder grey on frosted glass is the single most common failure. |
128
+ | **filled vs empty** | both states checked. An empty field on glass often has no visible box at all. |
129
+ | **label** | a real `<label>`, never a placeholder standing in for one — translucency makes a vanished label unrecoverable. |
130
+
131
+ For **Select** specifically the trigger and the listbox are two different problems: the trigger is a
132
+ field and follows this table; the **listbox is an overlay** and follows §4 — it needs the most
133
+ opaque fill of any surface, because a menu over arbitrary content is unreadable at a card's alpha.
134
+
135
+ In this library the field surface is `--control-surface-background` /
136
+ `--control-surface-border-color`, which Input, Select, Textarea, NumberInput and the pickers share.
137
+ That sharing is the opportunity — one pair retunes every field — and the risk: it also means a
138
+ field cannot currently differ from a card, which is the first thing this table asks for.
139
+
140
+ ## 5. The fallbacks that make it shippable
141
+
142
+ - **`@supports not (backdrop-filter: blur(1px))`** → a solid fill. Without it the panel is a
143
+ washed-out rectangle on any engine that lacks support.
144
+ - **`prefers-reduced-transparency`** → solid fills. This is an OS accessibility setting; honouring
145
+ it is not optional.
146
+ - **`prefers-reduced-motion`** for any animated backdrop.
147
+ - Backdrop blur is GPU-expensive. Blur the _few_ surfaces that define depth — shell chrome and
148
+ overlays — not every card, row and chip.
149
+
150
+ ## 6. What this library must expose for any of it to be reachable
151
+
152
+ Measured on the first attempt: **1 of 19 surfaces** could take a blur (Topbar), **3 of 19** a
153
+ gradient. **Measured now, token-only, on `/showcase/theme-lab?theme=glass`: 12 of 25 surfaces carry
154
+ a backdrop blur, 19 of 25 are translucent, 9 of 25 shadowed, and contrast is 557–558 of 559 strings
155
+ at every one of the five seeds** (the remainder is one badge on a hovered table row at 4.43:1).
156
+
157
+ Items 3, 5 and 6 below are CLOSED — kept with their measurements because each names a shape of
158
+ defect worth recognising again, not because it is still open:
159
+
160
+ - **3 — Dialog and Sheet fills** are knobs now (`--dialog-surface-background`,
161
+ `--sheet-surface-background`, `src/tokens/components/feedback.css`), both `initial` and resolved at
162
+ the call site.
163
+ - **5 — Card's gradient** is a real two-stop ramp; `card-layout.css` no longer names one variable
164
+ twice.
165
+ - **6 — Nested control surfaces** have knobs: `--tabs-list-background` and
166
+ `--tabs-trigger-active-background` exist and are read (`navigation-layout.css:268`).
167
+
168
+ The gaps that REMAIN, in priority order:
169
+
170
+ 1. **A backdrop-blur knob on every surface that can float** — Card, Dialog, Sheet, Popover,
171
+ DropdownMenu, Select listbox, Tooltip, Toast, Sidebar, Table surface. Today only
172
+ `--topbar-backdrop-blur-size` and `--app-launcher-launchpad-backdrop-blur-size` exist.
173
+ 2. **A saturate companion** to each, or one shared `--surface-backdrop-saturate`. Blur without
174
+ saturate is the grey mush.
175
+ 3. **Dialog and Sheet fills are dead ends** — `dialog-layout.css:56` hard-codes
176
+ `hsl(var(--background))`; Sheet bakes `bg-background` into its className.
177
+ 4. **`--background` cannot take an alpha** — it is already composed with one, so a second `/` is
178
+ invalid CSS. Any surface that reads it cannot be made translucent.
179
+ 5. **Card cannot take a real gradient** — `card-layout.css:49` writes
180
+ `linear-gradient(var(--card-tint), var(--card-tint))`, the same variable twice, so a two-colour
181
+ value degenerates into a hard split.
182
+ 6. **Nested control surfaces have no knobs** — `--tabs-list-background` and
183
+ `--tabs-trigger-active-background` do not exist, so a glass card's Tabs stay opaque `--muted`
184
+ while the card around them is translucent. This is the "các card này có đồng bộ đéo đâu"
185
+ defect: the container is glass and everything inside it is not.
186
+ 7. **The `--*-shadow` mirrors are frozen at `:root`**, so setting `--shadow-color` alone moves
187
+ nothing for Card, Sheet, Popover, Tooltip or Segmented.
188
+
189
+ ## Sources
190
+
191
+ - [namethatui — Glassmorphism](https://namethatui.com/styles/glassmorphism) — the recipe and the four signals quoted above
192
+ - [Axess Lab — Glassmorphism Meets Accessibility](https://axesslab.com/glassmorphism-meets-accessibility-can-frosted-glass-be-inclusive/)
193
+ - [Superdesign — Glassmorphism CSS recipe and when not to use it](https://www.superdesign.dev/styles/glassmorphism)
194
+ - [CSS Studio — The Complete Guide to Frosted Glass Effects](https://css-studio.com/blog/glassmorphism-css-guide)
195
+ - [IxDF — What Is Glassmorphism](https://ixdf.org/literature/topics/glassmorphism)
196
+ - [CodeFronts — Glassmorphic dropdown & mega menu](https://codefronts.com/navigation/css-glassmorphic-navbars/glassmorphic-dropdown-mega-menu/)