reflex 0.4.9a2__py3-none-any.whl → 0.5.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of reflex might be problematic. Click here for more details.

Files changed (131) hide show
  1. reflex/.templates/apps/blank/code/blank.py +19 -16
  2. reflex/.templates/apps/demo/code/pages/datatable.py +4 -4
  3. reflex/.templates/apps/demo/code/pages/forms.py +2 -2
  4. reflex/.templates/web/utils/helpers/debounce.js +17 -0
  5. reflex/.templates/web/utils/helpers/throttle.js +22 -0
  6. reflex/.templates/web/utils/state.js +21 -3
  7. reflex/__init__.py +6 -1
  8. reflex/__init__.pyi +4 -1
  9. reflex/app.py +157 -140
  10. reflex/app_module_for_backend.py +1 -1
  11. reflex/base.py +13 -15
  12. reflex/compiler/compiler.py +10 -1
  13. reflex/compiler/utils.py +3 -30
  14. reflex/components/__init__.py +1 -0
  15. reflex/components/chakra/datadisplay/list.py +1 -3
  16. reflex/components/chakra/datadisplay/list.pyi +3 -3
  17. reflex/components/chakra/disclosure/accordion.py +1 -1
  18. reflex/components/chakra/forms/pininput.pyi +1 -1
  19. reflex/components/chakra/media/icon.py +2 -2
  20. reflex/components/component.py +279 -32
  21. reflex/components/core/__init__.py +2 -2
  22. reflex/components/core/cond.py +1 -10
  23. reflex/components/core/debounce.py +5 -2
  24. reflex/components/core/debounce.pyi +4 -2
  25. reflex/components/core/foreach.py +1 -16
  26. reflex/components/core/html.py +6 -0
  27. reflex/components/core/match.py +2 -17
  28. reflex/components/core/upload.py +42 -1
  29. reflex/components/core/upload.pyi +199 -1
  30. reflex/components/datadisplay/code.py +7 -3
  31. reflex/components/datadisplay/code.pyi +3 -1
  32. reflex/components/el/elements/forms.py +1 -1
  33. reflex/components/el/elements/forms.pyi +1 -1
  34. reflex/components/lucide/icon.py +5 -13
  35. reflex/components/lucide/icon.pyi +0 -1
  36. reflex/components/markdown/markdown.py +5 -23
  37. reflex/components/markdown/markdown.pyi +1 -4
  38. reflex/components/radix/primitives/accordion.py +227 -406
  39. reflex/components/radix/primitives/accordion.pyi +369 -28
  40. reflex/components/radix/primitives/form.py +33 -29
  41. reflex/components/radix/primitives/form.pyi +7 -2
  42. reflex/components/radix/primitives/progress.py +17 -9
  43. reflex/components/radix/primitives/progress.pyi +2 -0
  44. reflex/components/radix/primitives/slider.py +30 -18
  45. reflex/components/radix/primitives/slider.pyi +4 -0
  46. reflex/components/radix/themes/base.py +8 -1
  47. reflex/components/radix/themes/base.pyi +79 -1
  48. reflex/components/radix/themes/color_mode.py +74 -30
  49. reflex/components/radix/themes/color_mode.pyi +26 -185
  50. reflex/components/radix/themes/components/__init__.py +17 -0
  51. reflex/components/radix/themes/components/badge.py +2 -1
  52. reflex/components/radix/themes/components/badge.pyi +3 -1
  53. reflex/components/radix/themes/components/button.py +3 -1
  54. reflex/components/radix/themes/components/button.pyi +4 -1
  55. reflex/components/radix/themes/components/checkbox_cards.py +48 -0
  56. reflex/components/radix/themes/components/checkbox_cards.pyi +264 -0
  57. reflex/components/radix/themes/components/checkbox_group.py +42 -0
  58. reflex/components/radix/themes/components/checkbox_group.pyi +253 -0
  59. reflex/components/radix/themes/components/data_list.py +63 -0
  60. reflex/components/radix/themes/components/data_list.pyi +426 -0
  61. reflex/components/radix/themes/components/icon_button.py +20 -17
  62. reflex/components/radix/themes/components/icon_button.pyi +5 -1
  63. reflex/components/radix/themes/components/progress.py +55 -0
  64. reflex/components/radix/themes/components/progress.pyi +180 -0
  65. reflex/components/radix/themes/components/radio.py +31 -0
  66. reflex/components/radix/themes/components/radio.pyi +169 -0
  67. reflex/components/radix/themes/components/radio_cards.py +48 -0
  68. reflex/components/radix/themes/components/radio_cards.pyi +264 -0
  69. reflex/components/radix/themes/components/radio_group.py +2 -4
  70. reflex/components/radix/themes/components/segmented_control.py +48 -0
  71. reflex/components/radix/themes/components/segmented_control.pyi +262 -0
  72. reflex/components/radix/themes/components/skeleton.py +32 -0
  73. reflex/components/radix/themes/components/skeleton.pyi +106 -0
  74. reflex/components/radix/themes/components/spinner.py +26 -0
  75. reflex/components/radix/themes/components/spinner.pyi +101 -0
  76. reflex/components/radix/themes/components/tabs.py +26 -1
  77. reflex/components/radix/themes/components/tabs.pyi +69 -9
  78. reflex/components/radix/themes/components/text_field.py +101 -71
  79. reflex/components/radix/themes/components/text_field.pyi +81 -499
  80. reflex/components/radix/themes/layout/base.py +2 -2
  81. reflex/components/radix/themes/layout/base.pyi +4 -4
  82. reflex/components/radix/themes/layout/center.py +8 -3
  83. reflex/components/radix/themes/layout/center.pyi +2 -1
  84. reflex/components/radix/themes/layout/container.py +30 -2
  85. reflex/components/radix/themes/layout/container.pyi +9 -30
  86. reflex/components/radix/themes/layout/list.py +10 -5
  87. reflex/components/radix/themes/layout/list.pyi +5 -21
  88. reflex/components/radix/themes/layout/spacer.py +8 -3
  89. reflex/components/radix/themes/layout/spacer.pyi +2 -1
  90. reflex/components/radix/themes/layout/stack.py +7 -1
  91. reflex/components/radix/themes/layout/stack.pyi +3 -3
  92. reflex/components/radix/themes/typography/link.py +10 -2
  93. reflex/components/radix/themes/typography/link.pyi +5 -4
  94. reflex/components/sonner/__init__.py +3 -0
  95. reflex/components/sonner/toast.py +267 -0
  96. reflex/components/sonner/toast.pyi +205 -0
  97. reflex/components/tags/iter_tag.py +9 -6
  98. reflex/config.py +30 -54
  99. reflex/constants/__init__.py +0 -2
  100. reflex/constants/base.py +0 -5
  101. reflex/constants/colors.py +2 -0
  102. reflex/constants/installer.py +5 -1
  103. reflex/constants/route.py +4 -0
  104. reflex/custom_components/custom_components.py +22 -1
  105. reflex/event.py +75 -30
  106. reflex/experimental/__init__.py +5 -0
  107. reflex/experimental/layout.py +24 -6
  108. reflex/model.py +2 -1
  109. reflex/page.py +7 -4
  110. reflex/reflex.py +8 -3
  111. reflex/route.py +39 -0
  112. reflex/state.py +128 -131
  113. reflex/style.py +20 -1
  114. reflex/testing.py +10 -6
  115. reflex/utils/console.py +3 -1
  116. reflex/utils/exec.py +20 -7
  117. reflex/utils/format.py +1 -1
  118. reflex/utils/imports.py +3 -1
  119. reflex/utils/prerequisites.py +141 -20
  120. reflex/utils/processes.py +21 -1
  121. reflex/utils/pyi_generator.py +95 -5
  122. reflex/utils/serializers.py +1 -1
  123. reflex/utils/telemetry.py +26 -4
  124. reflex/utils/types.py +62 -18
  125. reflex/vars.py +11 -5
  126. {reflex-0.4.9a2.dist-info → reflex-0.5.0a1.dist-info}/METADATA +16 -4
  127. {reflex-0.4.9a2.dist-info → reflex-0.5.0a1.dist-info}/RECORD +130 -108
  128. {reflex-0.4.9a2.dist-info → reflex-0.5.0a1.dist-info}/WHEEL +1 -1
  129. reflex/app.pyi +0 -149
  130. {reflex-0.4.9a2.dist-info → reflex-0.5.0a1.dist-info}/LICENSE +0 -0
  131. {reflex-0.4.9a2.dist-info → reflex-0.5.0a1.dist-info}/entry_points.txt +0 -0
