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>
    );
}

# 1. Basic HTML element with text
glob basic_element = <div>
         Hello World
     </div>;

with entry {
    print("Basic element:", basic_element);
}

# 2. Element with attributes
glob with_attrs = <div
         class="container"
         id="main"
     >
         Content
     </div>;

with entry {
    print("With attributes:", with_attrs);
}

# 3. Self-closing element
glob self_closing = <img
         src="image.jpg"
         alt="Description"
     />;

with entry {
    print("Self-closing:", self_closing);
}

# 4. Nested elements
glob nested = (
         <div>
             <h1>
                 Title
             </h1>
             <p>
                 Paragraph text
             </p>
         </div>
     );

with entry {
    print("Nested elements:", nested);
}

# 5. Elements with expression attributes
glob name = "user123",
     age = 25,
     user_element = <div
         id={name}
         data-age={age}
     >
         User Info
     </div>;

with entry {
    print("Expression attributes:", user_element);
}

# 6. Elements with expression children
glob count = 42,
     with_expr_child = <div>
         Count: {count}
     </div>;

with entry {
    print("Expression children:", with_expr_child);
}

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

with entry {
    print("Component:", button);
}

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

with entry {
    print("Spread attributes:", with_spread);
}

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

with entry {
    print("Mixed spread:", card);
}

# 10. Complex nested structure
glob 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>
     );

with entry {
    print("Complex structure:", app);
}

# 11. Fragment (no tag name)
glob fragment = (
         <>
             <div>
                 First
             </div>
             <div>
                 Second
             </div>
         </>
     );

with entry {
    print("Fragment:", fragment);
}

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

with entry {
    print("Dynamic list:", list_element);
}

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

with entry {
    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>
    );
}

# 1. Basic HTML element with text
glob basic_element = <div>
         Hello World
     </div>;

with entry {
    print("Basic element:", basic_element);
}

# 2. Element with attributes
glob with_attrs = <div
         class="container"
         id="main"
     >
         Content
     </div>;

with entry {
    print("With attributes:", with_attrs);
}

# 3. Self-closing element
glob self_closing = <img
         src="image.jpg"
         alt="Description"
     />;

with entry {
    print("Self-closing:", self_closing);
}

# 4. Nested elements
glob nested = (
         <div>
             <h1>
                 Title
             </h1>
             <p>
                 Paragraph text
             </p>
         </div>
     );

with entry {
    print("Nested elements:", nested);
}

# 5. Elements with expression attributes
glob name = "user123",
     age = 25,
     user_element = <div
         id={name}
         data-age={age}
     >
         User Info
     </div>;

with entry {
    print("Expression attributes:", user_element);
}

# 6. Elements with expression children
glob count = 42,
     with_expr_child = <div>
         Count: {count}
     </div>;

with entry {
    print("Expression children:", with_expr_child);
}

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

with entry {
    print("Component:", button);
}

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

with entry {
    print("Spread attributes:", with_spread);
}

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

with entry {
    print("Mixed spread:", card);
}

# 10. Complex nested structure
glob 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>
     );

with entry {
    print("Complex structure:", app);
}

# 11. Fragment (no tag name)
glob fragment = (
         <>
             <div>
                 First
             </div>
             <div>
                 Second
             </div>
         </>
     );

with entry {
    print("Fragment:", fragment);
}

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

with entry {
    print("Dynamic list:", list_element);
}

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

with entry {
    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_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_PROPS | 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.