Communitygithub.com

DroidGlass: 모든 플랫폼을 위한 리퀴드 글래스

Apple의 리퀴드 글래스 UI(iOS 26/macOS 26 스타일)를 모든 플랫폼에서 구현합니다. 웹, Android WebView, Electron, Capacitor, Cordova를 위한 준비된 엔진과 Jetpack Compose를 위한 Backdrop 라이브러리를 제공합니다.

DroidGlass: 모든 플랫폼을 위한 리퀴드 글래스란 무엇인가요?

DroidGlass는 Apple의 리퀴드 글래스(Liquid Glass) 머티리얼을 다양한 플랫폼에서 재현하는 AI 에이전트 스킬입니다. 리퀴드 글래스는 단순한 유리 효과(glassmorphism)와 달리 실제 굴절, 스펙큘러 림, 병합되는 드롭 효과를 특징으로 하며, iOS 26/macOS 26 이상에서만 네이티브로 지원됩니다. 이 스킬은 사용자가 '리퀴드 글래스', 'Apple 스타일 유리 효과', 'iOS 26 유리' 등을 요청할 때 자동으로 활성화됩니다. 플랫폼별로 다른 접근 방식을 사용합니다. SwiftUI/UIKit/AppKit에서는 시스템 API를 활용하고, Jetpack Compose에서는 Kyant의 Backdrop 라이브러리를 사용합니다. 웹/Electron/Android WebView 등에서는 assets에 포함된 자체 엔진으로 굴절, 분산, 하이라이트, 그림자, 스프링 애니메이션을 구현합니다. React Native와 Flutter는 백업 솔루션을 제공합니다. 이 스킬은 Apple HIG 가이드라인을 따르며, 투명성, 제한된 사용, 두 가지 모드(선명/일반), 형태와 움직임에 대한 정확한 규칙을 강조합니다. 또한 접근성, 성능 최적화, 크로스 브라우저 호환성(특히 Chromium 기반 브라우저에서만 완전한 굴절 지원)에 대한 주의사항을 포함합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roolzksd/DroidGlass/tree/HEAD

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

DroidGlass: 모든 플랫폼을 위한 리퀴드 글래스은(는) 무엇을 하나요?

리퀴드 글래스(Liquid Glass)는 Apple의 머티리얼로, 그 아래에 있는 것을 굴절시킵니다. 림 근처에서는 배경이 두꺼운 렌즈처럼 중앙으로 당겨지고, 가장자리에 부드러운 무지개가 나타나며, 림을 따라 가는 하이라이트 선이 흐릅니다. 터치하면 유리가 팽창하고 손가락 쪽으로 늘어났다가 다시 튕겨집니다. 일반적인 유리 효과(glassmorphism)는 단순히 배경을 흰색 안개로 흐리게 하여 싸고 무광택처럼 보이게 만듭니다.

감각의 핵심 규칙: 유리는 투명합니다. 뒤에 있는 것을 읽을 수 없다면, 그것은 iOS 7 스타일의 프로스티드 글래스(Frosted Glass)이지 리퀴드 글래스가 아닙니다. 텍스트가 유리 위에 있는 경우에만 블러와 표면을 추가하세요.

한계를 사용자에게 정직하게 알리세요. 실제 머티리얼은 iOS, iPadOS, macOS 26 이상에서만 존재합니다. 그 외 모든 것은 모방입니다. Android에서는 Backdrop이 완전한 모방을 제공합니다(렌즈 기능은 Android 13 필요). 웹에서는 굴절이 Chromium(Chrome, Edge, Samsung Internet, Android WebView, Electron)에서만 작동합니다. Safari, Firefox 및 iOS의 모든 브라우저는 굴절 없이 동일한 하이라이트, 그림자 및 스프링을 가진 가벼운 블러를 얻습니다.

