Element Framework

Item

  • HTML
  • JS
  • CSS
<ef-item type="header">Menu</ef-item>
<ef-item icon="home">Home</ef-item>
<ef-item icon="directory">Contacts</ef-item>
<ef-item icon="calendar">Calendar</ef-item>
<ef-item icon="briefcase" disabled>Briefcase</ef-item>
<ef-item type="header">Advanced</ef-item>
<ef-item type="divider"></ef-item>
<ef-item icon="compass">Sneak Peeks</ef-item>
<ef-item icon="dashboard">Dashboard</ef-item>

                  
ef-item {
  width: 300px;
}

ef-item is generally used as a basic building block to compose complex custom elements. Additionally it can be used by applications to create simple menus or navigation panels.

Basic usage

Use ef-item to create an individual list item. It provides features such as types and icons to simplify building menu controls.

  • HTML
  • JS
  • CSS
<div id="menu">
  <ef-item type="header">Edit</ef-item>
  <ef-item icon="undo" value="undo">Undo</ef-item>
  <ef-item icon="redo" value="redo" disabled>Redo</ef-item>
  <ef-item type="divider"></ef-item>
  <ef-item icon="cut" value="cut">Cut</ef-item>
  <ef-item icon="copy" value="copy">Copy</ef-item>
  <ef-item icon="paste" value="paste">Paste</ef-item>
</div>

<ef-item id="selected" disabled label="Try to click menu above"></ef-item>
var menu = document.getElementById("menu");
var selectedElement;
menu.addEventListener("tap", function(e) {
  var target = e.target;
  if (!target.highlightable) {
    return;
  }
  if (selectedElement) {
    selectedElement.selected = false;
  }
  selectedElement = target;
  selectedElement.selected = true;
  document.getElementById("selected").label = selectedElement.value + " is clicked!";
});
menu.addEventListener('mouseover', function(event) {
  event.target.highlighted = true;
});
menu.addEventListener('mouseout', function(event) {
  event.target.highlighted = false;
});
#menu {
  display: flex;
  flex-direction: column;
  width: 300px;
}

#selected {
  margin: 10px 0;
}
<div id="menu">
  <ef-item type="header">Edit</ef-item>
  <ef-item icon="undo" value="undo">Undo</ef-item>
  <ef-item icon="redo" value="redo" disabled>Redo</ef-item>
  <ef-item type="divider"></ef-item>
  <ef-item icon="cut" value="cut">Cut</ef-item>
  <ef-item icon="copy" value="copy">Copy</ef-item>
  <ef-item icon="paste" value="paste">Paste</ef-item>
</div>

ef-item provides styles for the focus, highlighted and selected states. However, only the focus state is managed by ef-item itself. The highlight and selection models should be managed by the external component by setting the highlighted and selected states, respectively.

menu.addEventListener("tap", function (e) {
  var target = e.target;
  // skip if users click on disabled or divider
  if (!target.highlightable) {
    return;
  }
  // deselected item that currently selected
  if (selectedElement) {
    selectedElement.selected = false;
  }
  // set selected flag to clicked item
  selectedElement = target;
  selectedElement.selected = true;
});

menu.addEventListener('mouseover', function (event) {
  event.target.highlighted = true;
});

menu.addEventListener('mouseout', function (event) {
  event.target.highlighted = false;
});

Using labels

ef-item provides label and sub-label attributes to set the label property as a simplified instance of the content.

  • HTML
  • JS
  • CSS
<div id="menu">
  <ef-item label="Team Members" icon="directory"></ef-item>
  <ef-item label="Cornelius Martin" sub-label="Position: Software Engineer" icon="individual"></ef-item>
  <ef-item label="Angela Lloyd" sub-label="Position: Development Manager" icon="individual"></ef-item>
</div>
var menu = document.getElementById("menu");
menu.addEventListener('mouseover', function(event) {
  event.target.highlighted = true;
});
menu.addEventListener('mouseout', function(event) {
  event.target.highlighted = false;
});
#menu {
  display: flex;
  flex-direction: column;
  width: 300px;
}
<div id="menu">
  <ef-item label="Team Members" icon="directory"></ef-item>
    <ef-item label="Cornelius Martin" sub-label="Position: Software Engineer" icon="individual"></ef-item>
  <ef-item label="Angela Lloyd" sub-label="Position: Development Manager" icon="individual" ></ef-item>
</div>

Both label and sub-label are not displayed if ef-item has children.

<ef-item label="This text will not be displayed" sub-label="This text will not be displayed">
    This text will be displayed
</ef-item>

Using slots

Custom content can be added using slots. ef-item provides bopth left and right slots.

  • HTML
  • JS
  • CSS
<div id="todo">
  <ef-item>
    <ef-checkbox>Carrots</ef-checkbox>
    <div class="notes" slot="right">Small bag</div>
    <ef-button toggles icon="trash" slot="right"></ef-button>
  </ef-item>
  <ef-item>
    <ef-checkbox>Chocolates</ef-checkbox>
    <div class="notes" slot="right">For Otis</div>
    <ef-button toggles icon="trash" slot="right"></ef-button>
  </ef-item>
  <ef-item>
    <ef-checkbox>Pumpkins</ef-checkbox>
    <div class="notes" slot="right">Halloween!</div>
    <ef-button toggles icon="trash" slot="right"></ef-button>
  </ef-item>
</div>

                  
#todo {
  display: flex;
  flex-direction: column;
  width: 550px;
  margin: 10px 0;
}

ef-button {
  margin: 0;
}

.notes {
  color: #b7b7b7;
  margin-right: 10px;
}

ef-item[focused] ef-checkbox {
  color: white;
}

