widgetti / solara Goto Github PK
View Code? Open in Web Editor NEWA Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps
Home Page: https://solara.dev
License: MIT License
A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps
Home Page: https://solara.dev
License: MIT License
When I create a button, I don't think I should have to figure out how to center that button with css. I think
sl.Button(
"Save Answer",
on_click=save_answer,
center=True
)
or maybe
sl.Button(
"Save Answer",
on_click=save_answer,
align="center"/"left"/"right"
)
I have a fresh conda environment with python 3.9 on windows. I've used poetry to install solara.
I have a myapp.py
file with the following code:
import solara
@solara.component
def Page():
clicks, set_clicks = solara.use_state(0)
def increase_clicks():
set_clicks(clicks+1)
solara.Button(label=f"Clicked {clicks} times", on_click=increase_clicks)
And then run with:
solara run `myapp.py`
These are some of the errors in the console:
The stylesheet http://localhost:8765/_solara/cdn/[email protected]/css/font-awesome.min.css was not loaded because its MIME type, “text/plain”, is not “text/css”.
The script from “http://localhost:8765/_solara/cdn/[email protected]/dist/mermaid.min.js” was loaded even though its MIME type (“text/plain”) is not a valid JavaScript MIME type
The script from “http://localhost:8765/_solara/cdn/[email protected]/require.js” was loaded even though its MIME type (“text/plain”) is not a valid JavaScript MIME type.
The stylesheet http://localhost:8765/_solara/cdn/@widgetti/[email protected]/dist/main.css was not loaded because its MIME type, “text/plain”, is not “text/css”.
See https://github.com/widgetti/ipyvue/blob/master/setup.cfg#L7
(instead of per line ignores)
Step to reproduce:
git clone https://github.com/aiidalab/aiidalab-qe.git && cd aiidalab-qe
pip install .
The AttributeError is also see from running notebook directly where the app showing just fine, so I assume it can be ignore and not critically make it not working.
However, the web page keep on loading and in the terminal shows the exception:
Traceback (most recent call last):
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/solara/server/app.py", line 497, in load_app_widget
widget, render_context = _run_app(
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/solara/server/app.py", line 445, in _run_app
main_object = app_script.run()
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/solara/server/app.py", line 255, in run
return self._execute()
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/solara/server/app.py", line 143, in _execute
exec(ast, local_scope)
File "/home/jyu/Projects/WP-AiiDAlab/aiidalab-qe/qe.ipynb input cell 3", line 41, in <module>
File "/home/jyu/Projects/WP-AiiDAlab/aiidalab-qe/aiidalab_qe/steps.py", line 310, in __init__
self.workchain_settings = WorkChainSettings()
File "/home/jyu/Projects/WP-AiiDAlab/aiidalab-qe/aiidalab_qe/steps.py", line 132, in __init__
super().__init__(
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget_box.py", line 64, in __init__
super(Box, self).__init__(**kwargs)
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 480, in __init__
self.open()
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 493, in open
state, buffer_paths, buffers = _remove_buffers(self.get_state())
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 591, in get_state
value = to_json(getattr(self, k), self)
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 55, in _widget_to_json
return [_widget_to_json(v, obj) for v in x]
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 55, in <listcomp>
return [_widget_to_json(v, obj) for v in x]
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 57, in _widget_to_json
return "IPY_MODEL_" + x.model_id
File "/home/jyu/micromamba/envs/aiidalab-voila-00/lib/python3.9/site-packages/solara/server/patch.py", line 335, in model_id_debug
raise RuntimeError("Widget has no comm, you are probably using a widget that was closed. The widget is:\n" + repr(self))
RuntimeError: Widget has no comm, you are probably using a widget that was closed. The widget is:
HTML(value='<div style="padding-top: 0px; padding-bottom: 0px">\n <h4>Structure</h4></div>')
I have a fresh conda environment with python 3.9 on windows. I've used poetry to install solara.
When running the quickstart example:
import solara
@solara.component
def Page():
clicks, set_clicks = solara.use_state(0)
def increase_clicks():
set_clicks(clicks+1)
solara.Button(label=f"Clicked {clicks} times", on_click=increase_clicks)
I get the error:
Traceback (most recent call last):
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\reacton\core.py", line 1457, in _render
root_element = el.component.f(*el.args, **el.kwargs)
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\solara\autorouting.py", line 87, in RoutingProvider
path, set_path = solara.use_state(pathname, key="solara-context-path")
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\reacton\core.py", line 722, in use_state
return rc.use_state(initial, key, eq)
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\reacton\core.py", line 1093, in use_state
elif utils.isinstance_lazy(initial, "pandas.DataFrame"):
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\reacton\utils.py", line 86, in isinstance_lazy
types = [import_item(t) if isinstance(t, str) else t for t in types]
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\reacton\utils.py", line 86, in <listcomp>
types = [import_item(t) if isinstance(t, str) else t for t in types]
File "C:\Users\jhsmi\Miniconda3\envs\py39_solara\lib\site-packages\reacton\utils.py", line 79, in import_item
module = __import__(".".join(parts[:-1]), fromlist=[parts[-1]])
ModuleNotFoundError: No module named 'pandas'
While I would expect pandas to be either optional (for this example) or listed as requirement
This code used to work, but now it hangs forever
solara 1.10.0
plotly 5.9.0
code
import pandas as pd
import solara as sl
import plotly.express as px
@sl.component
def Page():
df = pd.read_csv("conv_intent.csv")
df["text_length"] = df.text.str.len()
df["id"] = list(range(len(df)))
df["hovertext"] = df.text.str.wrap(30).str.replace("\n", "<br>")
fig = px.scatter(
df,
x="x",
y="y",
custom_data=[df["id"]],
hover_data=["hovertext"],
)
fig.update_layout(showlegend=False)
fig.update_xaxes(visible=False)
fig.update_yaxes(visible=False)
fig.update_traces(marker_size=2)
sl.FigurePlotly(fig)
Page()
The code outside of a component (plotly only) works
I've attached the file below
conv_intent.csv
- [What it is?](#what-it-is?)
- [Example](#example)
- [Usage](#usage)
- [Deployment](#deployment)
- [Flask](#flask)
- [Starlette](#flask)
- [FastAPI](#flask)
- [Voila](#voila)
- [Panel](#panel)
- [Nginx](#nginx)
- [Installation](#installation)
- [Development](#development)
- [FAQ](#faq)
<div class="solara-markdown rendered_html jp-RenderedHTMLCommon">
<ul>
<li><a href="#what-it-is?">What it is?</a></li>
<li><a href="#example">Example</a></li>
<li><a href="#usage">Usage</a></li>
<li><a href="#deployment">Deployment</a></li>
<li><a href="#flask">Flask</a></li>
<li><a href="#flask">Starlette</a></li>
<li><a href="#flask">FastAPI</a></li>
<li><a href="#voila">Voila</a></li>
<li><a href="#panel">Panel</a></li>
<li><a href="#nginx">Nginx</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#development">Development</a></li>
<li><a href="#faq">FAQ</a></li>
</ul>
</div>
It should output a nested list. The issue exists for ordered list as well.
This online markdown converter can be used to see appropriate output https://markdowntohtml.com/
If you have a styled df = pandas.DataFrame().style
, you can pass it as sdf = solara.DataFrame(df.data)
but you loose the styling that was applied to df. So if columns were hidden by the styler, they are displayed again. It would be good for solara.DataFrame to reapply the style before when displaying sdf in a notebook for example.
Suppose I'm making a solara component with several inputs/widgets, with a corresponding State
class, and assuming the return of this component is a list of ints.
I would probably want to do something like this:
@dataclasses.dataclass
class State:
my_reactive_numbers = Reactive[List[int]]([])
And in my app create an instance of State
and pass to the component. This works fine, however if i create multiple pairs of the component/state there could be a problem because of the mutable default argument passed to Reactive
(the list), as shown here:
s1 = State()
s2 = State()
s1.my_reactive_numbers.value = [1,2,3]
s2.my_reactive_numbers.value
>>> [1,2,3]
For non-mutable defaults such as str
/int
/float
its not a problem.
A solution could be to instead to this:
class InitState():
def __init__(self):
self.my_reactive_numbers = Reactive([])
However, I would like to keep the possibility of using dataclasses. Perhaps Reactive
variables should either optionally accept a default_factory
kwarg (such as used for dataclasses; dataclasses.field(default_factory=list)
) or we should create a constructor which allows for passing of factory methods?
For example, in class Reactive
:
@classmethod
def from_factory(cls, factory: Callable[[], S]) -> "Reactive[S]":
return cls(factory())
Then you could define your State
class as:
@dataclasses.dataclass
class State:
my_reactive_numbers = Reactive[List[int]]([])
my_reactive_factory_numbers = Reactive[List[int]].from_factory(list)
s1 = State()
s2 = State()
s1.my_reactive_factory_numbers = [4,5,6]
s2.my_reactive_factory_numbers.value
>>> []
Hi guys,
I am not able to run my solara app in a docker container. Running the docker container results in the following error:
ERROR: [Errno 99] error while attempting to bind on address ('::1', 8765, 0, 0): cannot assign requested address
Here is what my Dockerfile looks like
#
# Build image
#
FROM python:3.11-slim as builder
ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1 \
POETRY_HOME=/opt/poetry
WORKDIR /app
COPY . .
RUN apt update -y && apt upgrade -y && apt install curl -y
RUN curl -sSL https://install.python-poetry.org | python3 -
RUN ${POETRY_HOME}/bin/poetry config virtualenvs.create false
RUN ${POETRY_HOME}/bin/poetry install --no-dev
RUN ${POETRY_HOME}/bin/poetry export -f requirements.txt >> requirements.txt
#
# Prod image
#
FROM python:3.11-slim AS runtime
WORKDIR /app
COPY . .
COPY --from=builder /app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8765
CMD ["solara", "run", "src/app.py"]
In the video I first show the fullscreen app from a Jupyter notebook, then in the other tab from my terminal running solara run app.py
but the styles don't match up at all
https://user-images.githubusercontent.com/22605641/231195256-a543b8d3-6a6a-4fae-a2a7-2dcfd2ecf992.mov
A client ran solara, but the firewall blocked access to the CDN. We should detect this, suggest fixing this by giving a link to the docs (that we need to write) and by suggesting running pip install "solara[assets]"
.
Hi guys,
thanks for this great lib. I´ve already used it some time in jupyter notebooks and running apps on my local machine. However, I am not able to access apps running on my VM (oracle cloud). All I see is a "solara" spinner and the message "Loading app". I think it´s problem with my firewall configuration. Which ports need to be open for running apps on a virtual machine?
Thanks,
legout
In jupyter version 7+, when you run a Solara app in the notebook, there's no option to go fullscreen anymore.
simple app
import solara as sl
@sl.component
def Page():
sl.Markdown("# Hi there!")
sl.Markdown("This is my page")
Page()
Jupyter versions
Selected Jupyter core packages...
IPython : 8.12.0
ipykernel : 6.22.0
ipywidgets : 8.0.6
jupyter_client : 8.2.0
jupyter_core : 5.3.0
jupyter_server : 2.5.0
jupyterlab : not installed
nbclient : 0.7.3
nbconvert : 7.3.1
nbformat : 5.8.0
notebook : 6.5.4
qtconsole : 5.4.2
traitlets : 5.9.0
Solara version: '1.10.0'
Hello,
i´ve tested duckdb with solara and found, that executing queries in a solara app is much slower (5-10x) than running the same query in a jupyter notebook.
Here is some code for reproduction:
import duckdb
import pandas as pd
import solara
import pyarrow.dataset as pds
from typing import cast, Optional
import os
import threading
from solara.alias import rv
import tempfile
import time
TEMP_PATH = tempfile.mkdtemp()
def download_dataset(name: str = "netflix_titles"):
df = pd.read_csv(
f"https://raw.githubusercontent.com/adamerose/datasets/master/{name}.csv"
)
pd.concat([df for i in range(3)]).to_parquet(
f"{TEMP_PATH}/{name}.parquet", index=False
)
def register_table(
con: duckdb.DuckDBPyConnection,
name: str,
path: str,
):
if not os.path.exists(path):
download_dataset(name)
if not con.sql("SHOW TABLES"):
ds = pds.dataset(path)
con.register(name, ds)
else:
if name not in con.sql("SHOW TABLES").df()["name"].tolist():
ds = pds.dataset(path)
con.register(name, ds)
ALL_DATASETS1 = [
"country_indicators",
"diamonds",
"gammas",
"gapminder",
"googleplaystore",
"googleplaystore_reviews",
"happiness",
"harry_potter_characters",
"iris",
"mpg",
]
ALL_DATASETS2 = [
"netflix_titles",
"penguins",
"planets",
"pokemon",
"seinfeld_episodes",
"seinfeld_scripts",
"stockdata",
"tips",
"titanic",
"trump_tweets",
"us_shooting_incidents",
]
DATASETS1 = solara.reactive([])
DATASETS2 = solara.reactive([])
DDB = duckdb.connect()
@solara.component
def Page():
query, set_query = solara.use_state(
"SELECT * FROM googleplaystore_reviews INNER JOIN googleplaystore ON googleplaystore_reviews.App=googleplaystore.App"
)
query_executed, set_query_executed = solara.use_state(cast(Optional[str], None))
ddb_cursor, set_ddb_cursor = solara.use_state(DDB.cursor())
registered_tables, set_registered_tables = solara.use_state([])
table_hints, set_table_hints = solara.use_state({})
def register_tables(cancel: threading.Event):
for name in DATASETS1.value:
register_table(
con=ddb_cursor,
path=f"{TEMP_PATH}/{name}.parquet",
name=name,
)
set_registered_tables(registered_tables + [name])
for name in DATASETS2.value:
register_table(
con=ddb_cursor,
path=f"{TEMP_PATH}/{name}.parquet",
name=name,
)
set_registered_tables(registered_tables + [name])
# table_names = ddb_cursor.sql("SHOW TABLES").pl()["name"]
if len(registered_tables):
table_hints_ = {
table_name: ddb_cursor.sql(f"FROM {table_name}").columns
for table_name in registered_tables
}
set_table_hints(table_hints_)
def run_query(cancel: threading.Event) -> pd.DataFrame:
if not query_executed:
return
df = ddb_cursor.sql(query_executed).df()
return df
result: solara.Result[pd.DataFrame] = solara.use_thread(
run_query, dependencies=[query_executed]
)
with solara.VBox() as main:
with solara.Card("Toggle to register the dataset."):
solara.ToggleButtonsMultiple(
DATASETS1, ALL_DATASETS1, on_value=register_tables
)
solara.ToggleButtonsMultiple(
DATASETS2, ALL_DATASETS2, on_value=register_tables
)
solara.SqlCode(
label="Query Editor",
query=query,
tables=table_hints,
on_query=set_query,
height="240px",
)
enable_execute = (query != query_executed) or result.error is not None
def execute():
if not len(registered_tables):
register_tables()
set_query_executed(query)
if query == query_executed and result.error:
result.retry() # type: ignore
solara.Button("Execute", on_click=execute, disabled=not enable_execute)
if result.error:
solara.Error(f"Ooops {result.error}")
elif not query:
solara.Info("No query")
elif result.value is not None:
solara.Markdown(
f"<details><summary>Query</summary> `{query_executed}`</details>"
)
df = result.value
solara.DataFrame(df)
elif query_executed is not None:
with solara.Div():
solara.Text("Loading data...")
rv.ProgressCircular(indeterminate=True, class_="solara-progress")
if result.value is not None:
with solara.Card("Download"):
with solara.Column():
df = result.value
solara.FileDownload(
data=df.to_csv(index=False),
filename="result.csv",
label="Download query result",
)
return main
def run_query():
download_dataset("googleplaystore")
download_dataset("googleplaystore_reviews")
ddb_cursor = DDB.cursor()
register_table(
ddb_cursor, "googleplaystore", path=f"{TEMP_PATH}/googleplaystore.parquet"
)
register_table(
ddb_cursor,
"googleplaystore_reviews",
path=f"{TEMP_PATH}/googleplaystore_reviews.parquet",
)
start_time = time.time()
df = ddb_cursor.sql(
"SELECT * FROM googleplaystore_reviews INNER JOIN googleplaystore ON googleplaystore_reviews.App = googleplaystore.App"
).df()
print(f"Execution time: {time.time()-start_time:.2f} seconds.")
if __name__ == "__main__":
Page()
# run_query()
11vue.runtime.esm.js:1897 Error: Cannot sendat l.send (solara-widget-manager8.min.js:391:640623)at t.send (solara-widget-manager8.min.js:23:32156)at ee.send (solara-widget-manager8.min.js:23:18578)at VueRenderer.js:183:11at Ye (vue.runtime.esm.js:1863:26)at s.n (vue.runtime.esm.js:2188:14)at Ye (vue.runtime.esm.js:1863:26)at e.$emit (vue.runtime.esm.js:3903:9)at s.click (vuetify.js:2477:12)at Ye (vue.runtime.esm.js:1863:26)
https://solara.dev/api/app_layout
The App Layout link takes you to a broken page. I also cant render the screenshot, and the "Show Code" card just shows me the hyperlink, so I can't recreate the AppLayout locally
Consider this example
import numpy as np
import pandas as pd
import plotly.express as px
import solara
# Generate data
df = pd.DataFrame.from_records(
[
{'code': "GBR", "value": 1},
{'code': "NLD", "value": 10},
{'code': "USA", "value": 3},
{'code': "FRA", "value": 2},
{'code': "ES", "value": 7},
]
)
# Make a figure
fig = px.choropleth(data_frame=df, locations='code', color='value')
# Simple solara app that captures clicks on the map and prints the click event:
@solara.component
def Page():
text, set_text = solara.use_state('text')
def function(x):
x = str(x)
set_text(x)
print(text)
with solara.VBox() as main:
solara.FigurePlotly(fig=fig, on_click=function)
solara.Card(title=text)
# solara.Card(title=solara.Markdown(text)) # uncomment this to break app
return main
display(Page()) # For Jupyter notebook only
If you run this app as is, things will work file. If you uncomment the line indicated in the code, the Card
components are no longer updated, but the actual text
variable is being updated (as you can see by the print
statement).
I only noticed this behavior for the plotly maps. I tried similar example as above with a scatter plot and a histogram and there everything works as expected.
Let me know if you need more info.
solara version: 0.14.0
system: macOS
installed via: pip (from pypi) within conda env
I'm trying to use .connect
on a solara.InputFloat
, because I'm trying to adapt the scatter.py
app example.
However, this is a solara.component
, instead of a reacton.value_component
.
I was expecting the input components to also be value components because Checkbox, Select, Togglebuttons (togglebuttons is solara.value_component
vs reacton.value_component
.
Is there a reason these are not value components?
At the moment, when I visit https://solara.dev/apps/scatter on firefox, I briefly see the web page correctly but then I get the traceback posted below.
The same occurs in chrome or in incognito window.
The other full screen apps are working.
Traceback (most recent call last):
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1794, in _reconsolidate
self._remove_element(self.context.elements[key], key, parent_key=parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1845, in _remove_element
self._remove_element(self.context.root_element, "/", parent_key=new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1861, in _remove_element
assert widget.model_id in widgets.Widget.widgets
AssertionError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1838, in _remove_element
effect.cleanup()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 968, in cleanup
self._cleanup()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/solara/hooks/dataframe.py", line 45, in cleanup
listener()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/solara/hooks/dataframe.py", line 35, in on_change
updater()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/solara/hooks/misc.py", line 355, in updater
set_counter(lambda count: count + 1)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1154, in set_
self.render(self.element, self.container)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1271, in render
widget = self._reconsolidate(self.element, default_key="/", parent_key=ROOT_KEY)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
[Previous line repeated 1 more time]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
kwargs = reconsolidate_children()
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1678, in reconsolidate_children
new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in _visit_children_values
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1907, in <dictcomp>
return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in _visit_children_values
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1902, in <listcomp>
values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1899, in _visit_children_values
return f(value, key, parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1594, in _reconsolidate
widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1794, in _reconsolidate
self._remove_element(self.context.elements[key], key, parent_key=parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1845, in _remove_element
self._remove_element(self.context.root_element, "/", parent_key=new_parent_key)
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1861, in _remove_element
assert widget.model_id in widgets.Widget.widgets
AssertionError
I have an app with a plotly graph which re-renders when users change some inputs (number of bins, selection of x/y axis, etc)
I'm using the use_thread
such that the rendering is threaded, and when the redrawing is in progress, the app shows the solara.SpinnerSolara
. This works well but there are a lot of pixels which change a lot between the loading and rendered state, which makes the app feel very jittery.
Instead, I would like to be able to place a fade, possible with text / spinner, on top of the previous render of the graph to show the component is loading. Perhaps something similar to or an extension of #81.
I'm running a simple solara app, but keep seeing the Error
ERROR: nbextension pydeck/extension not found
2023-04-11 08:32:49,240 nbextension pydeck/extension not found
It's not stopping the app from running, but I do get the error every time
I'm running this from code, not from a jupyter notebook, so it's weird to get an nbextension error. When I list my nbextensions I get
I manually installed it
jupyter nbextension install --sys-prefix --symlink --overwrite --py pydeck
jupyter nbextension enable --sys-prefix --py pydeck
and I got a success message, but it still shows that it's not successful, and I still get the error when running the app
I think sl.Table
would be great, especially if It could come from a pandas dataframe (or list of dictionaries etc).
Currently, I need to do this to get a decent centered table
html = (f"""
<table class='center' height="50%" width="100%" align=center cellpadding ="25">
<tr>
<th><h2>Question</h2></th>
<th><h2>Answer</h2></th>
</tr>
{get_table_rows()}
</table>
"""
)
and then a get_table_rows
helper function thats like this
def get_table_rows() -> str:
table_rows = ""
for question in State.history.value:
table_rows += f"<tr>\n\t<td>{question.q}</td>\n\t<td>{question.a}</td>\n</tr>"
return table_rows
It would be awesome if I could have a simple styled centered table from an object
sl.Table(my_data)
# sol.py
from ipywidgets import Layout, Button
page = Button()
# solara run sol.py
Will not give a nice error msg, but: traitlets.traitlets.TraitError: The 'children' trait of a Sheet instance contains an Union of a List which expected a DOMWidget or a unicode string, not the Layout Layout().
cc @mangecoeur
@mariobuikhuizen I took the opportunity to implement the decorator we desperately needed to avoid boilerplate in 9b47b51:
@solara._component_vue("algolia.vue")
def Algolia(app_id: str, index_name: str, api_key: str, debug=False):
pass
which I used in 7793e76
I think we should review this together and remove the underscore
On the use_state_or_update
API docs (https://solara.dev/api/use_state_or_update), when clicking the 'show code' button, you only see the code of the Page
component, which doesn't use use_state_or_update
at all.
I guess this is because the api docs page is autogenerated from the Page
component, which for most cases should be fine, however in this case the other components have the actual use case and information needed to understand the example.
Suggestion: a button that links to the github pages/api/ ...
and/or a button that links to the solara implementation on GitHub
It seems the navigation controls are remaining under the rightmost portion of the dataframe, even when the frame cannot be displayed completely due to it wide width. This leaves the navigation controls not accessible. Also, there is no scrollbar to view the rest of the dataframe columns. Here is some sample code to demo the problem:
import solara
import pandas as pd
import plotly
df = plotly.data.iris()
for col in range(60):
df[str(col)] = str(col + 1)
@solara.component
def Page():
solara.DataFrame(df, items_per_page=5)
To allow passing of things like hints/prefix/class_ etc
I would like to be able to do this:
solara.InputFloat(label="Time start", hint="Start time point.", value=t_min, on_value=set_t_min, class_='ma-2')
On Jupyter Lab, the simple word demo gives me 'Error displaying widget'. I'm running the latest ubuntu and chrome. Jupyter server version is 1.4.1.
Here is some of the log that might be helpful
manager-base.js:274 Could not instantiate widget
(anonymous) @ manager-base.js:274
u @ manager-base.js:45
(anonymous) @ manager-base.js:26
a @ manager-base.js:18
Promise.then (async)
u @ manager-base.js:19
(anonymous) @ manager-base.js:20
P @ manager-base.js:16
t._make_model @ manager-base.js:258
(anonymous) @ manager-base.js:247
u @ manager-base.js:45
(anonymous) @ manager-base.js:26
(anonymous) @ manager-base.js:20
P @ manager-base.js:16
t.new_model @ manager-base.js:233
t.handle_comm_open @ manager-base.js:145
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1021
await in _handleCommOpen (async)
_handleMessage @ default.js:1189
await in _handleMessage (async)
(anonymous) @ default.js:109
Promise.then (async)
C._onWSMessage @ default.js:106
utils.js:119 Error: Could not create a model.
at r (utils.js:119:27)
at async _handleCommOpen (523.fa256ee012d38a89b65a.js:1:2798)
at async C._handleCommOpen (default.js:1020:102)
at async C._handleMessage (default.js:1188:43)
r @ utils.js:119
Promise.catch (async)
t.handle_comm_open @ manager-base.js:150
_handleCommOpen @ 523.fa256ee012d38a89b65a.js:1
_handleCommOpen @ default.js:1021
await in _handleCommOpen (async)
_handleMessage @ default.js:1189
await in _handleMessage (async)
(anonymous) @ default.js:109
Promise.then (async)
C._onWSMessage @ default.js:106
default.js:1027 Exception opening new comm
_handleCommOpen @ default.js:1027
await in _handleCommOpen (async)
_handleMessage @ default.js:1189
await in _handleMessage (async)
(anonymous) @ default.js:109
Promise.then (async)
C._onWSMessage @ default.js:106
see #81
The API page of AppLayout refers at the bottom to the 'AppLayout page', but links to 'https://solara.dev/app/scatter', which should be 'https://solara.dev/apps/scatter' (if the intention is to refer to the scatter example)
The Avatar component accepts a size var but it's actually not used to alter the image size:
@solara.component
def Avatar(image_url: Optional[str] = None, size: Union[int, str] = 40, color: str = "primary"):
user = auth.user.value
if user:
user_info = user.get("userinfo", {})
src = image_url
if src is None:
src = user_info.get("picture")
if src:
with v.Avatar(size=40, class_="ma-2"):
v.Img(src=src)
else:
with v.Avatar(size=40, color=color):
v.Icon(children=["mdi-account"])
else:
with v.Avatar(size=40, color=color):
with solara.Tooltip("No user"):
v.Icon(children=["mdi-error"])
Should be
@solara.component
def Avatar(image_url: Optional[str] = None, size: Union[int, str] = 40, color: str = "primary"):
user = auth.user.value
if user:
user_info = user.get("userinfo", {})
src = image_url
if src is None:
src = user_info.get("picture")
if src:
with v.Avatar(size=size, class_="ma-2"):
v.Img(src=src)
else:
with v.Avatar(size=size, color=color):
v.Icon(children=["mdi-account"])
else:
with v.Avatar(size=size, color=color):
with solara.Tooltip("No user"):
v.Icon(children=["mdi-error"])
Hi everyone,
I would love to have some documentation hints at how to serve a wonderful SOLARA app using FastAPI.
In the example shown here, I don't know how to specify the python file name that contains the app. I guess the first argument of app.mount
, i.e., /solara
is the directory containing the python file containing the app.
Thanks,
Sam
hi devs, great project, I'm a heavy user of ipyvuetify and I really like the concept behind solara. I had a problem when I wanted to test it: there's no package on conda-forge (that I could find, at least).
I know that it's possible to use pip in a conda environment, which I did, but the large number of dependencies became a problem, because pip and conda don't play together very well in dependency resolution. pip attempted to update and reinstall many already-present packages.
Anyway, something to consider for the future. Thanks for your work!
I'm trying to enable the two-line
mode on a ListItem
as shown in the lists example here and in the api docs here
But instead, the title and subtitle are side-by-side.
code:
import solara
from solara.alias import rv
FILE_LIST = [
{"name": "file1.txt", "icon": "mdi-file", "subtitle": "banana"},
{"name": "file2.pdf", "icon": "mdi-file-pdf", "subtitle": "pear"},
{"name": "asdf.png", "icon": "mdi-file-image", "subtitle": "apple"}
]
@solara.component
def Page():
file_list, set_file_list = solara.use_state(FILE_LIST)
list_items = []
for idx, file in enumerate(file_list):
def on_delete(idx=idx):
new_items = file_list.copy()
del new_items[idx]
set_file_list(new_items)
delete_btn = solara.IconButton(color='primary', small=True, rounded=True, icon_name='mdi-delete',
on_click=lambda *args: on_delete())
list_item = rv.ListItem(two_line=True, #two_line=True doesnt do anything
children=[
rv.ListItemIcon(left=True, children=[rv.Icon(children=[file['icon']])]),
rv.ListItemTitle(children=[file['name']]),
rv.ListItemSubtitle(children=[file["subtitle"]]),
delete_btn
]
)
list_items.append(list_item)
rv.List(children=list_items, max_width=750)
result
Ok, mystery solved. You have to nuke your cdn cache directory, e.g. sth like this:
$ rm -rf /c/ProgramData/Miniconda3/envs/solara39/share/solara/cdn/
Originally posted by @maartenbreddels in #37 (comment)
I just updated my solara 1.7.1 to solara 1.8.0 (both installed with poetry), and I had to manually clear the cache dir to get the new install of solara to work.
Is it possible to automatically clear the cache with a new (minor) version install?
Started #100 and also asked about on Discord.
I'm opening this to collect interest.
What I can see happening is a pyinstaller + https://pypi.org/project/pywebview/ in CI to test if it is possible to make a desktop-like application and because in CI it will always be stable.
But users will still have to build the custom apps themselves if they need particular python packages.
When I'm in on cmd.exe on windows, I wanted to quickly import solara and check its installed or the version.
This unexpectedly started an interactive shell, which I do not or cannot exit (ctrl + C or exit() do not work)
What I did:
python
>>> import solara
Also it looks like that importing solara (also when running as python.exe myfile.py) prints two objects:
Often you will need to point a listitem to solara route. We can have a path_or_route
param to the ListItem()
. to support vue route (similar to solara.Link()
).
When connecting the FileDrop
to a ProgressLinear
I find that the progress bar is slow to respond to progress callbacks.
The progress value is being printed at regular intervals, every 1-2 percent for a large file, but the progress bar only updates a few times and lags behind.
code:
import solara
from solara.alias import rv
@solara.component
def Page():
progress, set_progress = solara.use_state(0.)
def on_progress(value):
print(f"on_progress: {value}")
set_progress(value)
solara.FileDrop(on_total_progress=on_progress, lazy=False, on_file=lambda x: print('file loaded'))
rv.ProgressLinear(value=progress)
ProgressCircular has the exact same behaviour
Hi everyone,
After installing the latest Solara (as of today, 1.0.3) and trying to run the simple example shared by @maartenbreddels here
I am getting a circular import error. But things are fine if I use version 0.19.1
I tried to use even 1.0.0 version, but always get this error. Can someone please help?
Thanks,
Sam
I'd like to limit file types accepted by the FileDrop
, similar to the FileInput
of #46 , but currently the FileDrop
does not take the accept
kwarg
@mariobuikhuizen I took the opportunity to implement the decorator we desperately needed to avoid boilerplate in 9b47b51:
@solara._component_vue("algolia.vue")
def Algolia(app_id: str, index_name: str, api_key: str, debug=False):
pass
which I used in 7793e76
I think we should review this together and remove the underscore
@Ben-Epstein got a 502 error,
the only thing I saw in the logs was:
Apr 11 02:36:29 PM return f(value, key, parent_key)
Apr 11 02:36:29 PM File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1605, in _reconsolidate
Apr 11 02:36:29 PM widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
Apr 11 02:36:29 PM File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 1710, in _reconsolidate
Apr 11 02:36:29 PM widget, orphan_ids = el._create_widget(kwargs)
Apr 11 02:36:29 PM File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 351, in _create_widget
Apr 11 02:36:29 PM raise RuntimeError(f"Could not create widget {self.component.widget} with {kwargs}") from e
File "/opt/render/project/src/.venv/lib/python3.9/site-packages/reacton/core.py", line 351, in _create_widget
Apr 11 02:36:29 PM raise RuntimeError(f"Could not create widget {self.component.widget} with {kwargs}") from e
Apr 11 02:36:29 PM RuntimeError: Could not create widget <class 'ipyvuetify.Html.Html'> with {'tag': 'ul', 'children': [Html(attributes={'href': '/docs'}, children=[Html(attributes={'class': None}, children=['Introduction'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/installing'}, children=[Html(attributes={'class': None}, children=['Installing'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/quickstart'}, children=[Html(attributes={'class': None}, children=['Quickstart'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/tutorial'}, children=[Html(attributes={'class': None}, children=['Tutorial', Html(attributes={'class': None}, children=[Html(attributes={'href': '/docs/tutorial/data-science'}, children=[Html(attributes={'class': None}, children=['Data Science'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/tutorial/web-app'}, children=[Html(attributes={'class': None}, children=['Web App'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/tutorial/ipywidgets'}, children=[Html(attributes={'class': None}, children=['Ipywidgets'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/tutorial/streamlit'}, children=[Html(attributes={'class': None}, children=['Streamlit'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/tutorial/dash'}, children=[Html(attributes={'class': None}, children=['Dash'], layout=None, tag='li')], layout=None, tag='a')], layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/howto'}, children=[Html(attributes={'class': None}, children=['Howto', Html(attributes={'class': None}, children=[Html(attributes={'href': '/docs/howto/multipage'}, children=[Html(attributes={'class': None}, children=['Multipage'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/howto/layout'}, children=[Html(attributes={'class': None}, children=['Layout'], layout=None, tag='li')], layout=None, tag='a')], layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference'}, children=[Html(attributes={'class': None}, children=['Reference', Html(attributes={'class': None}, children=[Html(attributes={'href': '/docs/reference/static-files'}, children=[Html(attributes={'class': None}, children=['Static Files'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference/asset-files'}, children=[Html(attributes={'class': None}, children=['Asset Files'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference/static-site-generation'}, children=[Html(attributes={'class': None}, children=['Static Site Generation'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference/search'}, children=[Html(attributes={'class': None}, children=['Search'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference/reloading'}, children=[Html(attributes={'class': None}, children=['Reloading'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference/notebook-support'}, children=[Html(attributes={'class': None}, children=['Notebook Support'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/reference/caching'}, children=[Html(attributes={'class': None}, children=['Caching'], layout=None, tag='li')], layout=None, tag='a')], layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding'}, children=[Html(attributes={'class': None}, children=['Understanding', Html(attributes={'class': None}, children=[Html(attributes={'href': '/docs/understanding/ipywidgets'}, children=[Html(attributes={'class': None}, children=['Ipywidgets'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/ipyvuetify'}, children=[Html(attributes={'class': None}, children=['Ipyvuetify'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/reacton'}, children=[Html(attributes={'class': None}, children=['Reacton'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/reacton-basics'}, children=[Html(attributes={'class': None}, children=['Reacton Basics'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/anatomy'}, children=[Html(attributes={'class': None}, children=['Anatomy'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/rules-of-hooks'}, children=[Html(attributes={'class': None}, children=['Rules Of Hooks'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/containers'}, children=[Html(attributes={'class': None}, children=['Containers'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/solara'}, children=[Html(attributes={'class': None}, children=['Solara'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/routing'}, children=[Html(attributes={'class': None}, children=['Routing'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/solara-server'}, children=[Html(attributes={'class': None}, children=['Solara Server'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/understanding/voila'}, children=[Html(attributes={'class': None}, children=['Voila'], layout=None, tag='li')], layout=None, tag='a')], layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/deploying'}, children=[Html(attributes={'class': None}, children=['Deploying', Html(attributes={'class': None}, children=[Html(attributes={'href': '/docs/deploying/self-hosted'}, children=[Html(attributes={'class': 'active'}, children=['Self Hosted'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/deploying/cloud-hosted'}, children=[Html(attributes={'class': None}, children=['Cloud Hosted'], layout=None, tag='li')], layout=None, tag='a')], layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/development'}, children=[Html(attributes={'class': None}, children=['Development', Html(attributes={'class': None}, layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/troubleshoot'}, children=[Html(attributes={'class': None}, children=['Troubleshoot'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/faq'}, children=[Html(attributes={'class': None}, children=['Faq'], layout=None, tag='li')], layout=None, tag='a'), Html(attributes={'href': '/docs/lab'}, children=[Html(attributes={'class': None}, children=['Lab', Html(attributes={'class': None}, children=[Html(attributes={'href': '/docs/lab/toestand'}, children=[Html(attributes={'class': None}, children=['Toestand'], layout=None, tag='li')], layout=None, tag='a')], layout=None, tag='ul')], layout=None, tag='li')], layout=None, tag='a')], 'attributes': {'class': None}}
Often times you want a scrollable text area for markdown, text, sql, code, anything really. You should be able to do something like
with sl.Scrollable(max_height="500px"):
sl.Markdown("## Hi")
sl.Markdown(<some_long_text>)
or something similar. Currently, I need to do this, which would be nearly impossible to figure out for a new user
import reacton.ipyvuetify as v
with sl.Card():
card_md = v.Container(
style_=(
"height: 700px; overflow-y: scroll;"
)
)
card_md.add_children([sl.Markdown(my_content)])
I'd like the FileDownload the expand to the full width of a column / sidebar.
import solara
@solara.component
def Page():
with solara.Sidebar():
with solara.Column():
solara.InputText(label="Text input")
solara.Button(label='My button', block=True)
solara.FileDownload(label='My file download', data='foobar')
with solara.Column():
solara.InputText(label="Text input")
solara.Button(label='My button', block=True)
solara.FileDownload(label='My file download', data='foobar')
gives:
I can make the button expand in width with block=True
, but the FileDownload
does not accept this kwarg.
We currently don't support latex. Although we can support it easily on initial page load, we should also make sure they get updated when the widget value updates.
See voila-dashboards/voila#531 for inspiration
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.