워크플로우

  1. 플랫폼을 식별하세요.
    • iOS/macOS 26의 SwiftUI, UIKit, AppKit, WidgetKit: 시스템 API 사용, references/apple.md 참조. 아무것도 모방하지 마세요.
    • Jetpack Compose 또는 Compose Multiplatform: references/android-compose.md 참조. 처음부터 셰이더를 작성하지 말고 라이브러리를 사용하세요.
    • Web, Electron, Android WebView, Capacitor, Cordova, Windows/Android의 Tauri: assets/의 엔진 사용, references/web.md 참조. WebView 및 Electron에서는 굴절이 항상 작동합니다.
    • React Native, Flutter: 시스템에 해당하는 것이 없습니다. React Native의 경우 WebView 레이어 또는 Backdrop의 네이티브 모듈을 제안하세요. Flutter의 경우 대체제로 BackdropFilter를 사용하고 references/math-and-motion.md의 공식을 사용하여 FragmentProgram을 사용하세요. 현재 패키지를 직접 확인하세요. 이 스킬은 나열하지 않습니다.
  2. 컨트롤 레이어의 1~3개 요소를 선택하세요: 탭 바, 플로팅 버튼, 상단 바, 시트, 메뉴, 토글 또는 터치된 슬라이더 썸. 콘텐츠는 유리로 만들지 마세요.
  3. 아래 표에서 레시피를 선택하세요. 매개변수를 임의로 만들지 마세요. 값은 Kyant의 카탈로그에서 가져왔으며 화면에서 확인되었습니다.
  4. 유리 아래의 배경을 확인하세요. 유리는 풍부한 콘텐츠(사진, 색상, 차트, 스크롤 중인 텍스트) 위에서만 보입니다. 평범한 흰색 페이지 위에서는 투명 유리가 거의 사라집니다. 유리 뒤에 색상을 배치하거나, 어두운 레이어를 추가하거나, 그 위치에서 유리를 제거하세요.
  5. 올바른 레퍼런스를 사용하여 빌드하고 마지막의 체크리스트를 사용하여 직접 눈으로 확인하세요. 정지, 누름 및 드래그 상태의 스크린샷 없이 넘기지 마세요.

Apple의 규칙

Human Interface Guidelines, WWDC25 "Meet Liquid Glass" 및 인기 커뮤니티 스킬에서 가져왔습니다. 이 중 하나라도 어기면 즉시 가짜가 드러납니다.

  • 콘텐츠 위에 떠 있는 탐색 및 컨트롤 레이어만 유리여야 합니다. 목록, 행, 카드 및 페이지 배경은 유리가 아닙니다. 예외: 토글 및 슬라이더 썸은 터치되는 동안 유리가 됩니다.
  • 유리 위에 유리를 배치하지 마세요. 유리 위의 요소는 채움과 불투명도로 분리됩니다. Backdrop의 예외: 유리 시트 위의 슬라이더 썸은 시트(exportedBackdrop)를 굴절시킵니다. 하나의 렌즈 위에 다른 렌즈가 있는 것이지, 두 개의 무광택 판이 아닙니다.
  • 조금만 사용하세요. 가장 중요한 컨트롤에만 사용하세요.
  • 유리는 무색입니다. 색상과 밝기는 배경에서 비롯됩니다. 밝은 배경 위에서는 밝게, 어두운 배경 위에서는 어둡게, 하이라이트는 배경에 의해 색상이 지정됩니다. 자체적인 흰색 또는 회색 표면이 없습니다.
  • 두 가지 모드를 혼합하지 마세요. 선명함(버튼, 썸, 돋보기, 버튼과 함께 그룹화된 탭 바): 블러 04, 표면 없음. 일반(긴 텍스트가 있는 시트, 대화상자): 블러 816; 텍스트가 없으면 읽을 수 없는 경우에만 40~60% 표면을 추가하세요.
  • 기본 동작만 색상을 지정하세요.
  • 모양. 캡슐: 반경은 높이의 절반입니다. 동심 모서리: 내부 반경은 컨테이너 반경에서 패딩을 뺀 값입니다.
  • 클수록 더 두껍습니다: 큰 요소는 더 넓은 곡선 림과 더 깊은 굴절을 얻습니다.
  • 콘텐츠가 유리 아래에 반쯤 걸쳐 있도록 두지 마세요.
  • 움직이는 액체. 누르면 유리가 몇 픽셀 커지고 감쇠와 함께 손가락 쪽으로 기울어집니다. 썸은 1.5배 팽창하고 속도에 따라 방울 모양으로 늘어납니다. 모든 것은 스프링으로 실행되며 선형 전환은 없습니다.

