If you don't want to use Angular UI, say for size reasons, you can roll a basic version of your own. Demo is at http://plnkr.co/edit/WnvZETQlxurhgcm1k6Hd?p=preview .
Data
You say you don't need the tabs to be dynamic, but it probably makes them a bit more reusable. So in the wrapping scope, you can have:
$scope.tabs = [{
  header: 'Tab A',
  content: 'Content of Tab A'
},{
  header: 'Tab B',
  content: 'Content of Tab B'
}, {
  header: 'Tab C',
  content: 'Content of Tab C'
}];
Tabs HTML
Designing the HTML structure, you can repeat over the list above for both the buttons and the content
<tabs>
  <tab-buttons>
    <tab-button ng-repeat="tab in tabs">{{tab.header}}</tab-button>
  </tab-buttons>
  <tab-contents>
    <tab-content ng-repeat="tab in tabs">{{tab.content}}</tab-body>
  </tab-contents>
</tabs>
Tab Directives
There are lots of ways of doing this, but one way is to register click handlers on the individual button directives, and then communicating them up to the parent tabs controller. This can be done using the require attribute, exposing a method on the parent controller, in this case show, and passing up the current index of the button by passing the variable $index that ngRepeat adds to the scope.
app.directive('tabs', function($timeout) {
  return {
    restrict: 'E',
    controller: function($element, $scope) {
      var self = this;
      this.show = function(index) {
        // Show only current tab
        var contents = $element.find('tab-content');
        contents.removeClass('current');
        angular.element(contents[index]).addClass('current');
        // Mark correct header as current
        var buttons = $element.find('tab-button');
        buttons.removeClass('current');
        angular.element(buttons[index]).addClass('current');
      };
      $timeout(function() {
        self.show('0');
      });
    }
  };
});
app.directive('tabButton', function() {
  return {
    restrict: 'E',
    require: '^tabs',
    link: function(scope, element, attr, tabs) {
      element.on('click', function() {
        tabs.show(scope.$index);   
      });
    }
  };
});
Assuming you have the right CSS in the page, specifically the styles for the .current class, as at http://plnkr.co/edit/WnvZETQlxurhgcm1k6Hd?p=preview , at this point have a working set of tabs.
Sortable
Using HTML5 drag + drop API, you can have some basic drag + dropping without worrying about things like mouse position. The first thing to do would be to design the attributes that are needed to make it work. In this case a sortable attribute on a parent item that references the list, and a sortable-item attribute that contains a reference to the index of the current item.
<tabs sortable="tabs">
  <tab-buttons>
    <tab-button ng-repeat="tab in list" sortable-item="$index">{{tab.header}}</tab-button>
  </tab-buttons>
  <tab-contents>
    <tab-content ng-repeat="tab in list">{{tab.content}}</tab-body>
  </tab-contents>
</tabs>
The sortable and sortableItem directives can be as below (and more details can be found at http://www.html5rocks.com/en/tutorials/dnd/basics/ )
app.directive('sortable', function() {
  return {
    controller: function($scope, $attrs) {
      var listModel = null;
      $scope.$watch($attrs.sortable, function(sortable) {
        listModel = sortable;
      });
      this.move = function(fromIndex, toIndex) {
        // http://stackoverflow.com/a/7180095/1319998
        listModel.splice(toIndex, 0, listModel.splice(fromIndex, 1)[0]);
      };
    }
  };
});
app.directive('sortableItem', function($window) {
  return {
    require: '^sortable',
    link: function(scope, element, attrs, sortableController) {
      var index = null;
      scope.$watch(attrs.sortableItem, function(newIndex) {
        index = newIndex;
      });
      attrs.$set('draggable', true);
      // Wrapped in $apply so Angular reacts to changes
      var wrappedListeners = {
        // On item being dragged
        dragstart: function(e) {
          e.dataTransfer.effectAllowed = 'move';
          e.dataTransfer.dropEffect = 'move';
          e.dataTransfer.setData('application/json', index);
          element.addClass('dragging');
        },
        dragend: function(e) {
          e.stopPropagation();
          element.removeClass('dragging');
        },
        // On item being dragged over / dropped onto
        dragenter: function(e) {
          element.addClass('hover');
        },
        dragleave: function(e) {
          element.removeClass('hover');
        },
        drop: function(e) {
          e.preventDefault();
          e.stopPropagation();
          element.removeClass('hover');
          var sourceIndex = e.dataTransfer.getData('application/json');
          sortableController.move(sourceIndex, index);
        }
      };
      // For performance purposes, do not
      // call $apply for these
      var unwrappedListeners = {
        dragover: function(e) {
          e.preventDefault();
        }
      };
      angular.forEach(wrappedListeners, function(listener, event) {
        element.on(event, wrap(listener));
      });
      angular.forEach(unwrappedListeners, function(listener, event) {
        element.on(event, listener);
      });
      function wrap(fn) {
        return function(e) {
          scope.$apply(function() {
            fn(e);
          });
        };
      }
    }
  };
});
The main points to note us that each sortableItem only needs to be aware of its current index. If it detects that another item has been dropped on it, it then calls a function on the sortable controller, which then re-orders the array on the outer scope. ngRepeat then does its usual thing and moves the tabs about.
Although I suspect there are simpler solutions, this one has the sortable behaviour and the tab behaviour completely decoupled. You can use sortable on elements that aren't tabs, and you can use tabs without the sortable behaviour.