Skip to content

JSX Elements#

Code Example

Runnable Example in Jac and JacLib

# JSX Elements with Contextual Lexing
# Demonstrates various JSX features supported in Jac

# Simple component function that returns JSX
def Button(text: str, onclick: str) -> dict {
    return <button
        onclick={onclick}
    >
        {text}
    </button>;
}

# Component with multiple props
def Card(
    title: str, content: str, className: str
) -> dict {
    return (
        <div
            class={className}
        >
            <h2>
                {title}
            </h2>
            <p>
                {content}
            </p>
        </div>
    );
}

with entry {
    # 1. Basic HTML element with text
    let basic_element = <div>
        Hello World
    </div>;
    print("Basic element:", basic_element);

    # 2. Element with attributes
    let with_attrs = <div
        class="container"
        id="main"
    >
        Content
    </div>;
    print("With attributes:", with_attrs);

    # 3. Self-closing element
    let self_closing = <img
        src="image.jpg"
        alt="Description"
    />;
    print("Self-closing:", self_closing);

    # 4. Nested elements
    let nested = (
        <div>
            <h1>
                Title
            </h1>
            <p>
                Paragraph text
            </p>
        </div>
    );
    print("Nested elements:", nested);

    # 5. Elements with expression attributes
    let name = "user123";
    let age = 25;
    let user_element = <div
        id={name}
        data-age={age}
    >
        User Info
    </div>;
    print("Expression attributes:", user_element);

    # 6. Elements with expression children
    let count = 42;
    let with_expr_child = <div>
        Count: {count}
    </div>;
    print("Expression children:", with_expr_child);

    # 7. Component usage (capitalized names)
    let button = <Button
        text="Click Me"
        onclick="handleClick()"
    />;
    print("Component:", button);

    # 8. Spread attributes
    let props = {"class": "btn", "type": "submit"};
    let with_spread = <button
        {...props}
    >
        Submit
    </button>;
    print("Spread attributes:", with_spread);

    # 9. Mixed attributes and spread
    let base_props = {"class": "card"};
    let card = <Card
        {...base_props}
        title="Welcome"
        content="Hello!"
        className="custom"
    />;
    print("Mixed spread:", card);

    # 10. Complex nested structure
    let app = (
        <div class="app">
            <header>
                <h1>
                    My App
                </h1>
                <nav>
                    <a href="/home">
                        Home
                    </a>
                    <a href="/about">
                        About
                    </a>
                </nav>
            </header>
            <main>
                <Card
                    title="Card 1"
                    content="First card"
                    className="card-primary"
                />
                <Card
                    title="Card 2"
                    content="Second card"
                    className="card-secondary"
                />
            </main>
            <footer>
                <p>
                    Footer text
                </p>
            </footer>
        </div>
    );
    print("Complex structure:", app);

    # 11. Fragment (no tag name)
    let fragment = (
        <>
            <div>
                First
            </div>
            <div>
                Second
            </div>
        </>
    );
    print("Fragment:", fragment);

    # 12. Dynamic list rendering
    let items = ["Apple", "Banana", "Cherry"];
    let list_items = [
        (
            <li
                key={i}
            >
                {item}
            </li>
        ) for (i, item) in enumerate(items)
    ];
    let list_element = <ul>
        {list_items}
    </ul>;
    print("Dynamic list:", list_element);

    # 13. Conditional rendering with expressions
    let is_logged_in = True;
    let user_name = "Alice";
    let greeting = <div>
        {f"Welcome, {user_name}!" if is_logged_in else "Please log in"}
    </div>;
    print("Conditional:", greeting);

    print("\nAll JSX examples completed successfully!");
}
# JSX Elements with Contextual Lexing
# Demonstrates various JSX features supported in Jac

# Simple component function that returns JSX
def Button(text: str, onclick: str) -> dict {
    return <button
        onclick={onclick}
    >
        {text}
    </button>;
}

# Component with multiple props
def Card(
    title: str, content: str, className: str
) -> dict {
    return (
        <div
            class={className}
        >
            <h2>
                {title}
            </h2>
            <p>
                {content}
            </p>
        </div>
    );
}