레시피 (Kyant의 카탈로그에서 가져온 값)

요소효과하이라이트 및 그림자터치
버튼, 48 dp 캡슐비브랜스, 블러 2, 렌즈(12, 24)기본값, 기본 그림자빛남; 높이 4dp 증가; 오프셋 min × tanh(0.05 × offset / min); 손가락 방향으로 최대 4dp 늘어남
색상이 있는 버튼동일 + 색상동일동일
표면이 있는 버튼동일 + 흰색 30%동일동일
토글 썸 40×24 on 64×28 트랙정지 시 흰색 100%, 블러 8; 누를 때 p: 블러 8(1−p), 렌즈(5p, 10p, 분산), 흰색 (1−p)앰비언트, 너비 /1.5, 알파 p; 그림자 반경 4, 5%; 내부 그림자 반경 4p, 알파 p1.5배 확대; 트랙이 렌즈를 통해 보이며 0.75로 축소됨
슬라이더 썸 40×24, 6 dp 트랙토글과 유사, 렌즈(10p, 14p)토글과 유사1.5배 확대; 트랙을 탭하면 해당 지점으로 이동
탭 바 64 dp비브랜스, 블러 8, 렌즈(24, 24), 표면 #FAFAFA 40% (다크 모드 #121212 40%)기본값누르면 전체 패널 너비가 16dp 증가하고(레이블도 함께) 손가락 방향으로 최대 4dp 기울어짐
숨겨진 행 복사본 56 dp (tabsBackdrop)강조 색상의 동일한 패널, alpha(0): 비브랜스, 블러 8, 렌즈(24p, 24p), 패널 표면알파 p가 있는 기본값, InteractiveHighlight누르면 아이콘 및 레이블 ×1.2 (LocalLiquidBottomTabScale은 이 행에만 설정됨)
탭 바 썸 56 dp정지 시 회색 10%; 누를 때 렌즈(10p, 14p, 분산) 배경 및 행 복사본 위 (rememberCombinedBackdrop(backdrop, tabsBackdrop))기본값, 그림자 및 내부 그림자 8p, 알파 p78/56 확대; 드롭 내부에 "바 아래 막대": 강조 색상의 자체 항목, 확대됨, 림에 이웃 항목 표시됨
대화상자, 반경 48밝기 0.2 (라이트 모드), 채도 1.5, 블러 16 (다크 모드 8), 렌즈(24, 48, 깊이)일반배경 어둡게 #29293A 23% (다크 모드 #121212 56%)
제어 센터 타일비브랜스, 렌즈(24, 48, 깊이)기본값, 기울기 각도, 폴오프 2진입: 48 dp 오프셋 및 알파
돋보기 128×96렌즈(8, 24, 깊이, 분산), 배경 1.5배 확대내부 그림자 16드래그

스프링, 제스처 및 모든 플랫폼의 공유된 수학은 references/math-and-motion.md에 있습니다.

웹 및 Android WebView 1분 만에 설정하기

assets/에서 세 개의 파일을 프로젝트에 변경 없이 복사하고 옵션으로 구성하세요. 엔진을 다시 작성하지 마세요.

<link rel="stylesheet" href="liquid-glass.css">
<button id="buy">구매</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: '볼륨' });
  const tabs = LiquidUI.tabs(document.getElementById('tabs'), {
    items: [{ label: '홈', icon: '<svg>…</svg>' }, { label: '검색', icon: '<svg>…</svg>' }],
    index: 0, onChange: (i) => {},
  });
  // 병합: 바와 그 옆에 있는 버튼이 하나의 드롭으로 합쳐짐; 이웃하는 스트레치 버튼은 자동으로 합쳐짐
  // LiquidUI.blob([tabs.panel, fab], { blur: 3.5 }); LiquidUI.autoMerge(document.body); 화면 변경 후 LiquidUI.sweep()
  // 자체 마크업을 위한 베어 글래스
  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>
