In the previous post, we covered the basics of building Mendix Studio Pro extensions. Now let's make them look professional by styling them to match Studio Pro's design system.

Why Styling Matters

A well-styled extension:

  • Feels native - Users won't notice it's a third-party extension
  • Improves usability - Consistent UI patterns are easier to understand
  • Looks professional - Good design builds trust in your tool

Understanding Studio Pro's Design Language

Mendix Studio Pro uses a modern, clean design with:

  • Neutral color palette - Grays and whites for backgrounds
  • Blue accents - Primary actions and highlights
  • Clear typography - Readable fonts with proper hierarchy
  • Consistent spacing - Predictable padding and margins

Setting Up Your Styles

Create a styles.css file in your extension folder:

:root {
    --mx-primary: #0595DB;
    --mx-primary-hover: #0476B3;
    --mx-background: #FFFFFF;
    --mx-background-secondary: #F7F7F7;
    --mx-text-primary: #252525;
    --mx-text-secondary: #6C6C6C;
    --mx-border: #D7D7D7;
    --mx-success: #76C442;
    --mx-warning: #F99B1C;
    --mx-error: #E33F4E;
}

body {
    font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-size: 14px;
    color: var(--mx-text-primary);
    background-color: var(--mx-background);
    margin: 0;
    padding: 16px;
}

Common UI Components

Buttons

Create buttons that match Studio Pro's style:

.mx-button {
    padding: 8px 16px;
    background-color: var(--mx-primary);
    color: white;
    border: none;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.2s;
}

.mx-button:hover {
    background-color: var(--mx-primary-hover);
}

.mx-button-secondary {
    background-color: transparent;
    color: var(--mx-primary);
    border: 1px solid var(--mx-border);
}

.mx-button-secondary:hover {
    background-color: var(--mx-background-secondary);
}

Input Fields

.mx-input {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--mx-border);
    border-radius: 4px;
    font-size: 14px;
    font-family: inherit;
    transition: border-color 0.2s;
}

.mx-input:focus {
    outline: none;
    border-color: var(--mx-primary);
    box-shadow: 0 0 0 3px rgba(5, 149, 219, 0.1);
}

Cards and Panels

.mx-card {
    background-color: var(--mx-background);
    border: 1px solid var(--mx-border);
    border-radius: 4px;
    padding: 16px;
    margin-bottom: 16px;
}

.mx-card-header {
    font-size: 16px;
    font-weight: 600;
    margin-bottom: 12px;
    color: var(--mx-text-primary);
}

Building a Styled Extension

Here's a complete example of a styled extension:

<!DOCTYPE html>
<html>
<head>
    <title>Entity Creator</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="mx-card">
        <div class="mx-card-header">Create New Entity</div>
        
        <div class="mx-form-group">
            <label class="mx-label">Entity Name</label>
            <input type="text" class="mx-input" id="entityName" placeholder="Enter entity name">
        </div>
        
        <div class="mx-form-group">
            <label class="mx-label">Module</label>
            <select class="mx-input" id="moduleSelect">
                <option>Select a module...</option>
            </select>
        </div>
        
        <div class="mx-button-group">
            <button class="mx-button" onclick="createEntity()">Create Entity</button>
            <button class="mx-button-secondary" onclick="cancel()">Cancel</button>
        </div>
    </div>
    
    <script type="module" src="main.js"></script>
</body>
</html>

Responsive Design

Make your extension work at different sizes:

.mx-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 16px;
}

@media (max-width: 600px) {
    body {
        padding: 8px;
    }
    
    .mx-card {
        padding: 12px;
    }
}

Icons and Visual Feedback

Use icons to enhance usability:

.mx-icon {
    width: 16px;
    height: 16px;
    display: inline-block;
    vertical-align: middle;
    margin-right: 4px;
}

.mx-loading {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid var(--mx-border);
    border-top-color: var(--mx-primary);
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

Dark Mode Support

Consider adding dark mode support:

@media (prefers-color-scheme: dark) {
    :root {
        --mx-background: #1E1E1E;
        --mx-background-secondary: #2D2D2D;
        --mx-text-primary: #E0E0E0;
        --mx-text-secondary: #A0A0A0;
        --mx-border: #3D3D3D;
    }
}

Best Practices

  • Use CSS variables - Makes theming and updates easier
  • Keep it simple - Don't over-design; match Studio Pro's minimalist approach
  • Test at different sizes - Extensions can be resized by users
  • Provide visual feedback - Show loading states, success/error messages
  • Use consistent spacing - Stick to 4px, 8px, 12px, 16px increments

What's Next?

With a beautifully styled extension, you're ready to tackle more advanced functionality. In the next post, we'll explore using proxies to retrieve and work with data in your extensions, enabling powerful data-driven tools.