بنقرة واحدة
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 ويثبّتها لك.
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.
استنادا إلى تصنيف SOC المهني
| 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.