Hello to everyone !
I run dash on a jupyter notebook google chrome windows 11 set up. The idea is to talk to a chatbot and when the user says a word like “!col” a second col appears on the screen next to the chatbot, aligned on the same row.
The issue is that the width is always 50-50 even if I specified width = 20%
Here I can provided you a minimal example.
import dash
import dash_bootstrap_components as dbc
from dash import html, dcc, Input, Output, State, callback
def get_app_background_style():
"""
"""
# Set a unified background for the whole app or container.
BACKGROUND_COLOR = '#FAFAFA' # '#f8f9fa'
# 'height': f'{height}vh', 'display': 'flex', 'flexDirection': 'row'
app_background_style = {
'backgroundColor': BACKGROUND_COLOR, # Example background color, should be changed based on your design
'height': '100vh', # 100% of the viewport height
'padding': '20px',
'width': '100vw'
}
return app_background_style
def get_second_col_style():
"""
"""
return {
'padding': '10px',
'display': 'none', # Initially hidden
'marginLeft': '5px',
'marginRight': '7px',
'verticalAlign': 'top',
'width': "0%", # Define width only when the column is shown
}
def get_chatbot_column_style():
"""
"""
return {
'padding': '7px',
'marginLeft': '7px',
'marginRight': '7px',
'width': '100%', # Default width
'display': 'inline-block',
'verticalAlign': 'top',
}
def get_row_style():
# Use flex properties on the container of the columns to align them at the top.
return {
'display': 'flex',
'flexWrap': 'nowrap', # Prevents wrapping of columns
'alignItems': 'flex-start' # Align children to the start of the cross axis
}
# Initialize the Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
def get_app_layout_fake(CHAT_LAYOUT, MENU_LAYOUT):
chatbot_column_style = get_chatbot_column_style()
second_col_style = get_second_col_style()
row_style = get_row_style()
app_background_style = get_app_background_style()
header = html.Div() # Define your header here
APP_LAYOUT = html.Div([
header,
dbc.Row([
dbc.Col(id='chatbot_column', children=[CHAT_LAYOUT], style=chatbot_column_style),
dbc.Col(id='menu_column', children=[MENU_LAYOUT], style= second_col_style),
], style=row_style),
dbc.Row([
html.Div(id='profile-recipe-div'),
], className='h-100', style={'marginTop': '20px', 'marginBottom': '20px'}),
dcc.Store(id='profile-store'),
], style=app_background_style)
return APP_LAYOUT
# Chatbot Layout
CHAT_LAYOUT_FAKE = html.Div([
dbc.Textarea(id="chat-area", className="mb-3", style={"width": "100%", "height": "300px"}),
dbc.Input(id="chat-input", placeholder="Type a message...", type="text"),
dbc.Button("Send", id="send-button", n_clicks=0, className="ms-2"),
html.Div(id="chat-output")
])
# Menu Layout (Placeholder for your menu content)
MENU_LAYOUT_FAKE = html.Div([html.H3("Menu Area"), html.P("Menu content goes here...")])
app.layout = get_app_layout_fake(CHAT_LAYOUT_FAKE, MENU_LAYOUT_FAKE)
# Callback to update the chat and possibly show the second column
@app.callback(
[Output("chat-output", "children"),
Output("menu_column", "style")],
[Input("send-button", "n_clicks")],
[State("chat-input", "value"),
State("menu_column", "style")]
)
def update_output(n_clicks, value, style):
if n_clicks > 0:
# Check if the user typed "!col"
if value == "!col":
# Update style to show the second column
style["display"] = "inline-block"
style["width"] = "20%" # Adjust width as needed
return "Showing menu...", style
else:
return f"You said: {value}", style
return "", style
# Callback for the chatbot (This is a placeholder for the actual logic)
@app.callback(
Output("chat-area", "value"),
Input("send-button", "n_clicks"),
State("chat-input", "value"),
State("chat-area", "value")
)
def update_chat(n_clicks, user_input, chat_history):
if n_clicks > 0:
new_message = f"User: {user_input}\nChatbot: (Your response logic here)\n"
return chat_history + new_message if chat_history else new_message
return chat_history
# Run the app
if __name__ == '__main__':
app.run_server("localhost", 560, debug=True)
Thank you for your help !