Claude liquid glass
Skill zakisheriff/Claude-Liquid-Glass-Skill/claude-liquid-glass
Enforces native iOS 26+ Liquid Glass in all iOS UI — SwiftUI, UIKit, and React Native / Expo (expo-glass-effect + expo-router NativeTabs). Covers buttons, icons, navbars, tab bars, search bars, text inputs, sheets, cards, every interactive element. Two hard laws: (1) never hand-roll or custom-make Liquid Glass — always use the platform's native component (SwiftUI `.glassEffect`/ `.buttonStyle(.glass)`, or RN `GlassView`/`GlassContainer`/`NativeTabs`); never fake it with BlurView/ultraThinMaterial/opacity on iOS. (2) every touch fires a haptic. Use when writing, reviewing, or refactoring any iOS UI code (Swift or React Native/Expo), even if the user just says "make a button" or "add a nav bar" without mentioning liquid glass, haptics, or iOS 26. Trigger on SwiftUI views, buttons, NavigationStack/toolbar, TabView, .searchable, TextField, sheets; and on RN/Expo Pressable/TouchableOpacity, expo-router layouts, expo-glass-effect, expo-haptics, or any styling / press-feedback decision.From its SKILL.md
npx -y skills add zakisheriff/Claude-Liquid-Glass-Skill --skill claude-liquid-glassAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
14.4 KB, ~3.4k tokens by cl100k_base, as published. Nobody here has run it
Claude Liquid Glass Skill
Applies to both native Apple UI (SwiftUI/UIKit) and React Native / Expo apps targeting iOS 26+.
The Two Hard Laws
- Never custom-make Liquid Glass. Always render it with the platform's own native component. Do not hand-roll glass from
BlurView,.ultraThinMaterial, blur+opacity+border stacks, or gradients on iOS. If a native glass primitive exists for the job, you MUST use it and nothing else. - Every single touch fires a haptic. Every button, tab, toggle, card tap, chip, list row, and gesture triggers native haptic feedback. A tappable element with no haptic is a bug. (See Mandatory Haptics.)
Core Rule
This app uses only the OS's native Liquid Glass material system (shipped iOS 26, WWDC 2025). Every interactive surface — buttons, icons, nav bars, tab bars, search bars, text inputs, sheets, cards, toolbars — must use the real system APIs below. Never substitute:
- ❌ Manual "glassmorphism":
.background(.ultraThinMaterial)/Color.white.opacity(0.1)+ custom border/shadow, or RN<BlurView>used as glass on iOS - ❌ Flat, opaque, hard-edged controls with no material
- ❌ RN/RN-style press feedback (
.opacity(pressed ? 0.5 : 1), manualscaleEffect/Animatedon tap) instead of native glass button behavior - ❌ Custom
RoundedRectangle/Viewbackgrounds that don't match system concentricity - ❌ Reinventing blur/refraction by stacking
.blur()+.opacity()layers
If you catch yourself about to write any of the above, stop and reach for the native glass primitive for that platform instead.
Part A — Native SwiftUI / UIKit (iOS 26+)
Golden Rules (from Apple's HIG)
- Glass belongs to the navigation/control layer, floating above content — not the content itself. Don't apply glass to body text, list rows, or backgrounds behind bars.
- Recompiling with Xcode 26 already gives you most of this for free — standard
NavigationStack,.toolbar,TabView,.searchable, and sheets adopt Liquid Glass automatically. Only reach for manual.glassEffect()on custom controls. - Group related glass elements in a
GlassEffectContainerso they blend/morph as one shape instead of separate floating blobs. - Tint with meaning only — reserve tint for real semantic state (destructive, primary, selection), not decoration.
- Test with Reduce Transparency, Increase Contrast, and Reduce Motion on. If it breaks, it's decoration, not Liquid Glass.
Component → API Map (SwiftUI)
| Component | Native API | Notes |
|---|---|---|
| Standard button | .buttonStyle(.glass) | default for secondary/tertiary actions |
| Primary/CTA button | .buttonStyle(.glassProminent) | one per screen, ideally |
| Circular icon button | .buttonStyle(.glass or .glassProminent) + .buttonBorderShape(.circle) | preferred icon-button idiom — not a fixed frame + raw glassEffect |
| Custom shaped control | .glassEffect(.regular, in: shape) | e.g. .rect(cornerRadius:), .circle, Capsule() |
| Interactive glass (custom tappable) | .glassEffect(.regular.interactive()) | for custom surfaces that respond to touch |
| Tinted selectable glass (pills, segmented, status chips) | .glassEffect(.regular.tint(color).interactive(), in: shape) | tint the glass value itself, chained — different from a Button's .tint() modifier |
| Grouped floating controls (icon clusters, FABs) | GlassEffectContainer(spacing:) { ... } | blends + enables morphing |
| Morph between states | .glassEffectID(_:in:) inside a container + matched transition | smooth shape transform |
| Nav bar / toolbar | NavigationStack + .toolbar (automatic) | don't hand-roll a bar |
| Tab bar | TabView (automatic) | don't hand-roll a bar |
| Search bar | .searchable(text:) (preferred) | see note below |
| Text input | System TextField/SecureField, wrapped in .glassEffect(.regular, in:) capsule/rect when custom-framed | avoid flat bordered fields |
| Sheet / popover | System .sheet/.popover (automatic) | glass chrome applied by system |
Search bar nuance
Prefer .searchable(text:) — it adopts Liquid Glass automatically. A custom TextField wrapped in a real .glassEffect(.regular, in: RoundedRectangle(...)) is acceptable when you need inline placement, a controlled placeholder color, or custom trailing controls (this is the pattern in the Halal-It reference app's search + sign-in fields). What is never acceptable is a search field faked with .ultraThinMaterial/opacity instead of .glassEffect.
Quick Snippets (SwiftUI)
Tinted, selectable, interactive glass pill (the workhorse pattern for chips/segments):
Text(label)
.padding(.horizontal, 14).padding(.vertical, 8)
.glassEffect(.regular.tint(isOn ? Brand.greenSoft : .clear).interactive(), in: Capsule())
Circular icon button:
Button { HapticManager.shared.trigger(.lightImpact); action() } label: {
Image(systemName: "location.fill")
}
.buttonStyle(.glassProminent)
.buttonBorderShape(.circle)
.tint(Brand.green)
Grouped icon cluster (morphing):
GlassEffectContainer(spacing: 24) {
HStack(spacing: 24) {
Image(systemName: "scribble.variable").frame(width: 72, height: 72).glassEffect()
Image(systemName: "eraser.fill").frame(width: 72, height: 72).glassEffect()
}
}
Primary / secondary buttons:
Button("Confirm") { }.buttonStyle(.glassProminent)
Button("Cancel", role: .cancel) { }.buttonStyle(.glass)
Fallback / Availability (SwiftUI)
Only pre-iOS-26 targets get an .ultraThinMaterial fallback, and only inside an #available(iOS 26, *) branch. If the deployment target is iOS 26+, delete the fallback — keep no legacy styling.
Part B — React Native / Expo (iOS 26+)
React Native reaches the same native Liquid Glass, through native modules. You still never custom-make glass. On iOS you use the real native views; a custom BlurView dock is allowed only as a non-iOS (Android/Web) fallback, never as the iOS path.
Libraries (the only sanctioned glass on iOS)
| Need | Library / API | Notes |
|---|---|---|
| Tab bar / nav | NativeTabs from expo-router/unstable-native-tabs | real native Liquid Glass tab bar. blurEffect="systemChromeMaterial", SF Symbol icons via icon: { sf: '...' }, native haptics + scroll-to-top for free |
| Any custom glass surface | GlassView from expo-glass-effect | `glassEffectStyle="regular" |
| Grouped/merging glass | GlassContainer from expo-glass-effect | RN equivalent of GlassEffectContainer; pass spacing |
| Availability gate | isLiquidGlassAvailable() + isGlassEffectAPIAvailable() from expo-glass-effect | true only on iOS 26+ capable devices |
| SF Symbols | expo-symbols (SymbolView) | monochrome system symbols, not flat icon assets |
| Haptics | expo-haptics | see Mandatory Haptics |
Do not use expo-blur <BlurView> as glass on iOS. It is a fallback for platforms without native Liquid Glass only.
The required RN patterns (as used in the Akhi-AI mobile + Medhive Frontend reference apps)
1. Platform-split layouts — native on iOS, custom fallback elsewhere. Use Expo's platform file extensions so iOS gets the real native tab bar and other platforms get a custom dock:
app/(tabs)/_layout.ios.tsx → NativeTabs (native Liquid Glass) ✅ iOS
app/(tabs)/_layout.tsx → custom GlassmorphicTabBar (BlurView) — Android/Web ONLY
// _layout.ios.tsx
import { NativeTabs } from 'expo-router/unstable-native-tabs';
<NativeTabs blurEffect="systemChromeMaterial" tintColor={brand}>
<NativeTabs.Trigger name="history"
options={{ title: t('tabs.history'), icon: { sf: 'clock' }, selectedIcon: { sf: 'clock.fill' } }} />
</NativeTabs>
2. Wrap GlassView once, gate on availability + Reduce Transparency, fall back to a plain View. Never render fake glass when native glass is unavailable — degrade to a normal opaque view:
// LiquidGlassSurface.tsx (thin wrapper over expo-glass-effect)
const liquidGlassEnabled = useLiquidGlassEnabled(); // canUseLiquidGlass() && !reduceTransparency
if (!liquidGlassEnabled) return <View style={style}>{children}</View>;
return (
<GlassView glassEffectStyle={glassStyle} isInteractive={interactive} tintColor={tintColor} style={style}>
{children}
</GlassView>
);
// availability + accessibility gate
export function canUseLiquidGlass() {
if (Platform.OS !== 'ios') return false;
try { return isLiquidGlassAvailable() && isGlassEffectAPIAvailable(); } catch { return false; }
}
// useLiquidGlassEnabled() additionally subscribes to reduceTransparencyChanged and returns false when on
3. Group with GlassContainer (RN's GlassEffectContainer):
<GlassContainer spacing={14} style={style}>{children}</GlassContainer>
4. glassStyle/glassEffectStyle: "regular" for cards/panels/modals, "clear" for control-like chrome (buttons, pills, segmented controls). Pass tintColor (rgba) only for semantic state/selection, matching the SwiftUI tint rule.
RN mapping cheat-sheet (SwiftUI → RN)
| SwiftUI | React Native / Expo |
|---|---|
.glassEffect(.regular, in:) | <GlassView glassEffectStyle="regular"> |
.glassEffect(.clear, ...) | <GlassView glassEffectStyle="clear"> |
.glassEffect(.regular.interactive()) | <GlassView isInteractive> |
.glassEffect(.regular.tint(c)....) | <GlassView tintColor="rgba(...)"> |
GlassEffectContainer(spacing:) | <GlassContainer spacing={n}> |
TabView (auto glass) | NativeTabs (expo-router/unstable-native-tabs) |
#available(iOS 26,*) fallback | useLiquidGlassEnabled() → plain <View> |
Mandatory Haptics
Every touch must produce a haptic. This is non-negotiable and applies to both platforms. Buttons, tabs, chips, toggles, card taps, list rows, long-press, swipe actions, pull-to-refresh commit, sheet dismiss — all of them.
Intensity guide (both platforms):
- Light impact — most taps, secondary buttons, chips, list rows
- Medium impact — primary/CTA actions, tab switches, meaningful toggles
- Heavy / rigid — significant or destructive confirmations
- Selection — picker/segment scrubbing, incremental selection changes
- Success / warning / error notification — operation results (save done, validation fail)
React Native / Expo
Use expo-haptics through a shared useHaptics() hook and call it in every onPress/gesture handler:
// hooks/useHaptics.ts
import * as Haptics from 'expo-haptics';
export const useHaptics = () => ({
light: () => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light),
medium: () => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium),
heavy: () => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy),
selection: () => Haptics.selectionAsync(),
success: () => Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success),
warning: () => Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning),
error: () => Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error),
});
const { light, success } = useHaptics();
<Pressable onPress={() => { light(); onPress(); }} />
// notifications on outcomes: success() after a completed action, error() on failure
NativeTabsfires native tab haptics automatically — don't double-fire on tab changes.
SwiftUI / UIKit
Prefer a central manager + a .hapticTap() view modifier (as in the Halal-It reference app), or SwiftUI's .sensoryFeedback:
Button { HapticManager.shared.trigger(.lightImpact); action() } label: { ... }
// or attach to any tappable view:
someCard.hapticTap(.selection)
// or native modifier:
.sensoryFeedback(.impact(weight: .light), trigger: isPressed)
Review Checklist (auditing existing code)
Liquid Glass:
- Any
.ultraThinMaterial/opacity "glass" on iOS (SwiftUI or RN<BlurView>) outside a documented non-iOS/pre-26 fallback → replace with the native glass primitive - Any hand-rolled nav/tab/search bar →
NavigationStack/TabView/.searchable(SwiftUI) orNativeTabs(RN) - RN app rendering glass on iOS via anything other than
expo-glass-effect/NativeTabs→ replace - RN glass not gated by availability + Reduce Transparency (no plain-
Viewfallback) → add the gate - Manual
scaleEffect/opacity/Animatedpress hack instead of native glass button behavior → replace - Adjacent glass elements not grouped →
GlassEffectContainer/GlassContainer - Circular icon buttons (SwiftUI) not using
.buttonBorderShape(.circle)→ fix - Decorative-only tint on glass → remove or justify semantically
Haptics:
- Any tappable element with no haptic → add one (light default; medium for primary; selection for scrubbing; success/error for outcomes)
- Haptics scattered inline instead of via a shared
useHaptics()/HapticManager→ centralize - Double-firing haptics on
NativeTabstab changes (native already fires) → remove the manual one
Accessibility:
- Tested with Reduce Transparency / Increase Contrast / Reduce Motion → still legible; RN falls back to plain views
Resources
references/liquid-glass-reference.md— deeper snippets (concentricity, custom shapes, glassEffectID morphing, sheets, toolbar nuance, point-release quirks) and links to Apple's WWDC 2025 sessions (219, 323) + HIG "Materials".
What ships with it: 1 file
7.1 KB alongside SKILL.md