파일설명
assets/liquid-glass.js유리 엔진: 굴절 맵, 분산, 하이라이트, 그림자, 병합 그룹 (LiquidGlass)
assets/liquid-glass.css기본 스타일, 접근성 대체 스타일, 컴포넌트 스타일
assets/liquid-ui.js스프링, 제스처 및 컴포넌트: 버튼, 토글, 슬라이더, 탭, 돋보기, blob, autoMerge (LiquidUI)
assets/demo.html한 페이지에 모든 컴포넌트; 올바른 모양을 보려면 열어보세요

무엇을 변경하거나 앱에 연결하기 전에 references/web.md를 읽으세요. 거의 모든 구현을 망가뜨리는 Chromium 관련 사실들(backdrop roots, position: fixed, touch-action, body backgrounds)과 모든 옵션이 나열되어 있습니다. 문제가 있을 경우 references/troubleshooting.md를 참조하고, 끊김이 있을 경우 references/performance.md를 참조하세요.

웹에서 절대 실수하지 말아야 할 다섯 가지:

  • 배경은 실제 요소여야 합니다. body에 설정되어 루트로 전파되는 배경은 backdrop-filter에 의해 인식되지 않습니다.
  • 유리의 상위 요소에서 opacity, filter, mask 또는 clip-path를 애니메이션하지 마세요(예: 화면 페이드 인). 이는 backdrop root가 되어 유리가 배경을 잃고 어두워집니다. transform으로 화면을 이동하고 상단의 베일 레이어로 화면을 드러내세요.
  • 유리 요소에 자체 transform을 설정하지 마세요. 기본 오프셋을 --lg-base에 작성하세요.
  • 스트레치 버튼에는 touch-action: none(기본값)이 필요합니다. pan-y를 사용하면 브라우저가 드래그를 가로채서 pointercancel을 보냅니다.
  • Android WebView에서 길게 누르기 및 햅틱을 비활성화하세요: setOnLongClickListener(v -> true) 및 setHapticFeedbackEnabled(false).

접근성 및 가독성

  • 웹 엔진은 prefers-reduced-transparency: reduce(유리 끄기, 거의 불투명한 표면, Chrome 및 Edge 119+, 아직 Safari 또는 Firefox는 아님), prefers-contrast: more(단색 표면 및 테두리) 및 prefers-reduced-motion(스프링이 즉시 적용됨)을 존중합니다.
  • 컴포넌트는 역할 및 키보드 지원을 받습니다: 버튼(Enter, Space), switch(Enter, Space), slider(화살표), tablist(왼쪽 및 오른쪽 화살표). aria-label 또는 aria-labelledby로 레이블을 지정하세요.
  • Android에서는 Kyant의 카탈로그와 같이 semantics { role = Role.Switch } 및 레이블을 설정하세요. 오래된 Android에서는 onDrawSurface 색상이 효과 없이 읽을 수 있는지 확인하세요.
  • 패널 아래에 올 수 있는 가장 밝고 복잡한 콘텐츠 위에서 텍스트 대비를 확인하세요: 본문 텍스트의 경우 4.5:1. 실패하면 블러와 표면을 추가하거나 콘텐츠를 이동하세요. 텍스트 그림자는 문제를 해결하지 못합니다.

하지 말 것

  • 버튼에 흰색 반투명 표면 + blur(10px)를 사용하는 것: 그것은 프로스티드 글래스이지 리퀴드 글래스가 아닙니다. 밀도는 탭 바, 시트 및 텍스트가 있는 대화상자에만 적합합니다.
  • 유리 콘텐츠 카드 및 유리 페이지 배경.
  • 큰 패널에서 분산 사용: 비싸고 화려합니다.
  • 가는 하이라이트 대신 두꺼운 흰색 테두리.
  • 모든 버튼에 동일한 색상 지정.
  • 누름 및 드래그에 스프링 대신 선형 transition 사용.
  • 웹에서 유리의 width 및 height 애니메이션: 매 프레임마다 맵이 다시 빌드됩니다. scale을 애니메이션하세요.
  • 여러 단계에서 읽는 결과 아래에 무거운 필터 단계(블러, 변위, 컨볼루션, 형태)를 사용하는 것: Chrome은 분기당 한 번 계산하고 휴대폰이 멈춥니다.
  • "보기 좋게" 자체 표면으로 유리를 칠하는 것. 텍스트가 있는 밀도 있는 패널만 표면을 얻습니다.
  • Backdrop이 적합한 경우 자체 Compose 셰이더를 작성하는 것.
  • Apple 플랫폼 외부에서 SF Symbols 및 Apple 로고 사용: 라이선스가 금지합니다. 오픈 아이콘 세트를 사용하세요.
  • 웹 또는 Android 결과를 "공식 리퀴드 글래스"라고 부르는 것. 그것은 스타일을 모방한 것입니다.