@@ -5,302 +5,42 @@ from __future__ import annotations
5
5
  from typing import Any, Dict, List, Literal, Optional, Union
6
6
 
7
7
  from reflex.components.component import Component, ComponentNamespace
8
- from reflex.components.core.match import Match
8
+ from reflex.components.core.colors import color
9
9
  from reflex.components.lucide.icon import Icon
10
10
  from reflex.components.radix.primitives.base import RadixPrimitiveComponent
11
11
  from reflex.components.radix.themes.base import LiteralAccentColor
12
- from reflex.style import (
13
- Style,
14
- convert_dict_to_style_and_format_emotion,
15
- format_as_emotion,
16
- )
12
+ from reflex.style import Style
17
13
  from reflex.utils import imports
18
- from reflex.vars import BaseVar, Var, VarData, get_uuid_string_var
14
+ from reflex.vars import Var, get_uuid_string_var
19
15
 
20
16
  LiteralAccordionType = Literal["single", "multiple"]
21
17
  LiteralAccordionDir = Literal["ltr", "rtl"]
22
18
  LiteralAccordionOrientation = Literal["vertical", "horizontal"]
23
- LiteralAccordionRootVariant = Literal["classic", "soft", "surface", "outline", "ghost"]
24
- LiteralAccordionRootColorScheme = Literal["primary", "accent"]
19
+ LiteralAccordionVariant = Literal["classic", "soft", "surface", "outline", "ghost"]
25
20
 
