원클릭으로
glass-effects
Apple glass/translucency effect integration via NSVisualEffectView (macOS) and UIVisualEffectView (iOS)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Apple glass/translucency effect integration via NSVisualEffectView (macOS) and UIVisualEffectView (iOS)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Run the asset_pipeline convention linter (`scripts/lint_conventions.cr`) — Crystal-side runner that enforces Phase 10 Family 1 naming rules across src/, samples/, and spec/. Use before commit, in CI, or when reviewing a PR.
Build cross-platform apps with UI::App + UI::Screen + UI::Controller + UI::ActionDispatcher + UI::FormState — route declarations, native action dispatch, Amber web integration, and the static-site web target.
The developer-facing guide to building Apple UI (iOS 26, iPadOS 26, macOS 26) with asset_pipeline's UI::View system. Backed by the Apple HIG corpus and validated by macOS + iOS screenshots. Answers "I want to show X — what component, what args, what HIG says."
Complete catalog of Android Jetpack Compose and Material Design 3 components. Covers M3 Expressive (2025), gesture system, graphics/drawing, navigation patterns, theming, and mapping guidance for Crystal cross-platform UI integration via JNI.
Full Apple Human Interface Guidelines corpus packaged offline as searchable markdown. Covers iOS, iPadOS, and macOS guidance for every HIG page, with cross-referenced links, downloaded illustrations, and a tag index. Use as the authoritative design reference when building native UI with asset_pipeline.
Comprehensive cross-platform UI component mapping matrix showing how every common UI pattern maps across Crystal UI::View, SwiftUI, UIKit, AppKit, Jetpack Compose, Android Views, and Web HTML/CSS. Implementation priority guide for expanding the asset_pipeline cross-platform component system.
| name | glass-effects |
| description | Apple glass/translucency effect integration via NSVisualEffectView (macOS) and UIVisualEffectView (iOS) |
| version | 1.0 |
This skill covers how to use Apple's vibrancy/translucency glass effects from Crystal via the ObjC runtime bridge. Glass effects allow UI to blur and tint the content behind a window or behind another view, creating the frosted-glass appearance used throughout macOS and iOS.
NSVisualEffectView is the macOS class for glass/translucency effects. It blurs and tints content behind the view or behind the window.
| Property | Selector | Type | Description |
|---|---|---|---|
| Material | setMaterial: | NSInteger | What the effect looks like (color/tint) |
| Blending Mode | setBlendingMode: | NSInteger | What gets blurred (window background or view behind) |
| State | setState: | NSInteger | When the effect is active |
| Value | Name | Appearance |
|---|---|---|
| 0 | NSVisualEffectMaterialAppearanceBased | Matches app appearance (deprecated) |
| 1 | NSVisualEffectMaterialLight | Light translucent (deprecated, use Titlebar) |
| 2 | NSVisualEffectMaterialDark | Dark translucent (deprecated, use HUDWindow) |
| 3 | NSVisualEffectMaterialTitlebar | Window title bar appearance |
| 4 | NSVisualEffectMaterialSelection | Selected content appearance |
| 5 | NSVisualEffectMaterialMenu | Menu background |
| 6 | NSVisualEffectMaterialPopover | Popover background |
| 7 | NSVisualEffectMaterialSidebar | Sidebar background |
| 8 | NSVisualEffectMaterialHeaderView | Header view background |
| 9 | NSVisualEffectMaterialSheet | Sheet background |
| 10 | NSVisualEffectMaterialWindowBackground | Standard window background |
| 11 | NSVisualEffectMaterialHUDWindow | HUD window (heads-up display) |
| 12 | NSVisualEffectMaterialFullScreenUI | Full screen UI background |
| 13 | NSVisualEffectMaterialToolTip | Tooltip background |
| 14 | NSVisualEffectMaterialContentBackground | Content area background |
| 15 | NSVisualEffectMaterialUnderWindowBackground | Under-window background |
| 16 | NSVisualEffectMaterialUnderPageBackground | Under-page background |
| Value | Name | Description |
|---|---|---|
| 0 | BehindWindow | Blurs content behind the window (desktop, other windows) |
| 1 | WithinWindow | Blurs content behind this view within the same window |
| Value | Name | Description |
|---|---|---|
| 0 | FollowsWindowActiveState | Effect active only when window is key/main |
| 1 | Active | Effect always active, even when window is not focused |
| 2 | Inactive | Effect always inactive (appears opaque) |
# Create the visual effect view filling the content area
content_view = LibObjC.objc_send(window, sel("contentView"))
content_frame = LibObjC.objc_get_frame(content_view)
visual_effect = LibObjC.objc_send_rect(
alloc("NSVisualEffectView"), sel("initWithFrame:"), content_frame)
# Material: HUDWindow (dark translucent panel)
LibObjC.objc_send_long(visual_effect, sel("setMaterial:"), 11_i64)
# Blending: behind the window (blurs desktop and other windows)
LibObjC.objc_send_long(visual_effect, sel("setBlendingMode:"), 0_i64)
# State: always active (even when window loses focus)
LibObjC.objc_send_long(visual_effect, sel("setState:"), 1_i64)
# Fill entire content area on resize
# Width-sizable (2) | Height-sizable (16) = 18
LibObjC.objc_set_autoresize(visual_effect, 18_u64)
# Add as subview of the content view
LibObjC.objc_add_subview(content_view, visual_effect)
# Now add UI elements as children of the visual effect view
LibObjC.objc_add_subview(visual_effect, title_label)
LibObjC.objc_add_subview(visual_effect, button)
A common pattern for apps with a sidebar:
# Sidebar with sidebar material
sidebar = LibObjC.objc_send_rect(
alloc("NSVisualEffectView"), sel("initWithFrame:"),
LibObjC::CGRect.new(x: 0.0, y: 0.0, width: 240.0, height: 600.0))
LibObjC.objc_send_long(sidebar, sel("setMaterial:"), 7_i64) # Sidebar
LibObjC.objc_send_long(sidebar, sel("setBlendingMode:"), 0_i64)
LibObjC.objc_send_long(sidebar, sel("setState:"), 0_i64) # Follow window state
UIVisualEffectView is the iOS equivalent. It takes a UIVisualEffect object (either UIBlurEffect or UIVibrancyEffect) rather than individual material/blending/state properties.
| Value | Name | Appearance |
|---|---|---|
| 0 | UIBlurEffectStyleExtraLight | Extra light blur |
| 1 | UIBlurEffectStyleLight | Light blur |
| 2 | UIBlurEffectStyleDark | Dark blur |
| 3 | UIBlurEffectStyleRegular | Adapts to light/dark mode (iOS 10+) |
| 4 | UIBlurEffectStyleProminent | Adapts, more opaque than Regular (iOS 10+) |
| 10 | UIBlurEffectStyleSystemMaterial | System material (iOS 13+) |
| 11 | UIBlurEffectStyleSystemMaterialLight | System material, light |
| 12 | UIBlurEffectStyleSystemMaterialDark | System material, dark |
| 13 | UIBlurEffectStyleSystemThinMaterial | Thin system material |
| 14 | UIBlurEffectStyleSystemUltraThinMaterial | Ultra thin system material |
| 15 | UIBlurEffectStyleSystemThickMaterial | Thick system material |
| 16 | UIBlurEffectStyleSystemChromeMaterial | Chrome-style system material |
# Create a blur effect
blur_cls = LibObjC.objc_getClass("UIBlurEffect")
blur_effect = LibObjC.objc_send_long(
blur_cls.as(LibObjC::Id), sel("effectWithStyle:"), 3_i64) # Regular
# Create the visual effect view with the blur
visual_effect = LibObjC.objc_send_id(
alloc("UIVisualEffectView"), sel("initWithEffect:"), blur_effect)
# Set frame (or use Auto Layout)
LibObjC.objc_send_rect_void(visual_effect, sel("setFrame:"),
LibObjC::CGRect.new(x: 0.0, y: 0.0, width: 375.0, height: 667.0))
# Add UI elements to the contentView of the visual effect view
content_view = LibObjC.objc_send(visual_effect, sel("contentView"))
LibObjC.objc_add_subview(content_view, label)
For text and icons that should vibrate (change opacity/blend) with the glass:
# First create the blur effect
blur_effect = LibObjC.objc_send_long(
LibObjC.objc_getClass("UIBlurEffect").as(LibObjC::Id),
sel("effectWithStyle:"), 3_i64)
# Create vibrancy effect referencing the blur
vibrancy_cls = LibObjC.objc_getClass("UIVibrancyEffect")
vibrancy_effect = LibObjC.objc_send_id(
vibrancy_cls.as(LibObjC::Id),
sel("effectForBlurEffect:"), blur_effect)
# Create a secondary visual effect view for vibrant content
vibrant_view = LibObjC.objc_send_id(
alloc("UIVisualEffectView"), sel("initWithEffect:"), vibrancy_effect)
# Add vibrant content (labels, icons) to this view's contentView
vibrant_content = LibObjC.objc_send(vibrant_view, sel("contentView"))
LibObjC.objc_add_subview(vibrant_content, label)
# Add the vibrant view inside the blur view's contentView
blur_content = LibObjC.objc_send(blur_visual_effect_view, sel("contentView"))
LibObjC.objc_add_subview(blur_content, vibrant_view)
Glass effects involve selectors with multiple Float64 (CGFloat) arguments, which makes the ARM64 calling convention critical.
On ARM64, objc_msgSend is a raw assembly trampoline. It does not know the types of arguments. The caller must set up registers correctly:
x0 (self), x1 (_cmd), x2-x7 (method args)d0-d7 (independent register bank)d0-d3If you cast objc_msgSend to a function pointer with fewer double parameters than the actual ObjC method expects, the higher d registers contain garbage from prior computations. This produces random colors, invisible views (alpha = 0.0 or NaN), or crashes.
Every unique combination of (return type, parameter types) has a dedicated C wrapper function in objc_bridge.c. Key wrappers used for glass effects:
// Material, blending, state (all take NSInteger = long)
void* objc_send_long(void* self, SEL sel, long arg1);
// NSVisualEffectView initWithFrame: (CGRect = 4 doubles as HFA)
void* objc_send_rect(void* self, SEL sel, CGRect rect);
// Autoresize mask (NSUInteger = unsigned long)
void objc_set_autoresize(void* view, unsigned long mask);
// NSColor creation (4 doubles: r, g, b, a)
void* nscolor_rgba(double r, double g, double b, double a);
void* nscolor_white_alpha(double white, double alpha);
Never cast objc_msgSend directly in Crystal with a generic function pointer. Always go through the typed wrapper in objc_bridge.c. If a new ObjC method needs a combination of argument types not covered by existing wrappers, add a new wrapper function to the bridge.
| Wrapper | Signature | Use case |
|---|---|---|
objc_send_1d | (id, SEL, d0) | Single double arg (e.g., setAlphaValue:) |
objc_send_2d_ret_id | (id, SEL, d0, d1) -> id | Two doubles returning object |
objc_send_4d_ret_id | (id, SEL, d0, d1, d2, d3) -> id | Four doubles returning object (color creation) |
objc_send_rect | (id, SEL, CGRect) -> id | CGRect HFA argument (frame init) |
objc_send_rect_void | (id, SEL, CGRect) | CGRect HFA, no return (setFrame:) |
nscolor_rgba | (r, g, b, a) -> id | NSColor RGBA creation |
nscolor_srgba | (r, g, b, a) -> id | NSColor sRGB creation |
nscolor_white_alpha | (w, a) -> id | NSColor grayscale creation |
When glass effects are integrated into the cross-platform UI::View system, they would be handled at the renderer level rather than as a view type. For example, the AppKit::Renderer could apply glass effects to any view with a specific background configuration:
# Future API concept
stack = UI::VStack.new(spacing: 12.0)
stack.background = UI::GlassBackground.new(
material: :sidebar,
blending: :behind_window
)
The web renderer would map this to CSS backdrop-filter: blur(), the AppKit renderer to NSVisualEffectView, and the UIKit renderer to UIVisualEffectView.
A complete working macOS app with glass effects is at:
/Users/crimsonknight/open_source_coding_projects/crystal/samples/cross_platform/macos_app.cr
Build and run:
cd /Users/crimsonknight/open_source_coding_projects/crystal/samples/cross_platform
clang -c objc_bridge.c -o objc_bridge.o
bin/crystal build macos_app.cr --link-flags="objc_bridge.o" -o macos_app
./macos_app
This demo creates a window with NSVisualEffectMaterialHUDWindow (material 13), BehindWindow blending (0), and Active state (1), showing Crystal-generated labels and a button on top of the glass surface.