# check out https://dash.plotly.com/ for documentation
# And check out https://py.cafe/maartenbreddels for more examples
from dash import Dash, Input, Output, callback, dcc, html, State
import dash_bootstrap_components as dbc
import plotly.express as px
import numpy as np
import pandas as pd
from PIL import Image
from io import BytesIO
# Create app object===================================================================
app = Dash(__name__, external_stylesheets=[dbc.themes.CERULEAN, dbc.icons.BOOTSTRAP, dbc.icons.FONT_AWESOME, "/assets/styles.css"])
# Get image from local file path
def get_pil_image(file_path):
return Image.open(file_path)
# Define the file path
file_path = 'assets/header_bg_image.png'
# Load the image
image = get_pil_image(file_path)
# Convert image to NumPy array
header_bg_img = np.array(image)
#Create components====================================================================
card = dbc.Card([
dbc.CardHeader(
dbc.Tabs([
dbc.Tab(label="Continuous Color Scales", tab_id="tab-1"),
dbc.Tab(label="Discrete Color Scales", tab_id="tab-2"),
dbc.Tab(label="Swatches", tab_id="tab-3"),
dbc.Tab(label="How to use and configure ", tab_id="tab-4")
], id="card-tabs", active_tab="tab-1")
),
dbc.CardBody([
html.P(id="card-content", className="card-text"),
]),
])
content_swatches = dbc.Accordion([
dbc.AccordionItem(
"This is the content of the first section",
title='sequential.swatches ',
item_id="item-1"),
dbc.AccordionItem(
"This is the content of the second section",
title='qualitative.swatches',
item_id="item-2"),
], start_collapsed=True)
tabs_2 = dbc.Tabs([
dbc.Tab(label="Sequential Color Scales", tab_id="tab-11"),
dbc.Tab(label="Discrete Color Scales", tab_id="tab-12"),
dbc.Tab(label="Swatches", tab_id="tab-13"),
dbc.Tab(label="How to use and configure ", tab_id="tab-14")
], id="tabs-2", active_tab="tab-11")
drdw = dbc.Row([
dbc.Col(dcc.Dropdown(id="dropdown-sequential", options=[], clearable=False, value='Magma'), width=3),
dbc.Col(dcc.Dropdown(id="dropdown-template", options=[], placeholder='Select a template...'), width=5 ),
dbc.Col(dbc.Button([html.I(className='fas fa-download mx-2'),
'Color Export Options',
], id='open', n_clicks=0, className='btn btn-primary w-100 py-1' )
, width=4),
])
#----------------------------
# Define the name of the color palette you want to use
palette_name = 'Plotly3'
# Construct the full name dynamically
full_palette_name = f'px.colors.sequential.{palette_name}'
colorscale = getattr(px.colors.sequential, palette_name)
acc_code = html.Div(
[dcc.Markdown(f'''
```python
import plotly.express as px
{full_palette_name}
```
''', id='md-code'),
dcc.Clipboard(id='copy-code', target_id='md-code'),
], className='d-flex')
acc_array = html.Div(
[dcc.Markdown(f'''
```python
{colorscale}
```
''', id='md-array'),
dcc.Clipboard(id='copy-array', target_id='md-array'),
], className='d-flex')
#---------------------------------------------------------------------
content_continuous = drdw, dbc.Row([
dbc.Col(dcc.Graph(), width=3),
dbc.Col([
dbc.Row([
dbc.Col(dcc.Graph(), width=5),
dbc.Col(dcc.Graph(), width=4)
], class_name='justify-content-between'),
dbc.Row(dbc.Accordion(
dbc.AccordionItem(['Choose your favorite way to export those colors.',
html.Hr(),
# html.H6('Array of string:'),
# acc_array,
html.H6('Python code'),
acc_code],
title='Color Export Options',
item_id="acc-names"), start_collapsed=True, className='custom-accordion')
),
], width=9),
])
header_card = dbc.Card([
dbc.CardImg(
src=file_path,
top=True,
style={"opacity": 0.9, 'height':'80px'}),
dbc.CardImgOverlay(
dbc.CardBody(html.H1("Interactive Plotly Express Color Scale Selection", className="text-center text-white"),
class_name='p-0'))
], class_name='mb-3')
# Modal Window for The Save Options-----------------------------------------------------------------------------
modal = html.Div([
dbc.Modal([
#dbc.ModalHeader(
# dbc.ModalTitle("Choose your favorite way to export those colors."),
# close_button=False),
dbc.ModalBody(["Choose your favorite way to export those colors.",
html.Hr(),
html.H6('Lists of CSS colors:'),
acc_array,]),
dbc.ModalFooter(
dbc.Button("Close", id="close", className="ms-auto", n_clicks=0)
),
],
id="modal",
is_open=False,
#keyboard=False,
backdrop='static',
style={
'position': 'fixed',
'left': '400px', # Position the modal to the left
'top': '200px', # Position the modal at the top
#'width': '50%', # Optional: set the width
#'height': '100%', # Optional: set the height
'overflow': 'auto', # Optional: enable scrolling if content overflows
}
),
])
# Create app layout======================================================================
app.layout = dbc.Container([
dbc.Row(
dbc.Col(header_card
#html.H3("Interactive Plotly Express color scale selection"
, #class_name='text-center m-3 p-3 border rounded'
),
),
dbc.Row(dbc.Col(card)),
html.Br(),
#dbc.Row(dbc.Col(tabs_2)),
html.Br(),
dbc.Row([
modal
]),
dbc.Row(
dbc.Col(
dbc.Card(id='color-names-card', children=[], body=True, class_name='my-3'
), width=9, class_name='offset-3'
)
),
dbc.Row([
dbc.Col([
dbc.Button([
'View All Sequential Color Scales Swatches',
html.I(className='bi bi-chevron-down', id='icon')],
id='collapse-button',
color='outline-primary',
class_name='mb-1 w-100 d-flex justify-content-between'),
dbc.Collapse(dbc.Card('test', body=True),
#dcc.Graph(id='color-swatches'),
id="collapse",
is_open=False)
], width=9, class_name='offset-3')
])
])
#===================================================================
@app.callback(
Output('collapse', 'is_open'),
Output("icon", "className"),
Input('collapse-button', 'n_clicks'),
State('collapse', 'is_open')
)
def toggle_collapse(n_clicks, is_open):
if n_clicks:
return not is_open, "bi bi-chevron-up" if not is_open else "bi bi-chevron-down"
return is_open, "bi bi-chevron-down"
@app.callback(
Output('color-swatches', 'figure'),
[Input('collapse-button', 'n_clicks')]
)
def display_swatches(n_clicks):
# Generate the swatches figure
fig = px.colors.sequential.swatches()
return fig
@app.callback(
Output("modal", "is_open"),
[Input("open", "n_clicks"), Input("close", "n_clicks")],
[State("modal", "is_open")],
prevent_initial_call=True
)
def toggle_modal(n1, n2, is_open):
if n1 or n2:
return not is_open
return is_open
@app.callback(
Output("card-content", "children"), [Input("card-tabs", "active_tab")]
)
def tab_content(active_tab):
if active_tab == 'tab-1':
return content_continuous
if active_tab == 'tab-3':
return content_swatches
return f"This is tab {active_tab}"
if __name__ == "__main__":
app.run_server(debug=True)