Communitygithub.com

roolzksd/droidglass

Construit une interface utilisateur Liquid Glass de style Apple (iOS 26 / macOS 26) sur n'importe quelle plateforme. Web, Android WebView, Electron, Capacitor et Cordova reçoivent un moteur prêt et testé, avec réfraction réelle, bords spéculaires, gouttes fusionnées et boutons, toggles, curseurs et barres d'onglets extensibles façon iOS. Jetpack Compose utilise la bibliothèque Backdrop de Kyant ; SwiftUI, UIKit et AppKit utilisent le glassEffect système. Utilisez-le dès que l'utilisateur demande du Liquid Glass, du verre Apple ou iOS 26, du glassmorphisme, du verre dépoli, une barre d'onglets en verre, des boutons, toggles ou curseurs en verre, ou un « faites-le ressembler à Apple », même si les mots Liquid Glass ne sont pas utilisés.

Qu'est-ce que droidglass ?

DroidGlass est une bibliothèque de compétences IA qui reproduit le matériau Liquid Glass d'Apple (style iOS 26 / macOS 26) sur plusieurs plateformes, offrant une véritable réfraction du fond, des reflets arc-en-ciel sur les bords et des animations à ressorts. Contrairement au glassmorphisme ordinaire qui se contente d'un flou blanc, ce moteur simule l'épaisseur du verre, son gonflement au toucher et sa fusion avec les éléments voisins. Il prend en charge le Web et Android WebView via un moteur JavaScript/CSS complet, Jetpack Compose via la bibliothèque Backdrop de Kyant, et SwiftUI/UIKit/AppKit via l'API système native. L'outil fournit des recettes précises pour les boutons, toggles, curseurs, barres d'onglets, feuilles et loupes, avec des valeurs validées par Kyant, mais impose des règles strictes : le verre doit rester transparent, limité à la couche de navigation/contrôle, sans superposition de verre sur verre, et avec un maximum de 3 grands éléments en verre par écran.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roolzksd/DroidGlass/tree/HEAD

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

DroidGlass : Verre Liquide pour toute plateforme

Le verre liquide est le matériau d'Apple qui réfracte ce qui se trouve en dessous. Près du bord, l'arrière-plan est tiré vers le centre comme une lentille épaisse, un léger arc-en-ciel apparaît sur le bord, un fin liseré de surbrillance longe la bordure, et au toucher, le verre gonfle, s'étire vers le doigt et rebondit. Le glassmorphisme ordinaire ne fait que flouter l'arrière-plan sous une brume blanche, ce qui lui donne un aspect bon marché et mat.

La règle principale du bon goût : le verre est transparent. Si vous ne pouvez pas lire ce qui se trouve derrière, il s'agit de verre dépoli iOS 7, pas de verre liquide. Ajoutez du flou et une surface uniquement là où le texte repose sur le verre.

Indiquez honnêtement à l'utilisateur où se situent les limites. Le matériau réel n'existe que sur iOS, iPadOS et macOS 26 et ultérieurs ; tout le reste est une imitation. Sur Android, Backdrop offre une imitation complète (la lentille nécessite Android 13). Sur le Web, la réfraction ne fonctionne que dans Chromium (Chrome, Edge, Samsung Internet, Android WebView, Electron). Safari, Firefox et tous les navigateurs sur iOS obtiennent un léger flou avec les mêmes surbrillances, ombres et ressorts, mais sans déformation.