26
21
  DEFAULT_ANIMATION_DURATION = 250
27
22
 
28
23
 
29
- def get_theme_accordion_root(variant: Var[str], color_scheme: Var[str]) -> BaseVar:
30
- """Get the theme for the accordion root component.
31
-
32
- Args:
33
- variant: The variant of the accordion.
34
- color_scheme: The color of the accordion.
35
-
36
- Returns:
37
- The theme for the accordion root component.
38
- """
39
- return Match.create( # type: ignore
40
- variant,
41
- (
42
- "soft",
43
- convert_dict_to_style_and_format_emotion(
44
- {
45
- "border_radius": "6px",
46
- "background_color": f"var(--{color_scheme}-3)",
47
- "box_shadow": "0 2px 10px var(--black-a1)",
48
- }
49
- ),
50
- ),
51
- (
52
- "outline",
53
- convert_dict_to_style_and_format_emotion(
54
- {
55
- "border_radius": "6px",
56
- "border": f"1px solid var(--{color_scheme}-6)",
57
- "box_shadow": "0 2px 10px var(--black-a1)",
58
- }
59
- ),
60
- ),
61
- (
62
- "surface",
63
- convert_dict_to_style_and_format_emotion(
64
- {
65
- "border_radius": "6px",
66
- "border": f"1px solid var(--{color_scheme}-6)",
67
- "background_color": f"var(--{color_scheme}-3)",
68
- "box_shadow": "0 2px 10px var(--black-a1)",
69
- }
70
- ),
71
- ),
72
- (
73
- "ghost",
74
- convert_dict_to_style_and_format_emotion(
75
- {
76
- "border_radius": "6px",
77
- "background_color": "none",
78
- "box_shadow": "None",
79
- }
80
- ),
81
- ),
82
- convert_dict_to_style_and_format_emotion(
83
- {
84
- "border_radius": "6px",
85
- "background_color": f"var(--{color_scheme}-9)",
86
- "box_shadow": "0 2px 10px var(--black-a4)",
87
- }
88
- ),
89
- # defaults to classic
90
- )
91
-
92
-
93
- def get_theme_accordion_item():
94
- """Get the theme for the accordion item component.
95
-
96
- Returns:
97
- The theme for the accordion item component.
98
- """
99
- return convert_dict_to_style_and_format_emotion(
100
- {
101
- "overflow": "hidden",
102
- "width": "100%",
103
- "margin_top": "1px",
104
- "&:first-child": {
105
- "margin_top": 0,
106
- "border_top_left_radius": "4px",
107
- "border_top_right_radius": "4px",
108
- },
109
- "&:last-child": {
110
- "border_bottom_left_radius": "4px",
111
- "border_bottom_right_radius": "4px",
112
- },
113
- "&:focus-within": {
114
- "position": "relative",
115
- "z_index": 1,
116
- },
117
- }
118
- )
119
-
24
+ class AccordionComponent(RadixPrimitiveComponent):
25
+ """Base class for all @radix-ui/accordion components."""
120
26
 
