263 lines
7.0 KiB
Markdown
263 lines
7.0 KiB
Markdown
```python exec
|
|
import reflex as rx
|
|
from pcweb.pages.docs import components
|
|
from pcweb.pages.docs import styling
|
|
from pcweb.pages.docs import library
|
|
import docs.tutorial.tutorial_style as style
|
|
```
|
|
|
|
# Basic Frontend
|
|
|
|
Let's start with defining the frontend for our chat app. In Reflex, the frontend can be broken down into independent, reusable components. See the [components docs]({components.props.path}) for more information.
|
|
|
|
## Display A Question And Answer
|
|
|
|
We will modify the `index` function in `chatapp/chatapp.py` file to return a component that displays a single question and answer.
|
|
|
|
```python demo box
|
|
rx.fragment(
|
|
rx.box(
|
|
"What is Reflex?",
|
|
# The user's question is on the right.
|
|
text_align="right",
|
|
),
|
|
rx.box(
|
|
"A way to build web apps in pure Python!",
|
|
# The answer is on the left.
|
|
text_align="left",
|
|
),
|
|
)
|
|
```
|
|
|
|
```python
|
|
# chatapp.py
|
|
|
|
import reflex as rx
|
|
|
|
|
|
def index() -> rx.Component:
|
|
return rx.container(
|
|
rx.box(
|
|
"What is Reflex?",
|
|
# The user's question is on the right.
|
|
text_align="right",
|
|
),
|
|
rx.box(
|
|
"A way to build web apps in pure Python!",
|
|
# The answer is on the left.
|
|
text_align="left",
|
|
),
|
|
)
|
|
|
|
|
|
# Add state and page to the app.
|
|
app = rx.App()
|
|
app.add_page(index)
|
|
```
|
|
|
|
Components can be nested inside each other to create complex layouts. Here we create a parent container that contains two boxes for the question and answer.
|
|
|
|
We also add some basic styling to the components. Components take in keyword arguments, called [props]({components.style_props.path}), that modify the appearance and functionality of the component. We use the `text_align` prop to align the text to the left and right.
|
|
|
|
## Reusing Components
|
|
|
|
Now that we have a component that displays a single question and answer, we can reuse it to display multiple questions and answers. We will move the component to a separate function `question_answer` and call it from the `index` function.
|
|
|
|
```python exec
|
|
def qa(question: str, answer: str) -> rx.Component:
|
|
return rx.box(
|
|
rx.box(question, text_align="right"),
|
|
rx.box(answer, text_align="left"),
|
|
margin_y="1em",
|
|
)
|
|
|
|
|
|
qa_pairs = [
|
|
("What is Reflex?", "A way to build web apps in pure Python!"),
|
|
(
|
|
"What can I make with it?",
|
|
"Anything from a simple website to a complex web app!",
|
|
),
|
|
]
|
|
|
|
|
|
def chat() -> rx.Component:
|
|
qa_pairs = [
|
|
("What is Reflex?", "A way to build web apps in pure Python!"),
|
|
(
|
|
"What can I make with it?",
|
|
"Anything from a simple website to a complex web app!",
|
|
),
|
|
]
|
|
return rx.box(*[qa(question, answer) for question, answer in qa_pairs])
|
|
```
|
|
|
|
```python demo box
|
|
rx.container(chat())
|
|
```
|
|
|
|
```python
|
|
def qa(question: str, answer: str) -> rx.Component:
|
|
return rx.box(
|
|
rx.box(question, text_align="right"),
|
|
rx.box(answer, text_align="left"),
|
|
margin_y="1em",
|
|
)
|
|
|
|
|
|
def chat() -> rx.Component:
|
|
qa_pairs = [
|
|
("What is Reflex?", "A way to build web apps in pure Python!"),
|
|
("What can I make with it?", "Anything from a simple website to a complex web app!"),
|
|
]
|
|
return rx.box(*[qa(question, answer) for question, answer in qa_pairs])
|
|
|
|
|
|
def index() -> rx.Component:
|
|
return rx.container(chat())
|
|
```
|
|
|
|
## Chat Input
|
|
|
|
Now we want a way for the user to input a question. For this, we will use the [input]({library.chakra.forms.input.path}) component to have the user add text and a [button]({library.forms.button.path}) component to submit the question.
|
|
|
|
```python exec
|
|
def action_bar() -> rx.Component:
|
|
return rx.hstack(
|
|
rx.chakra.input(placeholder="Ask a question"),
|
|
rx.button("Ask"),
|
|
)
|
|
```
|
|
|
|
```python demo box
|
|
rx.container(
|
|
chat(),
|
|
action_bar(),
|
|
)
|
|
```
|
|
|
|
```python
|
|
def action_bar() -> rx.Component:
|
|
return rx.hstack(
|
|
rx.chakra.input(placeholder="Ask a question"),
|
|
rx.button("Ask"),
|
|
)
|
|
|
|
def index() -> rx.Component:
|
|
return rx.container(
|
|
chat(),
|
|
action_bar(),
|
|
)
|
|
```
|
|
|
|
## Styling
|
|
|
|
Let's add some styling to the app. More information on styling can be found in the [styling docs]({styling.overview.path}). To keep our code clean, we will move the styling to a separate file `chatapp/style.py`.
|
|
|
|
```python
|
|
# style.py
|
|
|
|
# Common styles for questions and answers.
|
|
shadow = "rgba(0, 0, 0, 0.15) 0px 2px 8px"
|
|
chat_margin = "20%"
|
|
message_style = dict(
|
|
padding="1em",
|
|
border_radius="5px",
|
|
margin_y="0.5em",
|
|
box_shadow=shadow,
|
|
max_width="30em",
|
|
display="inline-block",
|
|
)
|
|
|
|
# Set specific styles for questions and answers.
|
|
question_style = message_style | dict(margin_left=chat_margin)
|
|
answer_style = message_style | dict(margin_right=chat_margin)
|
|
|
|
# Styles for the action bar.
|
|
input_style = dict(
|
|
border_width="1px", padding="1em", box_shadow=shadow
|
|
)
|
|
button_style = dict(
|
|
background_color="#CEFFEE", box_shadow=shadow
|
|
)
|
|
```
|
|
|
|
We will import the styles in `chatapp.py` and use them in the components. At this point, the app should look like this:
|
|
|
|
```python exec
|
|
def qa4(question: str, answer: str) -> rx.Component:
|
|
return rx.box(
|
|
rx.box(rx.text(question, style=style.question_style), background_color="#F5EFFE", text_align="right"),
|
|
rx.box(rx.text(answer, style=style.answer_style), background_color="#DEEAFD", text_align="left"),
|
|
margin_y="1em",
|
|
width="100%",
|
|
)
|
|
|
|
|
|
def chat4() -> rx.Component:
|
|
qa_pairs = [
|
|
("What is Reflex?", "A way to build web apps in pure Python!"),
|
|
(
|
|
"What can I make with it?",
|
|
"Anything from a simple website to a complex web app!",
|
|
),
|
|
]
|
|
return rx.box(*[qa4(question, answer) for question, answer in qa_pairs])
|
|
|
|
|
|
def action_bar4() -> rx.Component:
|
|
return rx.hstack(
|
|
rx.chakra.input(placeholder="Ask a question", style=style.input_style),
|
|
rx.button("Ask", style=style.button_style),
|
|
)
|
|
```
|
|
|
|
```python demo box
|
|
rx.container(
|
|
chat4(),
|
|
action_bar4(),
|
|
)
|
|
```
|
|
|
|
```python
|
|
# chatapp.py
|
|
import reflex as rx
|
|
|
|
from chatapp import style
|
|
|
|
|
|
def qa(question: str, answer: str) -> rx.Component:
|
|
return rx.box(
|
|
rx.box(rx.text(question, style=style.question_style), text_align="right"),
|
|
rx.box(rx.text(answer, style=style.answer_style), text_align="left"),
|
|
margin_y="1em",
|
|
)
|
|
|
|
def chat() -> rx.Component:
|
|
qa_pairs = [
|
|
("What is Reflex?", "A way to build web apps in pure Python!"),
|
|
("What can I make with it?", "Anything from a simple website to a complex web app!"),
|
|
]
|
|
return rx.box(*[qa(question, answer) for question, answer in qa_pairs])
|
|
|
|
|
|
def action_bar() -> rx.Component:
|
|
return rx.hstack(
|
|
rx.chakra.input(placeholder="Ask a question", style=style.input_style),
|
|
rx.button("Ask", style=style.button_style),
|
|
)
|
|
|
|
|
|
def index() -> rx.Component:
|
|
return rx.container(
|
|
chat(),
|
|
action_bar(),
|
|
)
|
|
|
|
|
|
app = rx.App()
|
|
app.add_page(index)
|
|
```
|
|
|
|
The app is looking good, but it's not very useful yet! In the next section, we will add some functionality to the app.
|