reflex icon indicating copy to clipboard operation
reflex copied to clipboard

Implement raw HTML elements

Open kbrgl opened this issue 2 years ago • 0 comments

This PR adds raw HTML elements under the pynecone.el namespace that can be used in conjunction with class_name and stylesheets to support Tailwind and other custom workflows. (Support for stylesheets is not included in this PR, I’ll make a separate PR for that.)

The following is now possible:

from pynecone import el

def index():
    return el.div(
        el.div(
            el.h1("Welcome to Pynecone!", style={"font_size": "2em"}),
            el.div(
                "Get started by editing ",
                pc.code(filename, style={"font_size": "1em"}),
            ),
            el.a(
                "Check out our docs!",
                href=docs_url,
                style={
                    "color": "rgb(107,99,246)",
                    "border": "0.1em solid",
                    "padding": "0.5em",
                    "border_radius": "0.5em",
                    "display": "inline-block",
                },
            ),
            style={
                "font_size": "2em",
                "display": "flex",
                "flex_direction": "column",
                "align_items": "center",
            },
        ),
        style={
            "padding_top": "10%",
            "display": "flex",
            "justify_content": "center",
        },
    )

This PR contributes the following files under pynecone/el/:

element.py

Subclasses Component in order to remove the Chakra sx prop from the render. sx has been replaced with the raw style prop, meaning when you say something like

el.div(style={"font_size": "1em"})

It is compiled to:

<div style={{fontSize: '1em'}} />

constants.py

This file contains constants that are used in generating base elements: 1. ELEMENTS: A list of all valid HTML elements (including deprecated and obsolete ones) from MDN. 2. ATTR_TO_ELEMENTS: A dict mapping HTML attributes to all the elements that can possess those attributes. (e.g. "autofocus": ["button", "input", ...]) 3. PROP_TO_ELEMENTS (derived from ATTR_TO_ELEMENTS): A dict mapping Pynecone props (e.g. auto_focus) to the elements which can possess them. 4. _POSSIBLE_STANDARD_NAMES: Used internally to go from HTML attribute names to their React versions. 5. ELEMENT_TO_PROPS: This is just PROP_TO_ELEMENTS inverted; maps elements to the props that they can legally possess.

generate.py

This is the main compilation script. It's pretty short, so just read the source code. TL;DR, it uses a simple template to generate a subclass of Element for each element in ELEMENT_TO_PROPS, and outputs all the generated code to elements/__init__.py.

elements/__init__.py

Contains all the generated elements. Should not need manual review, just skim if necessary.

Design Decisions

  1. The Element subclass for the <del /> element is called Del, but it's used as el.del_ since del (lowercase) is a reserved keyword. I could have made the subclass name Del_, but I don't think that makes sense since reserved keywords are case-sensitive and Del works fine. This way, as a rule of thumb, you can assume that if something in the API resembles a keyword, you just need to append an underscore (with the exception of the class prop, which is used as class_name).
  2. async is a reserved keyword; the async_ prop is used instead.
  3. Code for all elements is output to a single generated file (pynecone/el/elements/__init__.py) rather than multiple files (pynecone/els/elements/a.py, pynecone/els/elements/abbr.py, etc.) because we don't want to manually edit the generated code. The generated file contains a "Do not edit" warning to this effect.

Misc.

All Submissions:

  • [x] Have you followed the guidelines stated in CONTRIBUTING.md file?
  • [x] Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • [x] This change requires a documentation update

New Feature Submission:

  • [ ] Does your submission pass the tests?
  • [ ] Have you linted your code locally prior to submission?

Changes To Core Features:

  • [x] Have you added an explanation of what your changes do and why you'd like us to include them?
  • [ ] Have you written new tests for your core changes, as applicable?
  • [ ] Have you successfully ran tests with your changes locally?

kbrgl avatar Mar 03 '23 20:03 kbrgl