Skip to content

Commit a725680

Browse files
feat: transitions component for slick UI's
Based on Vue's transitions
1 parent cded5b2 commit a725680

File tree

6 files changed

+141
-0
lines changed

6 files changed

+141
-0
lines changed

solara/components/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
from .switch import Switch # noqa: F401 F403
5656
from .progress import ProgressLinear # noqa: F401 F403
5757
from .component_vue import _component_vue, component_vue # noqa: F401 F403
58+
from .transition import Transition # noqa: F401 F403
5859
import reacton.core
5960

6061
try:

solara/components/_transitions.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import solara
2+
3+
4+
@solara.component
5+
def TransitionFlip(axis: str, show_first=True, children=[], duration=0.2):
6+
uid = solara.use_unique_key()[:6]
7+
name = f"rotate-{axis}-{uid}"
8+
css_code = f"""
9+
.{name}-enter-active, .{name}-leave-active {{
10+
transition: all {duration}s ease-out;
11+
backface-visibility: hidden;
12+
}}
13+
14+
.{name}-enter, .{name}-leave-to {{
15+
transform: rotate{axis}(90deg);
16+
}}
17+
.{name}-enter-to, .{name}-leave {{
18+
transform: rotate{axis}(0deg);
19+
}}
20+
"""
21+
solara.Style(css_code)
22+
solara.Transition(show_first=show_first, name=name, duration=duration, children=children, mode="out-in")
23+
24+
25+
@solara.component
26+
def TransitionSlide(axis: str = "X", show_first=True, children=[], duration=0.2, translate_enter="50px", translate_leave="-50px"):
27+
uid = solara.use_unique_key()[:6]
28+
name = f"slide-{axis}-{uid}"
29+
css_code = f"""
30+
.{name}-enter-active, .{name}-leave-active {{
31+
transition: all {duration}s ease-out !important;
32+
}}
33+
34+
.{name}-enter {{
35+
transform: translate{axis}({translate_enter});
36+
opacity: 0;
37+
}}
38+
39+
.{name}-leave-to {{
40+
transform: translate{axis}({translate_leave});
41+
opacity: 0;
42+
}}
43+
.{name}-enter-to, .{name}-leave {{
44+
transform: translate{axis}(0px);
45+
}}
46+
"""
47+
print("css", css_code)
48+
solara.Style(css_code)
49+
solara.Transition(show_first=show_first, name=name, duration=duration, children=children, mode="out-in")

solara/components/transition.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import solara
2+
from .component_vue import component_vue
3+
4+
5+
@solara.component
6+
def Transition(show_first=True, children=[], name="", mode="", duration=0.2):
7+
"""Transitions between two child elements with an animation.
8+
9+
These transitions are based on Vue's transition system.
10+
11+
* https://v2.vuejs.org/v2/guide/transitions
12+
* https://vuejs.org/guide/built-ins/transition
13+
14+
"""
15+
# in Python land we like to work with seconds
16+
return _Transition(show_first=show_first, children=children, name=name, mode=mode, duration=duration * 1000)
17+
18+
19+
@component_vue("transition.vue")
20+
def _Transition(show_first=True, children=[], name="", mode="", duration=200):
21+
pass # just a dummy function

solara/components/transition.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<template>
2+
<Transition :name="name" :mode="mode" :duration="duration">
3+
<jupyter-widget v-if="show_first && children.length > 0" :widget="children[0]" key="first-widget"></jupyter-widget>
4+
<jupyter-widget v-if="!show_first && children.length > 1" :widget="children[1]" key="second-widget"></jupyter-widget>
5+
</Transition>
6+
</template>

solara/lab/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from ..lifecycle import on_kernel_start # noqa: F401
55
from ..tasks import task, use_task, Task, TaskResult # noqa: F401, F403
66
from ..toestand import computed # noqa: F401
7+
from ..components._transitions import TransitionFlip, TransitionSlide # noqa: F401
78

89

910
def __getattr__(name):
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# check out https://solara.dev/ for documentation
2+
# or https://github.com/widgetti/solara/
3+
# And check out https://py.cafe/maartenbreddels for more examples
4+
5+
import solara
6+
import solara.lab
7+
8+
9+
clicks = solara.reactive(0)
10+
11+
12+
@solara.component
13+
def Page():
14+
color = "green"
15+
if clicks.value >= 5:
16+
color = "red"
17+
18+
def increment():
19+
clicks.value += 1
20+
21+
solara.Button(label=f"Clicked: {clicks}", on_click=increment, color=color)
22+
23+
with solara.lab.TransitionFlip("X", show_first=(clicks.value % 2) == 0, duration=0.2):
24+
with solara.Card("Even") as el1:
25+
solara.Text("This number is even")
26+
with solara.Card("Odd") as el2:
27+
solara.Text("This number is even")
28+
29+
with solara.Card("List"):
30+
TodoItem("Write", True)
31+
TodoItem("Read", False)
32+
33+
RemovableCard()
34+
RemovableCard()
35+
solara.v.use_event(el1, "click", lambda *_ignore: increment())
36+
solara.v.use_event(el2, "click", lambda *_ignore: increment())
37+
38+
39+
@solara.component
40+
def RemovableCard():
41+
show = solara.use_reactive(True)
42+
with solara.lab.TransitionSlide("X", show_first=show.value, duration=0.5, translate_leave="100px"):
43+
with solara.Card("Some report"):
44+
with solara.Column():
45+
solara.Text(
46+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
47+
)
48+
solara.Markdown("*Close the card to see it animate away*")
49+
with solara.CardActions():
50+
solara.v.Spacer()
51+
solara.Button("Close", on_click=lambda: show.set(False), text=True)
52+
53+
54+
@solara.component
55+
def TodoItem(text, default_value):
56+
done = solara.use_reactive(default_value)
57+
58+
with solara.Row(style={"overflow": "hidden"}):
59+
solara.Switch(label=text, value=done)
60+
solara.v.Spacer()
61+
62+
with solara.lab.TransitionSlide("X", show_first=done.value, duration=0.2):
63+
solara.v.Icon(children=["mdi-check"], color="success")

0 commit comments

Comments
 (0)