인계 전 체크리스트

2배율 스크린샷을 찍어 직접 확인하세요:

  1. 격자 또는 텍스트 위에서 정지: 선이 투명 유리를 통해 보이며, 림에서 중앙으로 당겨지고, 하이라이트가 얇습니다. 흰색 위에서는 림 음영과 그림자로 유리가 페이지와 구분됩니다. 어두운 곳에서는 밝은 쪽의 밝은 선으로 구분됩니다.
  2. 누름: 버튼이 커지고 손가락 쪽으로 기울어집니다. 썸은 팽창하고 투명해지며 트랙이 그를 통해 보이고 무지개가 부드럽고 색깔 구멍이 없습니다.
  3. 드래그: 썸이 속도에 따라 늘어나고 도착한 후에야 수축됩니다. 탭 바가 기울어졌다가 돌아옵니다. 가장자리 탭 및 화면 하단 가장자리 근처의 탭 바 드롭: 내부에 자체 항목, 림에 이웃 항목, 검은색 영역, 밴드 또는 미러링된 조각이 없습니다.
  4. 당기기: 버튼이 고무 밴드처럼 손가락을 따라갔다가 튕겨 돌아옵니다. 이웃 버튼 쪽으로 당겨진 바가 그 버튼과 합쳐지고, 다가갈수록 연결 브릿지가 커지며, 이음새나 이중 림이 없습니다. 정지 및 간단한 누름 시에는 분리되어 있습니다. 일반 탭이 작동하고, 멀리 당겨진 버튼을 놓아도 실행되지 않습니다.
  5. 사진 위 및 흰색 위: 유리 아래 색상이 풍부하고 텍스트를 읽을 수 있습니다.
  6. 다크 테마.
  7. 대체: 엔진을 가장하여(Safari user agent 및 빈 navigator.userAgentData) 요소가 구멍으로 변하지 않고 탭 바 썸 아래 아이콘이 흐려지지 않는지 확인하세요.
  8. 크기 조정 및 회전: 맵이 다시 빌드되고 림에 계단 현상이 없습니다.
  9. 화면 전환: 화면이 진입하는 동안 여러 연속 프레임을 캡처하세요. 유리 버튼이 정지 상태보다 어둡지 않고, 병합 레이어가 애니메이션 후에도 정확히 버튼 아래에 있어야 합니다.
  10. 콘솔 오류 없음 및 중단 없음: 연속 탭 후에도 페이지가 빠르게 응답합니다. 하나의 애니메이션 루프, 불필요한 requestAnimationFrame 없음.
  11. 휴대폰 화면에 3개 이상의 큰 유리 요소 없음, 유리 위에 유리 없음, 유리 콘텐츠 없음.

문제가 있으면 먼저 수정한 후 사용자에게 보여주세요.

출처

  • Kyant0/AndroidLiquidGlass, Backdrop 라이브러리 및 카탈로그 (Apache-2.0): 렌즈, 분산, 하이라이트 및 그림자 공식, 컴포넌트 레시피, 스프링 및 제스처 상수. 웹 엔진은 이 체계의 포트입니다.
  • Apple: Human Interface Guidelines "Materials", "Adopting Liquid Glass", WWDC25 "Meet Liquid Glass".
  • kube.io, "Liquid Glass in the Browser": backdrop-filter 내의 feDisplacementMap을 통한 굴절.
  • iyinchao/liquid-glass-studio (MIT): smin을 통한 모양 병합, 스넬 굴절, 무색 유리.

관련 스킬