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

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.