Flux de travail

  1. Identifiez la plateforme.
    • SwiftUI, UIKit, AppKit, WidgetKit sur iOS/macOS 26 : API système, voir references/apple.md. N'imitez rien.
    • Jetpack Compose ou Compose Multiplatform : references/android-compose.md. N'écrivez pas de shaders à partir de zéro, utilisez la bibliothèque.
    • Web, Electron, Android WebView, Capacitor, Cordova, Tauri sur Windows/Android : le moteur dans assets/, voir references/web.md. Dans WebView et Electron, la réfraction fonctionne toujours.
    • React Native, Flutter : pas d'équivalent système. Pour React Native, suggérez une couche WebView ou un module natif sur Backdrop ; pour Flutter, BackdropFilter comme solution de repli et un FragmentProgram avec les formules de references/math-and-motion.md. Vérifiez vous-même les packages actuels, cette compétence ne les liste pas.
  2. Choisissez 1 à 3 éléments de la couche de contrôle : barre d'onglets, bouton flottant, barre supérieure, feuille, menu, curseur ou pouce de toggle au toucher. Ne rendez pas le contenu en verre.
  3. Choisissez une recette dans le tableau ci-dessous. N'inventez pas de paramètres : les valeurs proviennent du catalogue de Kyant et ont été vérifiées à l'écran.
  4. Vérifiez l'arrière-plan sous le verre. Le verre n'est visible que sur un contenu riche : photos, couleurs, graphiques, texte en défilement. Sur une page blanche unie, le verre transparent disparaît presque : mettez de la couleur derrière, ajoutez une couche de fondu, ou supprimez le verre à cet endroit.
  5. Construisez à partir de la bonne référence et vérifiez par vous-même en utilisant la liste de contrôle à la fin. Ne remettez pas le travail sans captures d'écran au repos, en pression et en glissement.

Règles d'Apple