with entry {
    # 1. Basic HTML element with text
    let basic_element = <div>
        Hello World
    </div>;
    print("Basic element:", basic_element);

    # 2. Element with attributes
    let with_attrs = <div
        class="container"
        id="main"
    >
        Content
    </div>;
    print("With attributes:", with_attrs);

    # 3. Self-closing element
    let self_closing = <img
        src="image.jpg"
        alt="Description"
    />;
    print("Self-closing:", self_closing);

    # 4. Nested elements
    let nested = (
        <div>
            <h1>
                Title
            </h1>
            <p>
                Paragraph text
            </p>
        </div>
    );
    print("Nested elements:", nested);

    # 5. Elements with expression attributes
    let name = "user123";
    let age = 25;
    let user_element = <div
        id={name}
        data-age={age}
    >
        User Info
    </div>;
    print("Expression attributes:", user_element);

    # 6. Elements with expression children
    let count = 42;
    let with_expr_child = <div>
        Count: {count}
    </div>;
    print("Expression children:", with_expr_child);

    # 7. Component usage (capitalized names)
    let button = <Button
        text="Click Me"
        onclick="handleClick()"
    />;
    print("Component:", button);

    # 8. Spread attributes
    let props = {"class": "btn", "type": "submit"};
    let with_spread = <button
        {...props}
    >
        Submit
    </button>;
    print("Spread attributes:", with_spread);

    # 9. Mixed attributes and spread
    let base_props = {"class": "card"};
    let card = <Card
        {...base_props}
        title="Welcome"
        content="Hello!"
        className="custom"
    />;
    print("Mixed spread:", card);

    # 10. Complex nested structure
    let app = (
        <div class="app">
            <header>
                <h1>
                    My App
                </h1>
                <nav>
                    <a href="/home">
                        Home
                    </a>
                    <a href="/about">
                        About
                    </a>
                </nav>
            </header>
            <main>
                <Card
                    title="Card 1"
                    content="First card"
                    className="card-primary"
                />
                <Card
                    title="Card 2"
                    content="Second card"
                    className="card-secondary"
                />
            </main>
            <footer>
                <p>
                    Footer text
                </p>
            </footer>
        </div>
    );
    print("Complex structure:", app);

    # 11. Fragment (no tag name)
    let fragment = (
        <>
            <div>
                First
            </div>
            <div>
                Second
            </div>
        </>
    );
    print("Fragment:", fragment);

    # 12. Dynamic list rendering
    let items = ["Apple", "Banana", "Cherry"];
    let list_items = [
        (
            <li
                key={i}
            >
                {item}
            </li>
        ) for (i, item) in enumerate(items)
    ];
    let list_element = <ul>
        {list_items}
    </ul>;
    print("Dynamic list:", list_element);

    # 13. Conditional rendering with expressions
    let is_logged_in = True;
    let user_name = "Alice";
    let greeting = <div>
        {f"Welcome, {user_name}!" if is_logged_in else "Please log in"}
    </div>;
    print("Conditional:", greeting);

    print("\nAll JSX examples completed successfully!");
}
from __future__ import annotations
from jaclang.lib import jsx


def Button(text: str, onclick: str) -> dict:
    return jsx("button", {"onclick": onclick}, [text])


def Card(title: str, content: str, className: str) -> dict:
    return jsx("div", {"class": className}, [jsx("h2", {}, [title]), jsx("p", {}, [content])])


basic_element = jsx("div", {}, ["Hello World"])
print("Basic element:", basic_element)
with_attrs = jsx("div", {"class": "container", "id": "main"}, ["Content"])
print("With attributes:", with_attrs)
self_closing = jsx("img", {"src": "image.jpg", "alt": "Description"}, [])
print("Self-closing:", self_closing)
nested = jsx("div", {}, [jsx("h1", {}, ["Title"]), jsx("p", {}, ["Paragraph text"])])
print("Nested elements:", nested)
name = "user123"
age = 25
user_element = jsx("div", {"id": name, "data-age": age}, ["User Info"])
print("Expression attributes:", user_element)
count = 42
with_expr_child = jsx("div", {}, ["Count: ", count])
print("Expression children:", with_expr_child)
button = jsx(Button, {"text": "Click Me", "onclick": "handleClick()"}, [])
print("Component:", button)
props = {"class": "btn", "type": "submit"}
with_spread = jsx("button", {**{}, **props}, ["Submit"])
print("Spread attributes:", with_spread)
base_props = {"class": "card"}
card = jsx(
    Card,
    {
        **{**{**{**{}, **base_props}, "title": "Welcome"}, "content": "Hello!"},
        "className": "custom",
    },
    [],
)
print("Mixed spread:", card)
app = jsx(
    "div",
    {"class": "app"},
    [
        jsx(
            "header",
            {},
            [
                jsx("h1", {}, ["My App"]),
                jsx(
                    "nav",
                    {},
                    [
                        jsx("a", {"href": "/home"}, ["Home"]),
                        jsx("a", {"href": "/about"}, ["About"]),
                    ],
                ),
            ],
        ),
        jsx(
            "main",
            {},
            [
                jsx(
                    Card,
                    {
                        "title": "Card 1",
                        "content": "First card",
                        "className": "card-primary",
                    },
                    [],
                ),
                jsx(
                    Card,
                    {
                        "title": "Card 2",
                        "content": "Second card",
                        "className": "card-secondary",
                    },
                    [],
                ),
            ],
        ),
        jsx("footer", {}, [jsx("p", {}, ["Footer text"])]),
    ],
)
print("Complex structure:", app)
fragment = jsx(None, {}, [jsx("div", {}, ["First"]), jsx("div", {}, ["Second"])])
print("Fragment:", fragment)
items = ["Apple", "Banana", "Cherry"]
list_items = [jsx("li", {"key": i}, [item]) for i, item in enumerate(items)]
list_element = jsx("ul", {}, [list_items])
print("Dynamic list:", list_element)
is_logged_in = True
user_name = "Alice"
greeting = jsx("div", {}, [f"Welcome, {user_name}!" if is_logged_in else "Please log in"])
print("Conditional:", greeting)
print("\nAll JSX examples completed successfully!")
Jac Grammar Snippet
jsx_element: jsx_self_closing
           | jsx_fragment
           | jsx_opening_closing

