Thinking in Aurora

Aurora redefines UI development, adopting a component-based approach. Break designs into components, define states, and behaviors, then seamlessly connect components for data flow. Create intuitive in

Step 1: Define the JSON API and Mockup

Assuming we have a JSON API returning product data like this:

jsonCopy code[
  { "category": "Fruits", "price": "$1", "stocked": true, "name": "Apple" },
  { "category": "Fruits", "price": "$1", "stocked": true, "name": "Dragonfruit" },
  { "category": "Fruits", "price": "$2", "stocked": false, "name": "Passionfruit" },
  { "category": "Vegetables", "price": "$2", "stocked": true, "name": "Spinach" },
  { "category": "Vegetables", "price": "$4", "stocked": false, "name": "Pumpkin" },
  { "category": "Vegetables", "price": "$1", "stocked": true, "name": "Peas" }
]

And a mockup representing the UI:

[Mockup Image]

Step 2: Break Down the UI into Components

We'll identify the following components based on the mockup:

  1. FilterableProductTable: Main container for the app.

  2. SearchBar: Component to receive user input for searching.

  3. ProductTable: Component to display and filter the product list.

  4. ProductCategoryRow: Component to display category headings.

  5. ProductRow: Component to display individual product rows.

Step 3: Build a Static Version

We'll start by building a static version of the app without interactivity. We'll focus on reusability and passing data through props.

pythonCopy code# Define ProductCategoryRow component
component ProductCategoryRow:
    def __init__(self, category):
        self.category = category
    
    def render(self):
        return f"<tr><th colspan='2'>{self.category}</th></tr>"

# Define ProductRow component
component ProductRow:
    def __init__(self, product):
        self.product = product
    
    def render(self):
        name = f"<span style='color: red'>{self.product['name']}</span>" if not self.product['stocked'] else self.product['name']
        return f"<tr><td>{name}</td><td>{self.product['price']}</td></tr>"

# Define ProductTable component
component ProductTable:
    def __init__(self, products):
        self.products = products
    
    def render(self):
        rows = []
        last_category = None
        
        for product in self.products:
            if product['category'] != last_category:
                rows.append(ProductCategoryRow(product['category']).render())
                last_category = product['category']
            rows.append(ProductRow(product).render())
        
        return "<table>" + "".join(rows) + "</table>"

# Define FilterableProductTable component
component FilterableProductTable:
    def __init__(self, products):
        self.products = products
    
    def render(self):
        return f"<div><SearchBar/><ProductTable products={self.products}/></div>"

Step 4: Manage State

Identify the minimal but complete representation of UI state. In this case, it includes the search text and the value of the checkbox.

pythonCopy code# Define FilterableProductTable component with state
component FilterableProductTable:
    def __init__(self, products):
        self.products = products
        self.state = {
            'filterText': '',
            'inStockOnly': False
        }
    
    def render(self):
        return f"""
            <div>
                <SearchBar 
                    filterText={self.state['filterText']} 
                    inStockOnly={self.state['inStockOnly']} 
                    onFilterTextChange={self.handleFilterTextChange}
                    onInStockOnlyChange={self.handleInStockOnlyChange} 
                />
                <ProductTable 
                    products={self.products} 
                    filterText={self.state['filterText']} 
                    inStockOnly={self.state['inStockOnly']} 
                />
            </div>
        """

    # Define event handlers for updating state
    def handleFilterTextChange(self, new_filter_text):
        self.state['filterText'] = new_filter_text
    
    def handleInStockOnlyChange(self, new_value):
        self.state['inStockOnly'] = new_value

Step 5: Add Interactivity

Now, add inverse data flow to update the state based on user input.

pythonCopy code# Define SearchBar component
component SearchBar:
    def __init__(self, filterText='', inStockOnly=False, onFilterTextChange=None, onInStockOnlyChange=None):
        self.filterText = filterText
        self.inStockOnly = inStockOnly
        self.onFilterTextChange = onFilterTextChange
        self.onInStockOnlyChange = onInStockOnlyChange
    
    def render(self):
        return f"""
            <form>
                <input 
                    type='text' 
                    value='{self.filterText}' 
                    placeholder='Search...'
                    onchange='{self.handleFilterTextChange}' 
                />
                <label>
                    <input 
                        type='checkbox' 
                        checked='{self.inStockOnly}' 
                        onchange='{self.handleInStockOnlyChange}' 
                    />
                    Only show products in stock
                </label>
            </form>
        """
    
    # Define event handlers for updating state
    def handleFilterTextChange(self, event):
        self.onFilterTextChange(event.target.value)
    
    def handleInStockOnlyChange(self, event):
        self.onInStockOnlyChange(event.target.checked)

Now, you have a fully functional searchable product data table in Aurora! You can further enhance this implementation with styling and additional features as needed. Happy coding! 🚀

Last updated