Source code for duck.html.components.card
"""
Card component module.
"""
from duck.html.components.theme import Theme
from duck.html.components.container import FlexContainer
from duck.html.components.style import Style
[docs]
class Card(FlexContainer):
"""
Basic card component derived from flex container.
Renders a centered, vertically-stacked card with a soft shadow and a
subtle hover lift, suited for feature tiles, stat blocks, and similar
content that needs equal visual weight.
Args:
bg_color (str): Optional card background override.
border_color (str): Optional card border color override.
"""
[docs]
def on_create(self) -> None:
super().on_create()
# Base layout
self.id = self.kwargs.get("id", "card")
self.klass = "flex-card"
# Update style
self.style.update({
"min-height": "100px",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"text-align": "center",
})
# Surface styling
border_color = self.kwargs.get("border_color", "rgba(255, 255, 255, 0.08)")
self.style.update({
"padding": Theme.current.padding,
"border-radius": Theme.current.border_radius,
"background": self.kwargs.get("bg_color", "rgba(255, 255, 255, 0.03)"),
"border": f"1px solid {border_color}",
"box-shadow": "0 4px 12px rgba(0, 0, 0, 0.1)",
"--card-border-color": border_color,
})
# Hover transition
self.style.update({
"transition": "transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease",
})
# Scoped hover behaviour
self.add_child(self.build_style())
[docs]
def build_style(self) -> Style:
"""
Builds the card's scoped hover styling.
Reads the per-instance border color from the `--card-border-color`
custom property set alongside the base styling, so multiple cards
with different border colors don't stomp on each other's hover rule.
Returns:
A Style component containing the card's hover rule.
"""
return Style(
inner_html="""
.flex-card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
border-color: var(--card-border-color, rgba(255, 255, 255, 0.08));
}
"""
)