Border Healing
When border elements for certain border types are adjacent to each other and appear as if they should "join up", but don't because they belong to different elements, they will be joined up.
container_style = fill(1) | align_self_stretch | border_collapse
box_style = fill(1) | align_self_stretch | center_children
def box(s: str) -> Div:
return Div(
style=box_style | border | border_double,
children=(
Text(
style=text_justify_center | text_color("cyan", 500),
content=s,
),
),
)
@component
def root() -> Div:
def on_input(event: InputEvent, _: Receiver) -> AnyControl | None:
match event:
case KeyPressed(key=Key.Space):
return ToggleBorderHealing()
case _:
return None
return Div(
style=row | container_style,
on_input=on_input,
children=(
Div(
style=col | container_style,
children=(box("A1"), box("A2")),
),
Div(
style=col | container_style,
children=(
Div(style=row | container_style, children=(box("B1"), box("B2"))),
Div(style=row | container_style, children=(box("C1"), box("C2"), box("C3"), box("C4"))),
Div(style=row | container_style, children=(box("D1"), box("D2"), box("D3"))),
),
),
),
)
With border healing enabled:
╔═════════════════════════════╦═════════════╦══════════════╗
║ ║ ║ ║
║ ║ ║ ║
║ ║ B1 ║ B2 ║
║ ║ ║ ║
║ A1 ║ ║ ║
║ ╠══════╦══════╬═══════╦══════╣
║ ║ ║ ║ ║ ║
║ ║ ║ ║ ║ ║
║ ║ ║ ║ ║ ║
╠═════════════════════════════╣ C1 ║ C2 ║ C3 ║ C4 ║
║ ║ ║ ║ ║ ║
║ ║ ║ ║ ║ ║
║ ╠══════╩═╦════╩════╦══╩══════╣
║ A2 ║ ║ ║ ║
║ ║ ║ ║ ║
║ ║ D1 ║ D2 ║ D3 ║
║ ║ ║ ║ ║
║ ║ ║ ║ ║
╚═════════════════════════════╩════════╩═════════╩═════════╝
With border healing disabled:
╔═════════════════════════════╔═════════════╔══════════════╗
║ ║ ║ ║
║ ║ ║ ║
║ ║ B1 ║ B2 ║
║ ║ ║ ║
║ A1 ║ ║ ║
║ ╔══════╔══════╔═══════╔══════╗
║ ║ ║ ║ ║ ║
║ ║ ║ ║ ║ ║
║ ║ ║ ║ ║ ║
╔═════════════════════════════║ C1 ║ C2 ║ C3 ║ C4 ║
║ ║ ║ ║ ║ ║
║ ║ ║ ║ ║ ║
║ ╔════════╔═════════╔═════════╗
║ A2 ║ ║ ║ ║
║ ║ ║ ║ ║
║ ║ D1 ║ D2 ║ D3 ║
║ ║ ║ ║ ║
║ ║ ║ ║ ║
╚═════════════════════════════╚════════╚═════════╚═════════╝
Healing and clipping
A box that hides its overflow cuts off the borders inside it at its padding box, and the part that's cut off doesn't join anything. Here each container holds a box pushed up onto its top border. Where overflow is visible, the box's top corners are drawn on the container's border and join it; where it's hidden, they're clipped away, and the container's border stays straight:
@component
def clipped() -> Div:
return Div(
style=row | gap(2),
children=tuple(
Div(
style=border | border_light | size(16, 5) | overflow,
children=(
Div(
style=position_absolute | inset_top(-1) | inset_left(2) | size(11, 3) | border | border_light,
children=(Text(content=f" {name}"),),
),
),
)
for name, overflow in (("visible", overflow_visible), ("hidden", overflow_hidden))
),
)
A box whose border sits just inside its container's border doesn't join it either,
since the container's ─ and │ beside the box's corners don't point toward them.
Boxes that clip still join each other where their borders meet.
Every box in the grid above is a fill(1) item, which hides its overflow,
and each box's corners are inside its own clip, so they join across the shared edges.
Healing across z
Healing doesn't compare z or border styles,
so a raised box whose border lies on another box's border joins it as any border would:
@component
def raised() -> Div:
return Div(
style=col,
children=(
Div(style=border | border_light | size(24, 3), children=(Text(content="A panel"),)),
Text(
content="A raised box",
style=z(1) | position_absolute | inset_top(2) | inset_left(4) | border | border_light,
),
),
)
With border healing disabled, the raised box's corners are drawn over the panel's border as they are:
An unclipped box, such as a dropdown, joins borders beneath it the same way.
To keep a raised box from joining, keep its border off other borders.
#74 tracks whether healing should require matching z and styles.