D'après les Human Interface Guidelines, WWDC25 « Meet Liquid Glass » et les compétences communautaires populaires. Enfreindre l'une d'elles trahit immédiatement l'imitation.

  • Seulement la couche de navigation et de contrôle qui flotte au-dessus du contenu. Les listes, lignes, cartes et l'arrière-plan de la page ne sont pas en verre. Exception : les pouces de toggle et de curseur deviennent en verre lorsqu'ils sont touchés.
  • Pas de verre sur du verre. Les éléments au-dessus du verre sont séparés par un remplissage et une opacité. Exception de Backdrop : un pouce de curseur sur une feuille en verre réfracte la feuille (exportedBackdrop) : une lentille sur une autre, pas deux plaques mates.
  • Utilisez-en peu. Seulement les contrôles les plus importants.
  • Le verre est incolore. La couleur et la luminosité proviennent de l'arrière-plan : clair sur clair, sombre sur sombre, la surbrillance est teintée par l'arrière-plan. Pas de surface blanche ou grise propre.
  • Deux modes, ne les mélangez pas. Clair (boutons, pouces, loupe, une barre d'onglets regroupée avec un bouton) : flou 0 à 4, pas de surface. Régulier (feuille, dialogue avec texte long) : flou 8 à 16 ; ajoutez une surface de 40 à 60 % uniquement si le texte est illisible sans elle.
  • Teintez uniquement l'action principale.
  • Forme. Capsule : rayon égal à la moitié de la hauteur. Coins concentriques : rayon intérieur égal au rayon du conteneur moins le remplissage.
  • Plus grand signifie plus épais : les grands éléments ont un bord incurvé plus large et une réfraction plus profonde.
  • Ne laissez jamais de contenu reposer à moitié sous le verre.
  • Liquide en mouvement. À la pression, le verre grandit de quelques pixels et s'incline vers le doigt avec amortissement ; un pouce gonfle de 1,5× et s'étire en goutte à grande vitesse. Tout fonctionne avec des ressorts, pas de transitions linéaires.

Recettes (valeurs du catalogue de Kyant)

ÉlémentEffetsSurbrillance et ombresToucher
Bouton, capsule 48 dpvibrancy, flou 2, lens(12, 24)Default, ombre par défautlueur ; croît de 4 dp en hauteur ; décalage min × tanh(0.05 × décalage / min) ; s'étire jusqu'à 4 dp vers le doigt
Bouton teintémême + teinteidentiqueidentique
Bouton avec surfacemême + blanc 30%identiqueidentique
Pouce de toggle 40×24 sur une piste 64×28au repos blanc 100% et flou 8 ; pressé p : flou 8(1-p), lens(5p, 10p, dispersion), blanc (1-p)Ambient, largeur /1.5, alpha p ; rayon d'ombre 4, 5% ; rayon d'ombre intérieure 4p, alpha péchelle à 1.5 ; la piste apparaît à travers la lentille, réduite à 0.75
Pouce de curseur 40×24, piste 6 dpcomme le toggle, lens(10p, 14p)comme le toggleéchelle à 1.5 ; taper sur la piste saute au point touché
Barre d'onglets 64 dpvibrancy, flou 8, lens(24, 24), surface #FAFAFA 40% (sombre #121212 40%)Defaultà la pression, le panneau entier croît de 16 dp en largeur (les étiquettes avec) et s'incline jusqu'à 4 dp après le doigt
Copie de ligne masquée 56 dp (tabsBackdrop)le même panneau dans la couleur d'accent, alpha(0) : vibrancy, flou 8, lens(24p, 24p), surface du panneauDefault avec alpha p, InteractiveHighlighticônes et étiquettes ×1.2 à la pression (LocalLiquidBottomTabScale est défini uniquement sur cette ligne)
Pouce de barre d'onglets 56 dpau repos gris 10% ; pressé lens(10p, 14p, dispersion) sur l'arrière-plan et la copie de ligne (rememberCombinedBackdrop(backdrop, tabsBackdrop))Default, ombre et ombre intérieure 8p avec alpha péchelle 78/56 ; à l'intérieur de la goutte, une « barre sous la barre » : son propre élément en accent, agrandi, voisins visibles aux bords
Dialogue, rayon 48luminosité 0.2 (clair), saturation 1.5, flou 16 (sombre 8), lens(24, 48, profondeur)Plainassombrit l'arrière-plan #29293A 23% (sombre #121212 56%)
Tuile du centre de contrôlevibrancy, lens(24, 48, profondeur)Default, angle d'inclinaison de l'appareil, atténuation 2entrée : décalage 48 dp et alpha
Loupe 128×96lens(8, 24, profondeur, dispersion), arrière-plan zoomé 1.5×ombre intérieure 16glisser

Les ressorts, les gestes et les mathématiques partagées pour chaque plateforme se trouvent dans references/math-and-motion.md.

Web et Android WebView en une minute

Copiez les trois fichiers de assets/ dans le projet sans les modifier et configurez-les avec des options. Ne réécrivez pas le moteur.

<link rel="stylesheet" href="liquid-glass.css">
<button id="buy">Acheter</button>
<div id="wifi" aria-label="Wi-Fi"></div>
<div id="volume" style="width: 280px"></div>
<nav id="tabs" style="position: fixed; left: 16px; right: 16px; bottom: 16px"></nav>
<script src="liquid-glass.js"></script>
<script src="liquid-ui.js"></script>
<script>
  LiquidUI.button(document.getElementById('buy'), { tint: '#0088FF', onClick: () => {} });
  LiquidUI.toggle(document.getElementById('wifi'), { checked: true, onChange: (on) => {} });
  LiquidUI.slider(document.getElementById('volume'), { value: 0.4, onInput: (v) => {}, label: 'Volume' });
  const tabs = LiquidUI.tabs(document.getElementById('tabs'), {
    items: [{ label: 'Accueil', icon: '<svg>…</svg>' }, { label: 'Recherche', icon: '<svg>…</svg>' }],
    index: 0, onChange: (i) => {},
  });
  // fusion : une barre et un bouton à côté d'elle fusionnent en une seule goutte ; les boutons extensibles voisins le font automatiquement
  // LiquidUI.blob([tabs.panel, fab], { blur: 3.5 }); LiquidUI.autoMerge(document.body); après un changement d'écran LiquidUI.sweep()
  // verre nu pour votre propre balisage
  const g = LiquidGlass.attach(document.getElementById('panel'), { radius: 28, blur: 8, refractionHeight: 24, refractionAmount: 24, surface: 'rgb(250 250 250 / .4)' });
  // g.set({ lens: 0..1, blur, surface, highlightAlpha, angle, shadowAlpha, innerShadow, press: { p, x, y }, tx, ty, sx, sy, sleep })
</script>
FichierCe que c'est
assets/liquid-glass.jsmoteur de verre : cartes de réfraction, dispersion, surbrillance, ombres, groupes de fusion (LiquidGlass)
assets/liquid-glass.cssstyles de base, solutions de repli pour l'accessibilité, styles de composants
assets/liquid-ui.jsressorts, gestes et composants : bouton, toggle, curseur, onglets, loupe, blob, autoMerge (LiquidUI)
assets/demo.htmltous les composants sur une seule page ; ouvrez-la pour voir à quoi ressemble un rendu correct

Avant de modifier quoi que ce soit ou de l'intégrer dans une application, lisez references/web.md : il liste les faits Chromium qui cassent presque toutes les implémentations (backdrop roots, position: fixed, touch-action, arrière-plans du body) et toutes les options. Quand quelque chose semble anormal, allez dans references/troubleshooting.md ; quand quelque chose saccade, references/performance.md.

Cinq choses à ne jamais se tromper sur le Web :

  • L'arrière-plan doit être un élément réel. Un arrière-plan défini sur body qui se propage à la racine n'est pas vu par backdrop-filter.
  • N'animez jamais opacity, filter, mask ou clip-path sur un ancêtre du verre (un fondu d'écran, par exemple) : cela devient une backdrop root et le verre perd son arrière-plan et s'assombrit. Déplacez les écrans avec transform et révélez-les avec une couche de voile au-dessus.
  • Ne définissez pas votre propre transform sur un élément en verre ; écrivez le décalage de base dans --lg-base.
  • Les boutons extensibles nécessitent touch-action: none (par défaut). Avec pan-y, le navigateur vole le glissement et envoie pointercancel.
  • Dans un Android WebView, désactivez l'appui long et les retours haptiques : setOnLongClickListener(v -> true) et setHapticFeedbackEnabled(false).