121
- def get_theme_accordion_header() -> dict[str, str]:
122
- """Get the theme for the accordion header component.
27
+ library = "@radix-ui/react-accordion@^1.1.2"
123
28
 
124
- Returns:
125
- The theme for the accordion header component.
126
- """
127
- return {
128
- "display": "flex",
129
- }
29
+ # The color scheme of the component.
30
+ color_scheme: Var[LiteralAccentColor]
130
31
 
32
+ # The variant of the component.
33
+ variant: Var[LiteralAccordionVariant] = Var.create_safe("classic")
131
34
 
132
- def get_theme_accordion_trigger(variant: str | Var, color_scheme: str | Var) -> BaseVar:
133
- """Get the theme for the accordion trigger component.
35
+ def add_style(self) -> Style | None:
36
+ """Add style to the component."""
37
+ if self.color_scheme is not None:
38
+ self.custom_attrs["data-accent-color"] = self.color_scheme
134
39
 
135
- Args:
136
- variant: The variant of the accordion.
137
- color_scheme: The color of the accordion.
40
+ self.custom_attrs["data-variant"] = self.variant
138
41
 
139
- Returns:
140
- The theme for the accordion trigger component.
141
- """
142
- return Match.create( # type: ignore
143
- variant,
144
- (
145
- "soft",
146
- convert_dict_to_style_and_format_emotion(
147
- {
148
- "color": f"var(--{color_scheme}-11)",
149
- "&:hover": {
150
- "background_color": f"var(--{color_scheme}-4)",
151
- },
152
- "& > .AccordionChevron": {
153
- "color": f"var(--{color_scheme}-11)",
154
- "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
155
- },
156
- "&[data-state='open'] > .AccordionChevron": {
157
- "transform": "rotate(180deg)",
158
- },
159
- "font_family": "inherit",
160
- "width": "100%",
161
- "padding": "0 20px",
162
- "height": "45px",
163
- "flex": 1,
164
- "display": "flex",
165
- "align_items": "center",
166
- "justify_content": "space-between",
167
- "font_size": "15px",
168
- "line_height": 1,
169
- }
170
- ),
171
- ),
172
- (
173
- "outline",
174
- "surface",
175
- "ghost",
176
- convert_dict_to_style_and_format_emotion(
177
- {
178
- "color": f"var(--{color_scheme}-11)",
179
- "&:hover": {
180
- "background_color": f"var(--{color_scheme}-4)",
181
- },
182
- "& > .AccordionChevron": {
183
- "color": f"var(--{color_scheme}-11)",
184
- "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
185
- },
186
- "&[data-state='open'] > .AccordionChevron": {
187
- "transform": "rotate(180deg)",
188
- },
189
- "font_family": "inherit",
190
- "width": "100%",
191
- "padding": "0 20px",
192
- "height": "45px",
193
- "flex": 1,
194
- "display": "flex",
195
- "align_items": "center",
196
- "justify_content": "space-between",
197
- "font_size": "15px",
198
- "line_height": 1,
199
- }
200
- ),
201
- ),
202
- # defaults to classic
203
- convert_dict_to_style_and_format_emotion(
204
- {
205
- "color": f"var(--{color_scheme}-9-contrast)",
206
- "box_shadow": f"var(--{color_scheme}-11)",
207
- "&:hover": {
208
- "background_color": f"var(--{color_scheme}-10)",
209
- },
210
- "& > .AccordionChevron": {
211
- "color": f"var(--{color_scheme}-9-contrast)",
212
- "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
213
- },
214
- "&[data-state='open'] > .AccordionChevron": {
215
- "transform": "rotate(180deg)",
216
- },
217
- "font_family": "inherit",
218
- "width": "100%",
219
- "padding": "0 20px",
220
- "height": "45px",
221
- "flex": 1,
222
- "display": "flex",
223
- "align_items": "center",
224
- "justify_content": "space-between",
225
- "font_size": "15px",
226
- "line_height": 1,
227
- }
228
- ),
229
- )
230
-
231
-
232
- def get_theme_accordion_content(variant: str | Var, color_scheme: str | Var) -> BaseVar:
233
- """Get the theme for the accordion content component.
234
-
235
- Args:
236
- variant: The variant of the accordion.
237
- color_scheme: The color of the accordion.
238
-
239
- Returns:
240
- The theme for the accordion content component.
241
- """
242
- return Match.create( # type: ignore
243
- variant,
244
- (
245
- "outline",
246
- "ghost",
247
- convert_dict_to_style_and_format_emotion(
248
- {
249
- "overflow": "hidden",
250
- "font_size": "10px",
251
- "color": f"var(--{color_scheme}-11)",
252
- "padding": "15px 20px",
253
- "&[data-state='open']": {
254
- "animation": Var.create(
255
- f"${{slideDown}} {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
256
- _var_is_string=True,
257
- ),
258
- },
259
- "&[data-state='closed']": {
260
- "animation": Var.create(
261
- f"${{slideUp}} {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
262
- _var_is_string=True,
263
- ),
264
- },
265
- }
266
- ),
267
- ),
268
- convert_dict_to_style_and_format_emotion(
269
- {
270
- "overflow": "hidden",
271
- "font_size": "10px",
272
- "color": Match.create(
273
- variant,
274
- ("classic", f"var(--{color_scheme}-9-contrast)"),
275
- f"var(--{color_scheme}-11)",
276
- ),
277
- "background_color": Match.create(
278
- variant,
279
- ("classic", f"var(--{color_scheme}-9)"),
280
- f"var(--{color_scheme}-3)",
281
- ),
282
- "padding": "15px 20px",
283
- "&[data-state='open']": {
284
- "animation": Var.create(
285
- f"${{slideDown}} {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
286
- _var_is_string=True,
287
- ),
288
- },
289
- "&[data-state='closed']": {
290
- "animation": Var.create(
291
- f"${{slideUp}} {DEFAULT_ANIMATION_DURATION}ms cubic-bezier(0.87, 0, 0.13, 1)",
292
- _var_is_string=True,
293
- ),
294
- },
295
- }
296
- ),
297
- )
298
-
299
-
300
- class AccordionComponent(RadixPrimitiveComponent):
301
- """Base class for all @radix-ui/accordion components."""
302
-
303
- library = "@radix-ui/react-accordion@^1.1.2"
42
+ def _exclude_props(self) -> list[str]:
43
+ return ["color_scheme", "variant"]
304
44
 
