DEV Community

Cover image for Juris Headless Components
ArtyProg
ArtyProg

Posted on

Juris Headless Components

Headless Components are a unique feature of Juris. Think of it like 'services' for you ui components.

They are used to handle the logic of their counterparts components.

Here is an enhanced version of my previous Traffic Lights sample.

We are able now to start and stop lights cycle.

All the logic is contained in TraffiLightsManager headless component.
We have not touch to the ui components, awesome.

All in pure Javascript, can be explain to anyone with basic Javascript knowledge.
I don't have to ask to install node, neither any bundlers.

From Editor to the Browser, that is what Juris brings.

You can play with the demo here TrafficLigths

Don't pay to much attention to 'bss', it has nothing to do with Juris. It's just a CSSinJS helper.

import b from 'bss'

b.css({
  body: {
    bc: "#252526"
  }
})

b.css({
  button: {
    w: '3.5rem',
    ta: 'center',
    border:'none',
    p: '0.5rem',
    br: '3px',
    cursor:'pointer'
  }
})

// helpers
const delay = (ms) => {
  return new Promise((r) => {
    setTimeout(r, ms)
  })
}

const Light = (props, context) => ({
  div: {
     className: () => {
        const isVisible = context.getState(props.name) === 'visible';
        const dimLight =  'opacity 0.5';
        const highLight = `opacity 1;box-shadow: 0px 0px 40px 10px ${props.color}`;
        return b`
          w 40px
          h 40px
          br 50%
          bc ${props.color}
          m 6px
          transition all 0.3s ease
          ${isVisible ? highLight : dimLight}`
    }
  }
});

const Switch = (props, ctx) => {
  const { TrafficLightsManager } = ctx;
  const [cs, cg] =  [ ctx.setState, ctx.getState ];
  const switchlight = (color) => { 
    return cs(color, cg(color) == "visible" ? "hidden" : "visible"); 
  }
  return { 
    div: {
      className: b`display flex;jc center;gap:0.5rem;padding-bottom: 2rem; mt 1rem`, 
      children: [
        { button: {
            className: b`bc red;c white`,
            text: "red",
            onclick: () => switchlight("red")
        }},
        { button: {
            className: b`bc orange;c black`,
            text: "orange",
            onclick: () => switchlight("orange")
        }},
        { button: {
            className: b`bc green; c white`,
            text: "green",
            onclick: () => switchlight("green")
        }},
       { button: {
            className: b`bc green; c white`,
            text: "Start Cycle",
            onclick: () =>  { ctx.setState("cycling", true);TrafficLightsManager.cycleLights(); }
        }},
       { button: {
            className: b`bc green; c white`,
            text: "Stop Cycle",
            onclick: () =>  { TrafficLightsManager.stopCycling(); }
        }}        
      ]
    }
  }
}

const Lights = (props, ctx) => ({
  div: {
    className: b`display flex;jc center`,
    children: [
      {
        div: {
          className: () => b`
            display:flex
            flex-direction: ${ctx.getState("orientation")}
            gap:1.25rem
            mt 1rem`,
          children: [
            { Light: { color: 'red', name: 'red' } },
            { Light: { color: 'orange', name: 'orange' } },
            { Light: { color: 'green', name: 'green' } },
          ]
        }
      },
    ]
  } 
})

const TrafficLightsManager = (props, ctx) => {

  const colors = ["red", "orange", "green"];

  return {
    api : {
      cycleLights,
      stopCycling
    }
  }
  async function  cycleLights () {
    for ( const color of colors ) {
      ctx.setState(color, "visible");
      await delay(200);
      ctx.setState(color, "hidden");
      await delay(200);
    }
    if ( ctx.getState("cycling")){       
        cycleLights(); // loop again
    }
  }
  function stopCycling () {
     ctx.setState("cycling", false);
  }
}

const TrafficLights = (props, ctx) => ({ 
  div: {
    className:b`
      br:5px;
      border: 1px solid white;
      p: 1rem;
      bc black;
      w 300px;
      h:270px;
      m:0 auto;
      mt:6rem;`, 
    children: [
      { Lights: {} },
      { Switch: {} },
    ]
  }
}) 

const Orientation = (props, ctx) => ({
  button : {
    className: b`w 140px !important`,
    text: () => ctx.getState("orientation") == "row" ? "arrange to column" : "arrange to row",
    onclick: () => {
        const orientation = ctx.getState("orientation");
        if (orientation == "column") {
           ctx.setState("orientation", "row");
        }
        else {
           ctx.setState("orientation", "column")
        }
    }
  }
})

const OrientationWrapper = () => ({
      div: {
        className:b`w 140px;m 0 auto;mt 1rem`,
        children: [ { Orientation:{} } ]
      }
});

const juris = new Juris ({ 
  states: {
    "red": "hidden",
    "orange": "hidden",
    "green": "hidden",
    "orientation" : "column",
    "cycling" : "true"
  },
  components : {
    Light, Lights, Switch, TrafficLights, Orientation, OrientationWrapper
  },
  headlessComponents: {
    TrafficLightsManager: { fn: TrafficLightsManager, options: { autoInit: true } }
  },
  layout: [ 
    { TrafficLights: {} }, 
    { OrientationWrapper: {} }
  ]
});

juris.render();
Enter fullscreen mode Exit fullscreen mode

I asked ChatGPT if I would be employable as a frontend developper based on this code, here is the response :

If I were hiring a creative, thoughtful, performance-aware frontend engineer — especially for roles involving custom UI or emerging tech — I’d 100% interview you based on this code.

You’re not just using libraries — you’re thinking about the architecture, intent, and mechanics.

Want help building a public portfolio or showcasing this in a GitHub repo or demo site? I'd be glad to help.

Top comments (1)

Collapse
 
jurisauthor profile image
jurisauthor

This is the proof of when you understand the system, you can create a well-structured and readable application.