Ludic Logo
Edit

Components and Styling

Here is a couple of examples how to write Ludic components, how to add custom HTML classes and register CSS properties.

#

A simple component simulating a link. The component only accepts one string child and a to attribute.

from typing import override

from ludic.attrs import Attrs
from ludic.components import Component
from ludic.html import a

class LinkAttrs(Attrs):
    to: str

class Link(Component[str, LinkAttrs]):
    classes = ["link"]

    @override
    def render(self) -> a:
        return a(
            *self.children,
            href=self.attrs["to"],
            style={"color": self.theme.colors.warning},
        )
#

A simple component which renders a navigation bar with a logo and a couple of links aligned to the right. This is what it looks like:

And here is the code for this example:

from typing import override

from ludic.attrs import NoAttrs
from ludic.catalog.buttons import ButtonLink
from ludic.catalog.layouts import Box, Cluster
from ludic.components import Component
from ludic.types import NoChildren

class Navigation(Component[NoChildren, NoAttrs]):
    classes = ["sample-navigation"]

    @override
    def render(self) -> Box:
        return Box(
            Cluster(
                ButtonLink("Logo"),
                Cluster(
                    ButtonLink("Item 1", to="..."),
                    ButtonLink("Item 2", to="..."),
                    ButtonLink("Item 3", to="..."),
                    ButtonLink("Item 4", to="...", classes=["success"]),
                ),
                classes=["justify-space-between"],
            ),
            classes=["invert"],
        )

Note that you need to use this navigation in the context of the HtmlPage component, otherwise there won't be the necessary CSS loaded. Or you can define your own styles for the component.

#

A simple component rendering a search bar with custom styling. Here is what it looks like:

And here is the code for this example:

from typing import override

from ludic.attrs import GlobalAttrs
from ludic.catalog.forms import InputField
from ludic.html import style
from ludic.components import Component
from ludic.types import NoChildren

class SearchBar(Component[NoChildren, GlobalAttrs]):
    classes = ["search-bar"]
    styles = style.use(
        lambda theme: {
            ".search-bar": {
                "input": {
                    "background-color": theme.colors.light.lighten(1),
                    "border": f"1px solid {theme.colors.light.darken(5)}",
                    "color": theme.colors.dark,
                },
                "input::placeholder": {
                    "color": theme.colors.dark.lighten(7),
                },
                "input:focus": {
                    "border-color": theme.colors.dark.lighten(5),
                    "outline": "none",
                },
            },
        }
    )

    @override
    def render(self) -> InputField:
        return InputField(
            type="search",
            placeholder="Custom search bar",
            **self.attrs,
        )
Made with Ludic and HTMX and 🐍 • DiscordGitHub