ef-item[focused] .notes {
  color: white;
}
<ef-item>
  <ef-checkbox>Carrots</ef-checkbox>
  <div class="notes" slot="right">Small bag</div>
  <ef-button toggles icon="trash" slot="right"></ef-button>
</ef-item>

Advanced usage

ef-item can be used to create menu elements. You should implement your own highlight and selection models.

  • HTML
  • JS
  • CSS
<div id="menu" tabindex="0">
  <ef-item type="header">EMEA</ef-item>
  <ef-item value="Spain">Spain</ef-item>
  <ef-item value="France" disabled>France</ef-item>
  <ef-item value="Italy">Italy</ef-item>
  <ef-item type="header">ASIA</ef-item>
  <ef-item type="divider"></ef-item>
  <ef-item value="Japan">Japan</ef-item>
  <ef-item value="China">China</ef-item>
</div>
<div id="selected">Try to click and use keyboard to navigate the menu</div>
var menu = document.getElementById('menu');
var selectedEl;

// Get highlighted item
var getHighlighted = function() {
  return menu.querySelector('ef-item[highlighted]');
};

// Get all items that can be highlighted
var getHighlightableEls = function() {
  return Array.prototype.slice.call(menu.querySelectorAll('ef-item'))
    .filter(function(item) {
      return item.highlightable;
    });
};

var highlight = function(el) {
  var highlightedEl = getHighlighted();
  if (highlightedEl === el) {
    return true;
  }
  if (!el.highlightable) {
    return false;
  }

  if (highlightedEl) {
    highlightedEl.highlighted = false;
  }

  el.highlighted = true;
};

// Highlight next or previous item
var highlightNextFocusableItem = function(event, dir) {
  event.stopPropagation();
  event.preventDefault();

  var highlightableEls = getHighlightableEls();
  var highlightedEl = getHighlighted();

  if (dir === 1) {
    newHighlighted = highlightableEls[highlightableEls.indexOf(highlightedEl) + 1] || highlightableEls[0];
  } else if (dir === -1) {
    newHighlighted = highlightableEls[highlightableEls.indexOf(highlightedEl) - 1] || highlightableEls[highlightableEls.length - 1];
  }

  if (newHighlighted) {
    highlight(newHighlighted);
    newHighlighted.focus();
  }
};

var select = function(item) {
  if (selectedEl) {
    selectedEl.selected = false;
  }
  selectedEl = item;
  item.selected = true;
  document.getElementById('selected').innerHTML = item.value + ' is selected!';
};

menu.addEventListener('keydown', function(event) {
  switch (event.key) {
    case 'Down':
    case 'ArrowDown':
    case 'Tab':
      highlightNextFocusableItem(event, 1);
      break;
    case 'Up':
    case 'ArrowUp':
      highlightNextFocusableItem(event, -1);
      break;
    case 'Enter':
      getHighlighted().focus();
      getHighlighted() && getHighlighted().click();
      break;
    default:
      // no default
  }
});

menu.addEventListener('mouseover', function(event) {
  menu.focus();
  highlight(event.target);
});

menu.addEventListener('mouseout', function(event) {
  if (event.target.highlighted) {
    event.target.highlighted = false;
  }
});

menu.addEventListener('tap', function(event) {
  if (event.target.highlightable) {
    highlight(event.target);
    select(event.target);
  }
});
#menu {
  display: flex;
  flex-direction: column;
  width: 300px;
  outline: none;
}

#selected {
  margin: 10px 0;
}
<div id="menu" tabindex="0">
  <ef-item type="header">EMEA</ef-item>
  <ef-item value="Spain">Spain</ef-item>
</div>

<script>
  var menu = document.getElementById('menu');

  // Get highlighted item
  var getHighlighted = function () {
    return menu.querySelector('ef-item[highlighted]');
  };

  // Get all items that can be highlighted
  var getHighlightableEls = function () {
    return Array.prototype.slice.call(menu.querySelectorAll('ef-item'))
      .filter(function (item) {
        return item.highlightable;
      });
  };

  menu.addEventListener('keydown', function(event) {
    // Implement keyboard navigation model
  });

  menu.addEventListener('mouseover', function (event) {
    // Implement highlight model
  });

  menu.addEventListener('mouseout', function (event) {
    // Implement remove highlight model
  });

  menu.addEventListener('tap', function (event) {
    // Implement selection model
  });
</script>

Slots

left
Used to render the content on the left of the label.
right
Used to render the content on the right of the label.

API Reference

Attributes

string | null
label
The text for the label indicating the meaning of the item. By having both `label` and content, `label` always takes priority
ItemType | null
type
If defined value can be `text`, `header` or `divider`
string | null
icon
Set the icon name from the ef-icon list
boolean
selected
Indicates that the item is selected
boolean
multiple
Is the item part of a multiple selection
boolean
highlighted
Highlight the item
string | null
sub-label
The`subLabel` property represents the text beneath the label.
string | null
for
Specifies which element an item is bound to
string
value
The content of this attribute represents the value of the item.
boolean
disabled
Set disabled state.

Properties

string | null
label
The text for the label indicating the meaning of the item. By having both `label` and content, `label` always takes priority
ItemType | null
type
If defined value can be `text`, `header` or `divider`
string | null
icon
Set the icon name from the ef-icon list
boolean
selected
Indicates that the item is selected
false
boolean
multiple
Is the item part of a multiple selection
false
boolean
highlighted
Highlight the item
false
string | null
subLabel
The`subLabel` property represents the text beneath the label.
string | null
for
Specifies which element an item is bound to
boolean
highlightable
Return true if the item can be highlighted. True if not disabled and type is Text
boolean
isTruncated
Getter returning if the label is truncated
string
value
The content of this attribute represents the value of the item.
""
boolean
disabled
Set disabled state.
false