Effect modifiers add visual effects and transformations to views, including shadows, borders, blend modes, scaling, offsets, and animations.
import nib
nib.VStack(
controls=[nib.Text("Card")],
shadow_color="black",
shadow_radius=10,
shadow_y=4,
border_color="#CCCCCC",
border_width=1,
animation=nib.Animation.spring(),
)
Shadow¶
Drop shadows are controlled by four parameters that work together. At least one shadow parameter must be set for the shadow to render.
shadow_color¶
The color of the drop shadow.
| Type | Default |
|---|---|
Color \| str |
None |
shadow_radius¶
The blur radius of the shadow in points. Larger values produce softer shadows.
| Type | Default (when shadow is active) |
|---|---|
float |
4.0 |
shadow_x¶
Horizontal offset of the shadow in points. Positive values shift the shadow right.
| Type | Default (when shadow is active) |
|---|---|
float |
0.0 |
shadow_y¶
Vertical offset of the shadow in points. Positive values shift the shadow down.
| Type | Default (when shadow is active) |
|---|---|
float |
2.0 |
# Basic shadow
nib.Rectangle(fill="white", shadow_color="black", shadow_radius=8)
# Customized shadow
nib.VStack(
controls=[nib.Text("Elevated Card")],
padding=16,
background="#FFFFFF",
corner_radius=12,
shadow_color="black",
shadow_radius=12,
shadow_x=0,
shadow_y=6,
)
# Shadow with only radius (no color)
nib.Rectangle(fill="white", shadow_radius=4)
Border¶
Border modifiers draw an outline around a view's bounds. Unlike stroke (which is for shapes), borders work on any view type.
border_color¶
The color of the border. Required for the border to render.
| Type | Default |
|---|---|
Color \| str |
None |
border_width¶
The width of the border in points.
| Type | Default (when border_color is set) |
|---|---|
float |
1.0 |
# Default 1pt border
nib.Rectangle(fill="white", border_color="#CCCCCC")
# Custom border width
nib.VStack(
controls=[nib.Text("Bordered content")],
padding=12,
border_color=nib.Color.RED,
border_width=2,
corner_radius=8,
)
Note: border_width without border_color has no effect.
blend_mode¶
Controls how a view is composited with the content behind it. See BlendMode for all available modes.
| Type | Default |
|---|---|
BlendMode \| str |
None |
nib.Rectangle(fill=nib.Color.BLUE, blend_mode=nib.BlendMode.MULTIPLY)
nib.Image(source="overlay.png", blend_mode="screen")
scale¶
Applies a uniform scale transformation to a view. The view is scaled from its center point. A value of 1.0 is the original size.
| Type | Default |
|---|---|
float |
None |
nib.Image(system_name="star.fill", scale=2.0) # Double size
nib.Text("Small", scale=0.75) # 75% size
offset¶
Shifts a view from its natural position. The view still occupies its original space in the layout. See Offset for constructor details.
| Type | Default |
|---|---|
Offset |
None |
nib.Circle(
fill=nib.Color.BLUE,
width=50,
height=50,
offset=nib.Offset(10, -5),
)
Animation¶
animation¶
Configures how property changes on this view are animated. Once set, the animation is "sticky" -- all future property mutations on the view animate using this configuration. See Animation for factory methods and presets.
| Type | Default |
|---|---|
Animation |
None |
# Spring animation on all property changes
counter = nib.Text("0", animation=nib.Animation.spring())
def increment():
counter.content = str(int(counter.content) + 1) # Animates automatically
# Ease-in-out opacity toggle
box = nib.Rectangle(
fill="blue",
width=100,
height=100,
animation=nib.Animation.easeInOut(0.3),
)
content_transition¶
Controls how a view's content animates when it changes. This is separate from view transitions -- it affects the content within a view that remains visible. See ContentTransition for all values.
| Type | Default |
|---|---|
ContentTransition \| str |
None |
# Rolling numeric digits
counter = nib.Text(
"0",
content_transition=nib.ContentTransition.NUMERIC_TEXT,
animation=nib.Animation.spring(),
)
# Fading content swap
label = nib.Text("Status", content_transition=nib.ContentTransition.OPACITY)
transition¶
Controls how a view animates when it appears in or disappears from the view hierarchy. See Transition for all values, asymmetric transitions, and custom keyframes.
| Type | Default |
|---|---|
Transition \| str \| TransitionConfig |
None |
# Simple fade
panel = nib.VStack(controls=[...], transition=nib.Transition.OPACITY)
# Asymmetric: slide in, fade out
panel = nib.VStack(
controls=[...],
transition=nib.Transition.asymmetric(
insertion=nib.Transition.SLIDE,
removal=nib.Transition.OPACITY,
),
)
# Combined: fade and scale simultaneously
badge = nib.Text(
"New",
transition=nib.Transition.combined(nib.Transition.OPACITY, nib.Transition.SCALE),
)
Examples¶
Elevated card with shadow and border¶
import nib
def main(app: nib.App):
app.build(
nib.VStack(
controls=[
nib.Text("Notification", font=nib.Font.HEADLINE),
nib.Text(
"You have 3 new messages.",
foreground_color=nib.Color.SECONDARY,
),
],
spacing=6,
padding=16,
background="#FFFFFF",
corner_radius=12,
border_color="#E0E0E0",
border_width=1,
shadow_color="black",
shadow_radius=10,
shadow_y=4,
)
)
nib.run(main)
Animated counter with effects¶
import nib
def main(app: nib.App):
count = 0
label = nib.Text(
"0",
font=nib.Font.system(48, nib.FontWeight.BOLD),
content_transition=nib.ContentTransition.NUMERIC_TEXT,
animation=nib.Animation.spring(response=0.4, damping=0.6),
)
def increment():
nonlocal count
count += 1
label.content = str(count)
app.build(
nib.VStack(
controls=[
label,
nib.Button(
"Add",
action=increment,
style=nib.ButtonStyle.BORDERED_PROMINENT,
),
],
spacing=16,
padding=24,
)
)
nib.run(main)
Overlapping views with offset and blend¶
import nib
def main(app: nib.App):
app.build(
nib.ZStack(
controls=[
nib.Circle(fill=nib.Color.RED, width=100, height=100),
nib.Circle(
fill=nib.Color.BLUE,
width=100,
height=100,
offset=nib.Offset(40, 0),
blend_mode=nib.BlendMode.SCREEN,
),
],
padding=40,
)
)
nib.run(main)