Accessibilité et lisibilité

  • Le moteur Web respecte prefers-reduced-transparency: reduce (verre désactivé, surface presque opaque ; Chrome et Edge 119+, pas encore Safari ou Firefox), prefers-contrast: more (surface et bordure pleines) et prefers-reduced-motion (les ressorts deviennent instantanés).
  • Les composants reçoivent des rôles et la prise en charge du clavier : bouton (Entrée, Espace), switch (Entrée, Espace), slider (flèches), tablist (flèches gauche et droite). Étiquetez-les avec aria-label ou aria-labelledby.
  • Sur Android, définissez semantics { role = Role.Switch } et les étiquettes, comme dans le catalogue de Kyant ; sur Android ancien, vérifiez que la couleur onDrawSurface est lisible sans effets.
  • Vérifiez le contraste du texte sur le contenu le plus clair et le plus chargé qui peut se retrouver sous le panneau : 4.5:1 pour le corps du texte. Si cela échoue, ajoutez du flou et une surface ou déplacez le contenu. Une ombre de texte ne résout pas le problème.

À ne pas faire

  • Une surface blanche translucide plus blur(10px) sur les boutons : c'est du verre dépoli, pas du verre liquide. La densité n'est acceptable que pour les barres d'onglets, les feuilles et les dialogues avec texte.
  • Des cartes de contenu en verre et un arrière-plan de page en verre.
  • De la dispersion sur de grands panneaux : coûteuse et criarde.
  • Une bordure blanche épaisse au lieu d'un fin liseré de surbrillance.
  • La même teinte sur chaque bouton.
  • Des transitions linéaires au lieu de ressorts pour la pression et le glissement.
  • L'animation de width et height du verre sur le Web : la carte est reconstruite à chaque image. Animez l'échelle.
  • Des étapes de filtre lourdes (flou, déplacement, convolution, morphologie) sous un résultat que plusieurs étapes lisent : Chrome les calcule une fois par branche et les téléphones gèlent.
  • Peindre le verre avec votre propre surface « pour l'esthétique ». Seuls les panneaux denses avec du texte reçoivent une surface.
  • Écrire vos propres shaders Compose alors que Backdrop convient.
  • Les symboles SF et les logos Apple en dehors des plateformes Apple : leur licence l'interdit. Utilisez des jeux d'icônes ouverts.
  • Appeler le résultat Web ou Android « Liquid Glass officiel ». C'est une imitation dans son style.