305
45
 
306
46
  class AccordionRoot(AccordionComponent):
@@ -314,10 +54,10 @@ class AccordionRoot(AccordionComponent):
314
54
  type: Var[LiteralAccordionType]
315
55
 
316
56
  # The value of the item to expand.
317
- value: Var[Optional[Union[str, List[str]]]]
57
+ value: Var[Union[str, List[str]]]
318
58
 
319
59
  # The default value of the item to expand.
320
- default_value: Var[Optional[Union[str, List[str]]]]
60
+ default_value: Var[Union[str, List[str]]]
321
61
 
322
62
  # Whether or not the accordion is collapsible.
323
63
  collapsible: Var[bool]
@@ -332,16 +72,7 @@ class AccordionRoot(AccordionComponent):
332
72
  orientation: Var[LiteralAccordionOrientation]
333
73
 
334
74
  # The variant of the accordion.
335
- variant: Var[LiteralAccordionRootVariant] = "classic" # type: ignore
336
-
337
- # The color scheme of the accordion.
338
- color_scheme: Var[LiteralAccentColor] # type: ignore
339
-
340
- # dynamic themes of the accordion generated at compile time.
341
- _dynamic_themes: Var[dict] = Var.create({}) # type: ignore
342
-
343
- # The var_data associated with the component.
344
- _var_data: VarData = VarData() # type: ignore
75
+ variant: Var[LiteralAccordionVariant] = Var.create_safe("classic")
345
76
 
346
77
  _valid_children: List[str] = ["AccordionItem"]
347
78
 
@@ -356,81 +87,12 @@ class AccordionRoot(AccordionComponent):
356
87
  Returns:
357
88
  The Accordion root Component.
