anchor.diff:      }
       assert(selectedNode == items[selectedNodeIndex]);
   
  -    if (event.logicalKey == LogicalKeyboardKey.arrowDown ||
  -        event.logicalKey == LogicalKeyboardKey.arrowUp) {
  -      _moveSelection(event.logicalKey, scrollController, constraints.maxHeight);
  -    }
  -    // TODO(gmoothart): Add expand/collapse with left/right keys
  +    if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
  +      _moveSelection(ScrollKind.down, scrollController, constraints.maxHeight);
  +    } else if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
  +      _moveSelection(ScrollKind.up, scrollController, constraints.maxHeight);
  +    } else if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
  +      // On left arrow collapse the row if it is expanded. If it is not, move
  +      // selection to its parent.
  +      if (selectedNode.isExpanded) {
  +        _toggleNode(selectedNode);
  +      } else {
  +        _moveSelection(
  +          ScrollKind.parent,
  +          scrollController,
  +          constraints.maxHeight,
  +        );
  +      }
  +    } else if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
  +      // On right arrow expand the row if possible, otherwise move selection down.
  +      if (!selectedNode.isExpanded) {
  +        _toggleNode(selectedNode);
  +      } else {
  +        _moveSelection(
  +          ScrollKind.down,
  +          scrollController,
  +          constraints.maxHeight,
  +        );
  +      }
  +    }
     }
   
     void _moveSelection(
  -    LogicalKeyboardKey key,
  +    ScrollKind scrollKind,
       ScrollController scrollController,
       double viewportHeight,
     ) {
  
positive.code: 
    void _onItemPressed(T node, int nodeIndex) {
      /// Rebuilds the table whenever the tree structure has been updated
      setState(() {
        selectedNode = node;
        selectedNodeIndex = nodeIndex;
  
        if (!node.isExpandable) return;
        animatingNode = node;
        List<T> nodeChildren;
  
negative.code: 
      if (isBelowViewport) {
        // Scroll so selected row is the last full item displayed in the viewport.
        // To do this we need to be showing the (minCompleteItemsInView + 1)
        // previous item  at the top.
        scrollController.animateTo(
          (newSelectedNodeIndex - minCompleteItemsInView + 1) *
              _Table.defaultRowHeight,
          duration: defaultDuration,
          curve: defaultCurve,
  