What is nice about Juris, it is that it's just Javascript. Juris is all based on Javascript objects.
So AI have no problems to handle the Juris code.
I asked Claude to enhance my TrafficLights example.
The result is pretty nice, and very legible. Nothing tricky.
Beware 'bss' have nothing to do with Juris, it is just a simple and handy CssInJS library I used when developping with Mithril my first beloved library .
Sorry Mithril, I am in Juris now 😊.
TrafficLights enhanced by Claude:
import b from 'bss'
// ================================
// 📋 CONFIGURATION - All settings in one place
// ================================
// This is where you can easily change colors, sizes, and timing without digging through code
const CONFIG = {
// 🎨 Colors used throughout the app
colors: {
background: "#252526", // Dark background
border: "white", // White borders
container: "black", // Traffic light box background
text: {
light: "white", // White text
dark: "black" // Black text
},
lights: {
red: "red", // Red traffic light
orange: "orange", // Orange traffic light
green: "green" // Green traffic light
},
ui: {
primary: "#333", // Main button color
primaryHover: "#555", // Button hover color
danger: "crimson", // Stop button color
disabled: "gray" // Disabled button color
}
},
// 📏 Spacing - consistent gaps and margins
spacing: {
xs: "0.25rem", // Extra small: 4px
sm: "0.5rem", // Small: 8px
md: "1rem", // Medium: 16px
lg: "1.25rem", // Large: 20px
xl: "2rem", // Extra large: 32px
xxl: "6rem" // Extra extra large: 96px
},
// 📐 Sizes - dimensions for various elements
sizes: {
lightSize: "55px", // How big each light is
buttonWidth: "3.5rem", // Width of control buttons
containerWidth: "45px", // Width of traffic light box
containerHeight: "270px", // Height of traffic light box
orientationButtonWidth: "140px" // Width of orientation toggle button
},
// ⏰ Timing - how fast things happen
timing: {
lightDuration: 500, // How long each light stays on (milliseconds)
transitionDelay: 200, // Pause between lights
cycleDelay: 300, // Pause between complete cycles
cssTransition: "all 0.63s ease" // CSS animation speed
}
};
// 🏁 Starting state - what the app looks like when it first loads
const INITIAL_STATE = {
red: "hidden", // Red light starts off
orange: "hidden", // Orange light starts off
green: "hidden", // Green light starts off
orientation: "column", // Lights arranged vertically
cycling: false // Auto-cycling is off
};
// 🔄 The order lights flash in auto-cycle mode
const LIGHT_SEQUENCE = ["red", "orange", "green"];
// ================================
// 🛠️ HELPER FUNCTIONS
// ================================
// Simple delay function - makes code wait for a specified time
const delay = (milliseconds) => new Promise(resolve => setTimeout(resolve, milliseconds));
// Sets up the basic styles for the page
const createBaseStyles = () => {
// Style the page background
b.css({
body: {
bc: CONFIG.colors.background // bc = background-color
}
});
// Style all buttons to look consistent
b.css({
button: {
w: CONFIG.sizes.buttonWidth, // w = width
ta: 'center', // ta = text-align
border: 'none', // Remove default border
p: CONFIG.spacing.sm, // p = padding
br: '3px', // br = border-radius (rounded corners)
cursor: 'pointer', // Show hand cursor on hover
transition: CONFIG.timing.cssTransition // Smooth animations
}
});
};
// ================================
// 🎨 STYLE GENERATORS - Functions that create CSS styles
// ================================
// Creates styles for individual lights (red, orange, green)
const createLightStyles = (color, isVisible) => {
// Base styles that all lights share
const baseStyle = `
w ${CONFIG.sizes.lightSize}
h ${CONFIG.sizes.lightSize}
br 50%
bc ${color}
m 6px
transition ${CONFIG.timing.cssTransition}`;
// Different styles based on whether light is on or off
const stateStyle = isVisible
? `opacity 1; box-shadow: 0px 0px 40px 10px ${color}` // Bright with glow
: 'opacity 0.3'; // Dim
return b`${baseStyle} ${stateStyle}`;
};
// Collection of button styles for different purposes
const buttonStyles = {
// Styles for light control buttons (Red, Orange, Green)
lightControl: (backgroundColor, textColor) => b`bc ${backgroundColor}; c ${textColor}`,
// Styles for the "Start Cycle" button
cycleStart: (isCycling) => b`
bc ${isCycling ? CONFIG.colors.ui.disabled : CONFIG.colors.lights.green}
c ${CONFIG.colors.text.light}
${isCycling ? 'opacity 0.6; cursor not-allowed' : ''}`,
// Styles for the "Stop Cycle" button
cycleStop: (isCycling) => b`
bc ${isCycling ? CONFIG.colors.ui.danger : CONFIG.colors.ui.disabled}
c ${CONFIG.colors.text.light}
${!isCycling ? 'opacity 0.6; cursor not-allowed' : ''}`,
// Styles for the orientation toggle button
orientation: () => b`
w ${CONFIG.sizes.orientationButtonWidth} !important
bc ${CONFIG.colors.ui.primary}
c ${CONFIG.colors.text.light}
`.$hover({
bc: 'red' // Changes to red when you hover over it
})
};
// ================================
// 🧠 BUSINESS LOGIC - The "brain" of the application
// ================================
// This is the main controller that handles all the traffic light logic
const TrafficLightController = (context) => {
let cyclingTimeoutId = null; // Keeps track of the auto-cycle timer
// Shortcuts to make the code cleaner
const setState = context.setState;
const getState = context.getState;
// Helper functions for working with lights
const setLightState = (color, state) => setState(color, state);
const getLightState = (color) => getState(color);
const isCycling = () => getState("cycling");
// Turn off all lights at once
const turnOffAllLights = () => {
LIGHT_SEQUENCE.forEach(color => setLightState(color, "hidden"));
};
// Toggle a single light on/off (only works when not auto-cycling)
const toggleLight = (color) => {
if (isCycling()) return; // Don't allow manual control during auto-cycle
const currentState = getLightState(color);
setLightState(color, currentState === "visible" ? "hidden" : "visible");
};
// Start the automatic cycling of lights
const startCycling = () => {
if (isCycling()) return; // Don't start if already cycling
setState("cycling", true);
cycleLights();
};
// Stop the automatic cycling
const stopCycling = () => {
setState("cycling", false);
if (cyclingTimeoutId) {
clearTimeout(cyclingTimeoutId); // Stop the timer
cyclingTimeoutId = null;
}
turnOffAllLights(); // Turn off all lights when stopping
};
// The main cycling logic - makes lights flash in sequence
const cycleLights = async () => {
// Clear any existing timer to prevent conflicts
if (cyclingTimeoutId) {
clearTimeout(cyclingTimeoutId);
}
try {
// Start with all lights off
turnOffAllLights();
await delay(CONFIG.timing.transitionDelay);
// Go through each light in sequence
for (const color of LIGHT_SEQUENCE) {
if (!isCycling()) return; // Stop if cycling was turned off
setLightState(color, "visible"); // Turn light on
await delay(CONFIG.timing.lightDuration); // Wait
setLightState(color, "hidden"); // Turn light off
await delay(CONFIG.timing.transitionDelay); // Brief pause
}
// If still cycling, schedule the next cycle
if (isCycling()) {
cyclingTimeoutId = setTimeout(() => cycleLights(), CONFIG.timing.cycleDelay);
}
} catch (error) {
console.error("Error during light cycling:", error);
stopCycling(); // Stop cycling if something goes wrong
}
};
// Switch between vertical and horizontal light arrangement
const toggleOrientation = () => {
const current = getState("orientation");
setState("orientation", current === "column" ? "row" : "column");
};
// Return all the functions that other parts of the app can use
return {
toggleLight,
startCycling,
stopCycling,
toggleOrientation,
isCycling,
getLightState,
getState
};
};
// ================================
// 🎭 UI COMPONENTS - The visual parts of the app
// ================================
// Individual light component (red, orange, or green circle)
const Light = (props, context) => ({
div: {
className: () => {
const isVisible = context.getState(props.name) === 'visible';
return createLightStyles(props.color, isVisible);
}
}
});
// Container that holds all three lights
const LightContainer = (props, context) => ({
div: {
className: b`display flex; jc center`, // Center the lights
children: [{
div: {
className: () => b`
display flex
flex-direction ${context.getState("orientation")}
gap ${CONFIG.spacing.lg}
mt ${CONFIG.spacing.md}`,
children: [
{ Light: { color: CONFIG.colors.lights.red, name: 'red' } },
{ Light: { color: CONFIG.colors.lights.orange, name: 'orange' } },
{ Light: { color: CONFIG.colors.lights.green, name: 'green' } },
]
}
}]
}
});
// Control panel with all the buttons
const ControlPanel = (props, context) => {
const controller = TrafficLightController(context);
return {
div: {
className: b`
display flex
jc center
gap ${CONFIG.spacing.sm}
padding-bottom ${CONFIG.spacing.xl}
mt 6rem`,
children: [
// Individual light control buttons
{ button: {
className: buttonStyles.lightControl(CONFIG.colors.lights.red, CONFIG.colors.text.light),
text: "Red",
onclick: () => controller.toggleLight("red")
}},
{ button: {
className: buttonStyles.lightControl(CONFIG.colors.lights.orange, CONFIG.colors.text.dark),
text: "Orange",
onclick: () => controller.toggleLight("orange")
}},
{ button: {
className: buttonStyles.lightControl(CONFIG.colors.lights.green, CONFIG.colors.text.light),
text: "Green",
onclick: () => controller.toggleLight("green")
}},
// Auto-cycle control buttons
{ button: {
className: () => buttonStyles.cycleStart(controller.isCycling()),
text: () => controller.isCycling() ? "Cycling..." : "Start Cycle",
onclick: () => controller.startCycling()
}},
{ button: {
className: () => buttonStyles.cycleStop(controller.isCycling()),
text: "Stop Cycle",
onclick: () => controller.stopCycling()
}}
]
}
};
};
// The main traffic light box that contains everything
const TrafficLightBox = (props, context) => ({
div: {
className: b`
br 5px
border 1px solid ${CONFIG.colors.border}
p ${CONFIG.spacing.md}
bc ${CONFIG.colors.container}
w ${CONFIG.sizes.containerWidth}
h ${CONFIG.sizes.containerHeight}
m 0 auto
mt ${CONFIG.spacing.xxl}`,
children: [
{ LightContainer: {} },
{ ControlPanel: {} },
]
}
});
// Button to switch between vertical and horizontal layout
const OrientationToggle = (props, context) => {
const controller = TrafficLightController(context);
return {
button: {
className: buttonStyles.orientation(),
text: () => {
const orientation = controller.getState("orientation");
return orientation === "row" ? "Arrange Vertical" : "Arrange Horizontal";
},
onclick: () => controller.toggleOrientation()
}
};
};
// Container for the orientation toggle button
const OrientationContainer = () => ({
div: {
className: b`
w ${CONFIG.sizes.orientationButtonWidth}
m 0 auto
mt ${CONFIG.spacing.md}`,
children: [{ OrientationToggle: {} }]
}
});
// ================================
// 🔧 HEADLESS COMPONENTS - Logic without visual elements
// ================================
// This component provides the cycling API but doesn't render anything
const TrafficLightsManager = (props, context) => {
const controller = TrafficLightController(context);
return {
api: {
cycleLights: controller.startCycling,
stopCycling: controller.stopCycling
}
};
};
// ================================
// 🚀 APPLICATION SETUP
// ================================
// Function that sets up and creates the entire application
const initializeApp = () => {
createBaseStyles(); // Apply the base CSS styles
return new Juris({
// Starting state of the application
states: INITIAL_STATE,
// All the visual components
components: {
Light,
LightContainer,
ControlPanel,
TrafficLightBox,
OrientationToggle,
OrientationContainer
},
// Non-visual components that provide functionality
headlessComponents: {
TrafficLightsManager: {
fn: TrafficLightsManager,
options: { autoInit: true }
}
},
// What gets displayed on the page
layout: [
{ TrafficLightBox: {} },
{ OrientationContainer: {} }
]
});
};
// ================================
// 🎬 START THE APP
// ================================
const app = initializeApp();
app.render();
// 📚 HOW TO CUSTOMIZE:
// 1. Change colors: Edit the CONFIG.colors section
// 2. Adjust timing: Modify CONFIG.timing values
// 3. Resize elements: Update CONFIG.sizes
// 4. Add new lights: Add to LIGHT_SEQUENCE and update components
// 5. Change layout: Modify the layout array in initializeApp
Rating from ChatGPT
Category | Score | Comments |
---|---|---|
Structure & Modularity | ✅ 10/10 | Excellent separation of concerns (config, logic, UI). Easy to navigate and extend. |
Readability & Comments | ✅ 10/10 | Well-documented with friendly, helpful inline comments. Emojis + clear headers = super readable. |
Styling System (bss ) |
✅ 9/10 | Consistent and compact, though a small learning curve if you're unfamiliar with bss . |
Logic & Flow | ✅ 9/10 | Async cycleLights is clean. Good use of promises and delays. Minor edge cases could be expanded. |
Reusability / Scalability | ⚠️ 7.5/10 | Mostly hardcoded for 3 lights. Would benefit from making lights dynamic via config. |
Accessibility / UX | ⚠️ 6.5/10 | Could improve on keyboard access, color contrast, and ARIA roles for screen readers. |
Framework Usage | ✅ 9/10 | Assuming familiarity with Juris , it's cleanly integrated. If not, maybe a bit opaque to newcomers. |
Top comments (0)