358
89
  """
359
- comp = super().create(*children, **props)
360
-
361
- if comp.color_scheme is not None and not comp.color_scheme._var_state: # type: ignore
362
- # mark the vars of color string literals as strings so they can be formatted properly when performing a var operation.
363
- comp.color_scheme._var_is_string = True # type: ignore
364
-
365
- if comp.variant is not None and not comp.variant._var_state: # type: ignore
366
- # mark the vars of variant string literals as strings so they are formatted properly in the match condition.
367
- comp.variant._var_is_string = True # type: ignore
368
-
369
- return comp
370
-
371
- def _get_style(self) -> dict:
372
- """Get the style for the component.
373
-
374
- Returns:
375
- The dictionary of the component style as value and the style notation as key.
376
- """
377
- return {"css": self._dynamic_themes._merge(format_as_emotion(self.style))} # type: ignore
378
-
379
- def _apply_theme(self, theme: Component):
380
- global_color_scheme = getattr(theme, "accent_color", None)
381
-
382
- if global_color_scheme is None and self.color_scheme is None:
383
- raise ValueError(
384
- "`color_scheme` cannot be None. Either set the `color_scheme` prop on the accordion "
385
- "component or set the `accent_color` prop in your global theme."
386
- )
387
-
388
- # prepare the color_scheme var to be used in an f-string(strip off the wrapping curly brace)
389
- color_scheme = Var.create(
390
- self.color_scheme if self.color_scheme is not None else global_color_scheme
391
- )._replace( # type: ignore
392
- _var_is_string=False
393
- )
90
+ for child in children:
91
+ if isinstance(child, AccordionItem):
92
+ child.color_scheme = props.get("color_scheme") # type: ignore
93
+ child.variant = props.get("variant") # type: ignore
394
94
 
395
- accordion_theme_root = get_theme_accordion_root(
396
- variant=self.variant, color_scheme=color_scheme
397
- )
398
- accordion_theme_content = get_theme_accordion_content(
399
- variant=self.variant, color_scheme=color_scheme
400
- )
401
- accordion_theme_trigger = get_theme_accordion_trigger(
402
- variant=self.variant, color_scheme=color_scheme
403
- )
404
-
405
- # extract var_data from dynamic themes.
406
- self._var_data = (
407
- self._var_data.merge( # type: ignore
408
- accordion_theme_trigger._var_data,
409
- accordion_theme_content._var_data,
410
- accordion_theme_root._var_data,
411
- )
412
- or self._var_data
413
- )
414
-
415
- self._dynamic_themes = Var.create( # type: ignore
416
- convert_dict_to_style_and_format_emotion(
417
- {
418
- "& .AccordionItem": get_theme_accordion_item(),
419
- "& .AccordionHeader": get_theme_accordion_header(),
420
- "& .AccordionTrigger": accordion_theme_trigger,
421
- "& .AccordionContent": accordion_theme_content,
422
- }
423
- )
424
- )._merge( # type: ignore
425
- accordion_theme_root
426
- )
427
-
428
- def _get_imports(self):
429
- return imports.merge_imports(
430
- super()._get_imports(),
431
- self._var_data.imports if self._var_data else {},
432
- {"@emotion/react": [imports.ImportVar(tag="keyframes")]},
433
- )
95
+ return super().create(*children, **props)
434
96
 
435
97
  def get_event_triggers(self) -> Dict[str, Any]:
436
98
  """Get the events triggers signatures for the component.
@@ -443,28 +105,36 @@ class AccordionRoot(AccordionComponent):
443
105
  "on_value_change": lambda e0: [e0],
444
106
  }
445
107
 
446
- def _get_custom_code(self) -> str:
447
- return """
448
- const slideDown = keyframes`
449
- from {
450
- height: 0;
451
- }
452
- to {
453
- height: var(--radix-accordion-content-height);
454
- }
455
- `
456
- const slideUp = keyframes`
457
- from {
458
- height: var(--radix-accordion-content-height);
459
- }
460
- to {
461
- height: 0;
462
- }
463
- `
464
- """
108
+ def add_style(self):
109
+ """Add style to the component.
465
110
 
466
- def _exclude_props(self) -> list[str]:
467
- return ["color_scheme", "variant"]
111
+ Returns:
112
+ The style of the component.
113
+ """
114
+ return Style(
115
+ {
116
+ "border_radius": "6px",
117
+ "box_shadow": f"0 2px 10px {color('black', 1, alpha=True)}",
118
+ "&[data-variant='classic']": {
119
+ "background_color": color("accent", 9),
120
+ "box_shadow": f"0 2px 10px {color('black', 4, alpha=True)}",
121
+ },
122
+ "&[data-variant='soft']": {
123
+ "background_color": color("accent", 3),
124
+ },
125
+ "&[data-variant='outline']": {
126
+ "border": f"1px solid {color('accent', 6)}",
127
+ },
128
+ "&[data-variant='surface']": {
129
+ "border": f"1px solid {color('accent', 6)}",
130
+ "background_color": color("accent", 3),
131
+ },
132
+ "&[data-variant='ghost']": {
133
+ "background_color": "none",
134
+ "box_shadow": "None",
135
+ },
136
+ }
137
+ )
468
138
 
