2. Components and props¶
A page can be broken into reusable Component classes. Let’s show some
guestbook entries, each in its own card:
"""Tutorial step 2: a component with props."""
from dataclasses import dataclass
from rational import App, Card, Column, Component, Container, Heading, Page, Text
app = App(title="Guestbook")
@dataclass(frozen=True)
class Entry:
name: str
message: str
ENTRIES = [
Entry("Ada", "What a lovely place!"),
Entry("Grace", "Signed, sealed, compiled."),
]
class EntryCard(Component):
entry: Entry # an annotated class attribute is a prop: EntryCard(entry=...)
def render(self):
return Card(
Text(self.entry.message),
Text(f"— {self.entry.name}", muted=True, size="sm"),
)
@app.page("/")
class Home(Page):
title = "Guestbook"
def render(self):
return Container(
Heading("Guestbook", level=1),
Column(*[EntryCard(entry=entry, key=i) for i, entry in enumerate(ENTRIES)]),
max_width=640,
)
if __name__ == "__main__":
app.run()
Props¶
Annotated class attributes are props, the inputs of a component. entry: Entry makes
EntryCard(entry=...) required; a default value (excited: bool = False) makes a prop
optional. A misspelled or missing prop is an error when the component is created, not a
silent bug.
Keys¶
key= gives each card a stable identity among its siblings. It doesn’t matter yet, but
it will in the next step, once the cards have state of their own. When you render a list,
always pass a key.
Primitives you will use most¶
Text:
Heading,Text,Link,BadgeLayout:
Container,Row,Column,Grid,CardForms:
Form,Input,Textarea,Select,Checkbox,Button
They are listed in the API reference. For anything else, h("tag", ...) builds any element.
Next: 3. State, events and forms.