jsx_self_closing: JSX_OPEN_START jsx_element_name jsx_attributes? JSX_SELF_CLOSE
jsx_opening_closing: jsx_opening_element jsx_children? jsx_closing_element
jsx_fragment: JSX_FRAG_OPEN jsx_children? JSX_FRAG_CLOSE

jsx_opening_element: JSX_OPEN_START jsx_element_name jsx_attributes? JSX_TAG_END
jsx_closing_element: JSX_CLOSE_START jsx_element_name JSX_TAG_END

jsx_element_name: JSX_NAME (DOT JSX_NAME)*

jsx_attributes: jsx_attribute+
jsx_attribute: jsx_spread_attribute | jsx_normal_attribute

jsx_spread_attribute: LBRACE ELLIPSIS expression RBRACE
jsx_normal_attribute: JSX_NAME (EQ jsx_attr_value)?

jsx_attr_value: STRING
              | LBRACE expression RBRACE

jsx_children: jsx_child+
jsx_child: jsx_element
         | jsx_expression
         | jsx_text

jsx_expression: LBRACE expression RBRACE
jsx_text: JSX_TEXT
        | jsx_text_keyword

// Keywords that can appear as text in JSX content (common English words)
jsx_text_keyword: KW_TO | KW_AS | KW_FROM | KW_WITH | KW_IF | KW_FOR | KW_BY
                | KW_IN | KW_IS | KW_HAS | KW_CAN | KW_TRY | KW_MATCH | KW_CASE
                | KW_TEST | KW_LET | KW_ELSE | KW_RETURN | KW_BREAK | KW_CLASS
                | KW_NODE | KW_EDGE | KW_VISIT | KW_ENTRY | KW_EXIT | KW_WAIT
                | KW_FLOW | KW_SKIP | KW_CONTINUE | KW_REPORT | KW_RAISE
                | KW_DEFAULT | KW_YIELD | KW_EXCEPT | KW_FINALLY | KW_ASSERT
                | KW_WHILE | KW_STATIC | KW_OVERRIDE | KW_SWITCH | KW_HERE
                | KW_SELF | KW_SUPER | KW_ROOT | NOT | KW_DELETE | KW_IMPORT
                | KW_INCLUDE | KW_ASYNC | KW_AWAIT | KW_SPAWN | KW_LAMBDA
                | KW_ENUM | KW_OBJECT | KW_ABSTRACT | KW_WALKER | KW_IMPL
                | KW_SEM | KW_ELIF | KW_DISENGAGE | KW_PRIV | KW_PUB | KW_PROT
                | KW_GLOBAL | KW_DEF | KW_CLIENT | KW_INIT | KW_POST_INIT
                | KW_VISITOR | KW_AND | KW_OR

Description

JSX elements with contextual lexing allow embedding HTML-like syntax within Jac code.

Basic JSX Elements

JSX (JavaScript XML) syntax in Jac enables writing UI elements in a familiar HTML-like format. The lexer uses contextual lexing to switch between regular Jac syntax and JSX syntax seamlessly.

Key Features

  • Self-closing tags: <Component />
  • Nested elements: <Parent><Child /></Parent>
  • Attributes with values: <div prop="value" />
  • Dynamic content interpolation

This feature enables more expressive and readable code when working with UI components or templating.