469
139
 
470
140
  class AccordionItem(AccordionComponent):
@@ -488,13 +158,6 @@ class AccordionItem(AccordionComponent):
488
158
 
489
159
  _valid_parents: List[str] = ["AccordionRoot"]
490
160
 
491
- def _apply_theme(self, theme: Component):
492
- self.style = Style(
493
- {
494
- **self.style,
495
- }
496
- )
497
-
498
161
  @classmethod
499
162
  def create(
500
163
  cls,
@@ -506,9 +169,9 @@ class AccordionItem(AccordionComponent):
506
169
  """Create an accordion item.
507
170
 
508
171
  Args:
172
+ *children: The list of children to use if header and content are not provided.
509
173
  header: The header of the accordion item.
510
174
  content: The content of the accordion item.
511
- *children: The list of children to use if header and content are not provided.
512
175
  **props: Additional properties to apply to the accordion item.
513
176
 
514
177
  Returns:
@@ -527,14 +190,55 @@ class AccordionItem(AccordionComponent):
527
190
  AccordionHeader.create(
528
191
  AccordionTrigger.create(
529
192
  header,
530
- AccordionIcon.create(),
193
+ AccordionIcon.create(
194
+ color_scheme=props.get("color_scheme"),
195
+ variant=props.get("variant"),
196
+ ),
197
+ color_scheme=props.get("color_scheme"),
198
+ variant=props.get("variant"),
531
199
  ),
200
+ color_scheme=props.get("color_scheme"),
201
+ variant=props.get("variant"),
202
+ ),
203
+ AccordionContent.create(
204
+ content, color_scheme=props.get("color_scheme")
532
205
  ),
533
- AccordionContent.create(content),
534
206
  ]
535
207
 
536
208
  return super().create(*children, value=value, **props, class_name=cls_name)
537
209
 
210
+ def add_style(self) -> Style | None:
211
+ """Add style to the component.
212
+
213
+ Returns:
214
+ The style of the component.
215
+ """
216
+ for child in self.children:
217
+ if isinstance(child, (AccordionHeader, AccordionContent)):
218
+ child.color_scheme = self.color_scheme
219
+ child.variant = self.variant
220
+
221
+ return Style(
222
+ {
223
+ "overflow": "hidden",
224
+ "width": "100%",
225
+ "margin_top": "1px",
226
+ "&:first-child": {
227
+ "margin_top": 0,
228
+ "border_top_left_radius": "4px",
229
+ "border_top_right_radius": "4px",
230
+ },
231
+ "&:last-child": {
232
+ "border_bottom_left_radius": "4px",
233
+ "border_bottom_right_radius": "4px",
234
+ },
235
+ "&:focus-within": {
236
+ "position": "relative",
237
+ "z_index": 1,
238
+ },
239
+ }
240
+ )
241
+
538
242
 
539
243
  class AccordionHeader(AccordionComponent):
540
244
  """An accordion component."""
@@ -561,8 +265,21 @@ class AccordionHeader(AccordionComponent):
561
265
 
562
266
  return super().create(*children, class_name=cls_name, **props)
563
267
 
564
- def _apply_theme(self, theme: Component):
565
- self.style = Style({**self.style})
268
+ def add_style(self) -> Style | None:
269
+ """Add style to the component.
270
+
271
+ Returns:
272
+ The style of the component.
273
+ """
274
+ for child in self.children:
275
+ if isinstance(child, AccordionTrigger):
276
+ child.color_scheme = self.color_scheme
277
+ child.variant = self.variant
278
+
279
+ return Style({"display": "flex"})
280
+
281
+
282
+ cubic_bezier = "cubic-bezier(0.87, 0, 0.13, 1)"
566
283
 
567
284
 
568
285
  class AccordionTrigger(AccordionComponent):
@@ -590,8 +307,52 @@ class AccordionTrigger(AccordionComponent):
590
307
 
591
308
  return super().create(*children, class_name=cls_name, **props)
592
309
 
593
- def _apply_theme(self, theme: Component):
594
- self.style = Style({**self.style})
310
+ def add_style(self) -> Style | None:
311
+ """Add style to the component.
312
+
313
+ Returns:
314
+ The style of the component.
315
+ """
316
+ for child in self.children:
317
+ if isinstance(child, AccordionIcon):
318
+ child.color_scheme = self.color_scheme
319
+ child.variant = self.variant
320
+
321
+ return Style(
322
+ {
323
+ "color": color("accent", 11),
324
+ "line_height": 1,
325
+ "font_size": "15px",
326
+ "justify_content": "space-between",
327
+ "align_items": "center",
328
+ "flex": 1,
329
+ "display": "flex",
330
+ "padding": "0 20px",
331
+ "height": "45px",
332
+ "font_family": "inherit",
333
+ "width": "100%",
334
+ "&[data-state='open'] > .AccordionChevron": {
335
+ "transform": "rotate(180deg)",
336
+ },
337
+ "&:hover": {
338
+ "background_color": color("accent", 4),
339
+ },
340
+ "& > .AccordionChevron": {
341
+ "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms {cubic_bezier}",
342
+ },
343
+ "&[data-variant='classic']": {
344
+ "color": color("accent", 12),
345
+ "box_shadow": color("accent", 11),
346
+ "&:hover": {
347
+ "background_color": color("accent", 10),
348
+ },
349
+ "& > .AccordionChevron": {
350
+ "color": color("accent", 12),
351
+ "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms {cubic_bezier}",
352
+ },
353
+ },
354
+ }
355
+ )
595
356
 
596
357
 
597
358
  class AccordionIcon(Icon):
@@ -623,6 +384,14 @@ class AccordionContent(AccordionComponent):
623
384
 
624
385
  alias = "RadixAccordionContent"
625
386
 
387
+ def add_imports(self) -> imports.ImportDict:
388
+ """Add imports to the component.
389
+
390
+ Returns:
391
+ The imports of the component.
392
+ """
393
+ return {"@emotion/react": [imports.ImportVar(tag="keyframes")]}
394
+
626
395
  @classmethod
627
396
  def create(cls, *children, **props) -> Component:
628
397
  """Create the Accordion content component.
@@ -641,14 +410,66 @@ class AccordionContent(AccordionComponent):
641
410
 
642
411
  return super().create(*children, class_name=cls_name, **props)
643
412
 
644
- def _apply_theme(self, theme: Component):
645
- self.style = Style({**self.style})
413
+ def add_custom_code(self) -> list[str]:
414
+ """Add custom code to the component.
646
415
 
647
- # def _get_imports(self):
648
- # return {
649
- # **super()._get_imports(),
650
- # "@emotion/react": [imports.ImportVar(tag="keyframes")],
651
- # }
416
+ Returns:
417
+ The custom code of the component.
418
+ """
419
+ return [
420
+ """
421
+ const slideDown = keyframes`
422
+ from {
423
+ height: 0;
424
+ }
425
+ to {
426
+ height: var(--radix-accordion-content-height);
427
+ }
428
+ `
429
+ const slideUp = keyframes`
430
+ from {
431
+ height: var(--radix-accordion-content-height);
432
+ }
433
+ to {
434
+ height: 0;
435
+ }
436
+ `
437
+ """
438
+ ]
439
+
440
+ def add_style(self) -> Style | None:
441
+ """Add style to the component.
442
+
443
+ Returns:
444
+ The style of the component.
445
+ """
446
+ slideDown = Var.create(
447
+ f"${{slideDown}} {DEFAULT_ANIMATION_DURATION}ms {cubic_bezier}",
448
+ _var_is_string=True,
449
+ )
450
+
451
+ slideUp = Var.create(
452
+ f"${{slideUp}} {DEFAULT_ANIMATION_DURATION}ms {cubic_bezier}",
453
+ _var_is_string=True,
454
+ )
455
+
456
+ return Style(
457
+ {
458
+ "overflow": "hidden",
459
+ "font_size": "10px",
460
+ "color": color("accent", 11),
461
+ "background_color": color("accent", 3),
462
+ "padding": "0 15px",
463
+ "&[data-state='open']": {"animation": slideDown},
464
+ "&[data-state='closed']": {"animation": slideUp},
465
+ "&[data-variant='classic']": {
466
+ "color": color("accent", 12),
467
+ "background_color": color("accent", 9),
468
+ },
469
+ "&[data-variant='outline']": {"background_color": "transparent"},
470
+ "&[data-variant='ghost']": {"background_color": "transparent"},
471
+ }
472
+ )
652
473
 
653
474
 
654
475
  class Accordion(ComponentNamespace):