Liste de contrôle avant la remise

Captures d'écran à l'échelle 2, regardez-les vous-même :

  1. Au repos sur une grille ou du texte : les lignes sont visibles à travers le verre transparent, tirées vers le centre au bord, la surbrillance est fine. Sur fond blanc, le verre est séparé de la page par l'ombrage du bord et l'ombre ; sur fond sombre, par une ligne lumineuse sur le côté éclairé.
  2. Pression : le bouton a grandi et s'incline vers le doigt ; un pouce est gonflé et transparent, la piste se voit à travers, l'arc-en-ciel est doux, pas de trous colorés.
  3. Glissement : un pouce s'étire à vitesse et se dégonfle seulement après son arrivée ; la barre d'onglets s'incline et revient. La goutte de la barre d'onglets sur les onglets de bord et près du bord inférieur de l'écran : son propre élément à l'intérieur, les voisins aux bords, pas de zones noires, de bandes ou de pièces en miroir.
  4. Tirage : un bouton suit le doigt sur un élastique et rebondit ; une barre tirée vers un bouton voisin fusionne avec lui, le pont grandit à mesure qu'ils s'approchent, pas de couture ni de double bord ; au repos et sur une simple pression, ils restent séparés ; un tap normal fonctionne, un bouton tiré loin et relâché ne se déclenche pas.
  5. Sur une photo et sur fond blanc : la couleur sous le verre est riche, le texte est lisible.
  6. Thème sombre.
  7. Solution de repli : simulez le moteur (user agent Safari et navigator.userAgentData vide) et vérifiez que les éléments ne se sont pas transformés en trous et que les icônes sous le pouce de la barre d'onglets ne sont pas floues.
  8. Redimensionnement et rotation : la carte est reconstruite, pas de marches d'escalier sur le bord.
  9. Transitions d'écran : capturez plusieurs images consécutives pendant qu'un écran entre ; les boutons en verre ne sont jamais plus sombres qu'au repos, les couches de fusion restent exactement sous leurs boutons après l'animation.
  10. Aucune erreur dans la console et pas de blocage : après une rafale de taps, la page répond aussi rapidement. Une boucle d'animation, pas de requestAnimationFrames errants.
  11. Pas plus de 3 grands éléments en verre sur un écran de téléphone, pas de verre sur du verre, pas de contenu en verre.

Si quelque chose échoue, corrigez-le d'abord, puis montrez-le à l'utilisateur.

Sources

  • Kyant0/AndroidLiquidGlass, bibliothèque Backdrop et catalogue (Apache-2.0) : formules de lentille, dispersion, surbrillance et ombre, recettes de composants, constantes de ressorts et de gestes. Le moteur Web est un portage de ce schéma.
  • Apple : Human Interface Guidelines « Materials », « Adopting Liquid Glass », WWDC25 « Meet Liquid Glass ».
  • kube.io, « Liquid Glass in the Browser » : réfraction via feDisplacementMap à l'intérieur de backdrop-filter.
  • iyinchao/liquid-glass-studio (MIT) : fusion de formes via smin, réfraction de Snell, verre incolore avec une haute...

… [tronqué pour la traduction]

Skills associés