Skip to content

Update some reflex ui components#6311

Merged
carlosabadia merged 2 commits intomainfrom
carlos/update-reflex-ui-styles
Apr 9, 2026
Merged

Update some reflex ui components#6311
carlosabadia merged 2 commits intomainfrom
carlos/update-reflex-ui-styles

Conversation

@carlosabadia
Copy link
Copy Markdown
Contributor

No description provided.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 9, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing carlos/update-reflex-ui-styles (2c982c5) with main (08ee62a)

Open in CodSpeed

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 9, 2026

Greptile Summary

This PR updates several reflex-ui components — Button, Input, Tabs, Textarea — adding size variants, loading states, clear buttons, and icon support, alongside CSS design-token updates in globals.css. Three bugs in input.py and one in button.py need attention before merging:

  • input.py line 23: lg size uses rounded-lg instead of rounded-ui-lg, breaking the design-token system.
  • input.py lines 147–151: user-supplied custom_attrs are silently dropped because custom_attrs is not in _el_input_props, so the merge always produces only DEFAULT_INPUT_ATTRS.
  • input.py line 163: show_clear_button typed as Var[bool] but checked with a Python if, so a Var is always truthy and the clear button can never be hidden dynamically.
  • button.py line 90–91: validate_variant / validate_size raise ValueError (and line 99 raises KeyError) when variant/size are Var objects, despite the class declaring them as Var[Literal[...]].

Confidence Score: 4/5

Safe to merge after fixing the four P1 bugs in input.py and button.py.

Four P1 issues are present: a wrong Tailwind class in the lg size variant, silently dropped user custom_attrs, a Var-incompatible Python conditional for show_clear_button, and validation logic that throws on Var inputs for button variant/size. These produce incorrect visual output and runtime errors on valid usage patterns.

packages/reflex-ui/src/reflex_ui/components/base/input.py and packages/reflex-ui/src/reflex_ui/components/base/button.py require fixes before merging.

Vulnerabilities

No security concerns identified.

Important Files Changed

Filename Overview
packages/reflex-ui/src/reflex_ui/components/base/button.py Adds loading state, variant/size validation, and ClassNames namespace; validate_variant/validate_size will fail at runtime if a Var is passed for variant or size.
packages/reflex-ui/src/reflex_ui/components/base/input.py Introduces HighLevelInput wrapper with icon, clear button, and size variants; has three bugs: rounded-lg inconsistency for lg size, user custom_attrs silently dropped, and show_clear_button Var not handled correctly.
packages/reflex-ui/src/reflex_ui/components/base/tabs.py Adds size-aware tabs components (Root, List, Tab, Indicator, Panel) with ClassNames; list and indicator sizes share identical class strings across sm/md/lg which may be intentional.
packages/reflex-ui/src/reflex_ui/components/base/textarea.py Simple textarea wrapper with auto-attribute defaults and design-token class names; no issues found.
packages/reflex-ui-shared/src/reflex_ui_shared/styles/globals.css CSS design-token file defining color palette, shadow, font, and radius variables; no logic issues identified.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["HighLevelInput.create()"] --> B["Extract _el_input_props from props"]
    B --> C["Pop icon, size, id, class_name,\nshow_clear_button, clear_events"]
    C --> D["Build input_props with id +\ncustom_attrs (DEFAULT_INPUT_ATTRS only)"]
    D --> E["Div.create()"]
    E --> F{icon?}
    F -->|yes| G["Span + hi(icon)"]
    F -->|no| H["(None)"]
    G --> I["InputRoot.create(**input_props)"]
    H --> I
    I --> J{show_clear_button?\nPython truthiness only}
    J -->|bool True| K["_create_clear_button(id, clear_events)"]
    J -->|bool False| L["(None)"]
    J -->|Var - always True| K
    K --> M["Button with set_value + set_focus"]
Loading

Comments Outside Diff (4)

  1. packages/reflex-ui/src/reflex_ui/components/base/input.py, line 23 (link)

    P1 Inconsistent border-radius class for lg size

    The lg size uses rounded-lg (a standard Tailwind class) while every other size — xs, sm, md, and xl — uses the project's custom rounded-ui-* scale. This will produce a visually different corner radius for lg inputs, breaking the design-token system.

  2. packages/reflex-ui/src/reflex_ui/components/base/input.py, line 147-151 (link)

    P1 User-provided custom_attrs silently dropped

    custom_attrs is not in _el_input_props, so it is never moved into input_props by the dict-comprehension on line 135. input_props.get("custom_attrs", {}) therefore always returns {}, and any custom_attrs kwarg the caller passes is left in props, applied to the outer Div instead of the InputRoot. The intent is clearly to merge caller-supplied HTML attributes into the input element, but the current code silently discards them.

    To fix this, extract custom_attrs from props before (or alongside) the _el_input_props filtering:

            custom_attrs_override = props.pop("custom_attrs", {})
            input_props.update({
                "id": id,
                "custom_attrs": {
                    **DEFAULT_INPUT_ATTRS,
                    **custom_attrs_override,
                },
            })
  3. packages/reflex-ui/src/reflex_ui/components/base/input.py, line 163 (link)

    P1 show_clear_button as a Var is always truthy

    show_clear_button is typed as Var[bool], but the Python-level conditional if show_clear_button evaluates the truthiness of the Var object itself, which is always True. Passing show_clear_button=rx.State.hide_clear (a Var) will always render the clear button regardless of the state value. If dynamic hiding is not a supported use-case, update the type annotation to bool; if it should be supported, use cond() to conditionally render the button at the React level.

  4. packages/reflex-ui/src/reflex_ui/components/base/button.py, line 90-91 (link)

    P1 validate_variant fails when variant is a Var

    The class declares variant: Var[LiteralButtonVariant], which implies callers can pass a reactive Var. However, validate_variant checks if variant not in BUTTON_VARIANTS["variant"] — a Var object will never be a key in that dict, so validation raises ValueError for any dynamic variant. Similarly, line 99 does BUTTON_VARIANTS['variant'][variant], which would raise KeyError. Either restrict the type annotation to LiteralButtonVariant (plain string only) or guard the validation path with if not isinstance(variant, Var).

Reviews (1): Last reviewed commit: "Update some reflex ui components" | Re-trigger Greptile

@carlosabadia carlosabadia merged commit 8f407f9 into main Apr 9, 2026
55 of 56 checks passed
@carlosabadia carlosabadia deleted the carlos/update-reflex-ui-styles branch April 9, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants