hi, I've just completed a js menu class base on yui-ext and yui. Because the YAHOO's menu class
is too large and complex, my menu don't rely on it and just a js class especialy bases on yui-ext.
shown below:

menu.js
Code:
/**
 * @author zsx
 * @version 0.1.6
 */

if (!YAHOO.ext.MenuDB) {
    YAHOO.ext.MenuDB = {};
    YAHOO.ext.MenuDB.menu = [];
    YAHOO.ext.MenuDB.menuItem = [];
}    

YAHOO.ext.MenuItem = function(config) {
    YAHOO.ext.util.Config.apply(this, config);
    this.innerElement = document.createElement('span');
};
YAHOO.ext.MenuItem.prototype = {

    /**
     * @private
     * @param {Object} appendTo
     * @param {Object} tr
     */
    init: function(appendTo, tr) {
        if (this.id) {
            this.innerElement.id = this.id;
            YAHOO.ext.MenuDB.menuItem[this.id] = this;
        }
        this.disable = (this.disabled === true);
        appendTo.appendChild(this.innerElement);
        this.el = getEl(tr, true);
        this.innerElement.innerHTML = (this.text ? this.text : '');
        this.el.mon('click', this.onClick, this, true);
        this.el.mon('mouseout', this.onMouseOut, this, true);
        this.el.mon('mouseover', this.onMouseOver, this, true);
    },
    disable : function() {
        this.disabled = true;
        if(this.el){
            this.el.addClass('ymb-item-disabled');
        }
    },
    enable : function() {
        this.disabled = false;
        if(this.el){
            this.el.removeClass('ymb-item-disabled');
        }
    },
    isDisabled : function() {
        return this.disabled === true;
    },
    setDisabled : function(disabled) {
        if(disabled){
            this.disable();
        } else {
            this.enable();
        }
    },
    onClick : function(e, scope) {
        if(!this.disabled && this.click)
            this.click.call(this.scope || window, e, this);
        },
    onMouseOver : function(e, scope) {
        if(!this.disabled){
            this.el.addClass('ymb-item-over');
            if(this.mouseover){
                this.mouseover.call(this.scope || window, e, this);
            }
        }
    },
    onMouseOut : function(e, scope) {
        if (this.isLabel)
            return;
        this.el.removeClass('ymb-item-over');
        if(!this.disabled){
            if(this.mouseout){
                this.mouseout.call(this.scope || window, e, this);
            }
        }
    },
    addMouseOverClass: function() {
        this.el.addClass('ymb-item-over');
    },
    removeMouseOverClass: function() {
        this.el.removeClass('ymb-item-over');
    }
};

YAHOO.ext.Menu = function(config) {
    YAHOO.ext.util.Config.apply(this, config);
    var appendTo = document.body;
    var div = document.createElement('div');
    div.className = 'ymenubar';
    appendTo.appendChild(div);
    var tb = document.createElement('table');
    tb.boder = 0;
    tb.cellPadding = 0;
    tb.cellSpacing = 0;
    div.appendChild(tb);

    var tbody = document.createElement('tbody');
    tb.appendChild(tbody);
    
    this.el = getEl(div, true);
    this.container = getEl(div, true);
    this.container.setVisible(false);
    this.tbody = tbody;
    this.children = [];
    this.menuItems = [];
    this.padding_left = 0;
    this.padding_bottom = 0;
    this.init(config);
};
YAHOO.ext.Menu.prototype = {
    init: function(config) {
        if (!config)
            return;
        if (this.id)
            YAHOO.ext.MenuDB.menu[this.id] = this;
        for (var i = 0; i < config.length; i++) {
            var item = config[i];
            var isSep = item['separator'];
            var isTextItem = item['textItem'];
            var subMenu = item['subMenu'];
  
            if (isSep)
                this.addSeparator();
            else if (isTextItem)
                this.addText(item.text);
            else if (subMenu)
                this.addSubMenu(item);
            else   
                this.addItem(item);
        }
    },
    add: function() {
        for (var i = 0; i < arguments.length; i++) {
            var el = arguments[i];
            var tr = document.createElement('tr');
            var td = document.createElement('td');
            tr.appendChild(td);
            this.tbody.appendChild(tr);
         
            if (el instanceof YAHOO.ext.MenuItem) {
                el.init(td, tr);
            } else if (el instanceof Array) {
                this.addItem(el);
            } else if (typeof el == 'string') {
                var span = document.createElement('span');
                if (el == 'separator') {
                    span.className = 'ymb-sep';
                } else {
                    span.innerHTML = el;
                    span.className = 'ymb-span';
                }
                td.appendChild(span);
            } else if (typeof el == 'object') {
                td.appendChild(el);
            }
        }
    },
    /**
     * @public
     * @param {Object} config
     */
    addItem: function(config) {
        if(config instanceof Array){
            var items = [];
            for (var i = 0, len = config.length; i < len; i++)
                items.push(this.addItem(config[i]));
            return items;
        }
  
        var m = config;
        if(!(config instanceof YAHOO.ext.MenuItem)) {
            YAHOO.ext.util.Config.apply(config,
	                                    {
                                            mouseover: this.onMouseOver,
                                            parent: this
                                        });
            m = new YAHOO.ext.MenuItem(config);
        }

        this.add(m);
        this.menuItems.push(m);
        return m;
    },
    addSubMenu:function(config) {
        var sub = config['subMenu'];
        var subMenu = YAHOO.ext.MenuHelper.createMenu(sub);
        YAHOO.ext.util.Config.apply(config,
                                    {
                                        menu: subMenu,
                                        hasChild: true,
                                        isLabel: true
                                    });
        var MenuItem = this.addItem(config);
        this.children.push(subMenu);
        subMenu.label = MenuItem;
    },
    addSeparator: function() {
        var tr = document.createElement('tr');
        var td = document.createElement('td');
        this.tbody.appendChild(tr);
        tr.appendChild(td);
        td.className = 'ymb-sep';
    },
    addText : function(text) {
        var tr = document.createElement('tr');
        var td = document.createElement('td');
        var span = document.createElement('span');
        this.tbody.appendChild(tr);
        tr.appendChild(td);
        td.appendChild(span);
        span.className = 'ymb-span';
        span.innerHTML = text;
    },
    removeItem: function(menuItem) {
        for (var i = 0; i < this.menuItems.length; i++) {
            var tmp = this.menuItems[i];
            if (!tmp)
                continue;
            if (menuItem == tmp) {
                this.tbody.removeChild(menuItem.el.dom);
                this.menuItems.splice(i, 1);
                break;
            }
        }
    },
    onMouseOver: function(e, o) {
        var menu = o.parent;
        var oTarget = e.getTarget();
        for (var i = 0; i < menu.menuItems.length; i++) {
            var item = menu.menuItems[i];
            if (item instanceof YAHOO.ext.MenuItem) {
                if (item.menu)
                    YAHOO.ext.MenuHelper.hideMenu({menu: item.menu});
            }
            var el = getEl(item);
            if (el && oTarget != el.dom && !YAHOO.util.Dom.isAncestor(el.dom, oTarget)) {
                if (item.isLabel)
                    item.removeMouseOverClass();
            }
        }
        if (o.menu) {
            if (o.menu.label)
                o.menu.label.addMouseOverClass();
            YAHOO.ext.MenuHelper.openMenu(o);
        }
    },
    onClick : function(e, o) {
        var oTarget = e.getTarget();
        var el = getEl(o['id']);
        if (el.dom != oTarget
            && !YAHOO.util.Dom.isAncestor(el.dom, oTarget)
            && !YAHOO.util.Dom.isAncestor(this['menu'].dom, oTarget)) {
            this['menu'].hideAll();
        }
    },
    showAt: function(el, hasChild) {
        var menu = getEl(this.container);
        var el = getEl(el);
        var bottom = el.getBottom(false);
        var left = el.getLeft(false);

        left += this.padding_left;
        bottom += this.padding_bottom;

        if (hasChild) {
            left = el.getRight(false);
            bottom -= el.getHeight(false);
        }
        var viewWidth = YAHOO.util.Dom.getViewportWidth();
        var myWidth = this.container.getWidth(false);
        if (left + myWidth > viewWidth)
            left = el.getLeft(false) - myWidth;

        var viewHeight = YAHOO.util.Dom.getViewportHeight();
        var myHeight = this.container.getHeight(false);
        if (bottom + myHeight > viewHeight)
            bottom = el.getBottom(false) - myHeight;

        menu.setXY([left, bottom]);
        menu.setVisible(true);
    },
    showAtPos: function(pos) {
        var menu = getEl(this.container);
        var left = pos[0];
        var bottom = pos[1];

        left += this.padding_left;
        bottom += this.padding_bottom;

        var viewWidth = YAHOO.util.Dom.getViewportWidth();
        var myWidth = this.container.getWidth(false);
        if (left > viewWidth)
            left = viewWidth - myWidth;
        else if (left + myWidth > viewWidth)
            left = left - myWidth;

        var viewHeight = YAHOO.util.Dom.getViewportHeight();
        var myHeight = this.container.getHeight(false);
        if (bottom > viewHeight)
            bottom = viewHeight - myHeight;
        else if (bottom + myHeight > viewHeight)
            bottom = bottom - myHeight;

        menu.setXY([left, bottom]);
        menu.setVisible(true);
    },
    hide: function() {
        var menu = getEl(this.container);
        menu.setVisible(false);
    },
    hideAll: function() {
        for (var i = 0; i < this.children.length; i++) {
            var subMenu = this.children[i];
            if (subMenu.label)
                subMenu.label.removeMouseOverClass();
            if (subMenu.children.length > 0 && subMenu.children[i].isVisible())
                subMenu.children[i].hideAll();
            subMenu.hide();
        }
        this.hide();
    },
    isVisible: function() {
        var menu = getEl(this.container);
        return menu.isVisible();
    },
    setPaddingLeft: function(num) {
        this.padding_left = num;
    },
    setPaddingBottom: function(num) {
        this.padding_bottom = num;
    }
};

YAHOO.ext.MenuMon = function(config) {
    this.doc = getEl(document.body);
    this.wrappedFn = null;
    YAHOO.ext.util.Config.apply(this, config);
};

YAHOO.ext.MenuMon.prototype = {
    onDocumentClick : function(e) {
        if (!this.id) {
            if (this.menu.isVisible())
                this.menu.hideAll();
            return;
        }
        var el = getEl(this.id, true);
        if (!el || !el.dom) {
            if (this.menu.isVisible())
            this.menu.hideAll();
            return;
        }
        var oTarget = e.getTarget();
        if (el.dom != oTarget && !YAHOO.util.Dom.isAncestor(el.dom, oTarget)) {
            if (this['menu'].isVisible())
	            this['menu'].hideAll();
        }
//        alert('click doc, fn=' + this.wrappedFn);  //just for debug
        if (this.wrappedFn) {
//         this.doc.removeListener('click', this.onDocumentClick, this);
//         this.doc.removeListener('click', this.wrappedFn, this);
//         YAHOO.ext.EventManager.removeListener(this.doc.dom, 'click', this.wrappedFn);
            this.wrappedFn = null;
        }
    },
    setClick: function(){
        if (this.clickSet)
            return;
        this.clickSet = true;
        this.wrappedFn = this.doc.mon('click', this.onDocumentClick, this, true);
    }
};

YAHOO.ext.MenuHelper = new function() {
    this.openMenu = function(o) {
        var m = o['menu'];
        if (!m || !(m instanceof YAHOO.ext.Menu))
            return;
        m.showAt(o['id'], o['hasChild']);
        if (!o.oMon) {
            o.oMon = new YAHOO.ext.MenuMon(o);
            o.oMon.setClick();
        }
    };
    this.openMenuAt = function(o) {
        var m = o.menu;
        if (!m || !(m instanceof YAHOO.ext.Menu))
            return;
        var el = getEl(m, true);
        m.showAtPos(o['pos']);
        if (!o.oMon) {
            o.oMon = new YAHOO.ext.MenuMon(o);
            o.oMon.setClick();
        }
    };
    this.setupContentMenu = function(o) {
        if (!o || !o.menu) {
            alert('please check you menu config!')
            return;
        }
        var container = o.container;
        if (!container)
            container = document.body;
        var element = document.createElement('div');
    
        container = getEl(container);
    
        function onDocRightClick(e) {
            var pos = e.getXY();
            YAHOO.ext.util.Config.apply(o, {pos: pos});
            this.openMenuAt(o);
            e.preventDefault();
        };
        container.mon('contextmenu', onDocRightClick, this, true);
    };
    this.hideMenu = function(o) {
        o.menu.hideAll();
    };
    this.createMenu = function(config) {
        if (!(config instanceof Array))
            return;
        var m = new YAHOO.ext.Menu(config);
        return m;
    };
    this.registerMenu = function(id, m) {
        if (m instanceof YAHOO.ext.Menu)
            YAHOO.ext.MenuDB.menu[id] = m;
    };
    this.removeMenu = function(id) {
        var menu = YAHOO.ext.MenuDB.menu[id];
        if (menu && menu.el && menu.el.dom) {
            menu.el.dom.parentNode.removeChild(menu.el.dom);
            YAHOO.ext.MenuDB.menu[id] = null;
        }
    };
    this.removeMenuItem = function(id) {
        var item = YAHOO.ext.MenuDB.menuItem[id];
        if (item && item.el && item.el.dom) {
            item.parent.removeItem(item);
            YAHOO.ext.MenuDB.menuItem[id] = null;
        }
    };
}();
menu.css
Code:
.ymenubar{
	z-index:1000;
	visibility:hidden;
	background-color: #D5E7FF;
	border: 1px solid #cbc7b8;
	padding:2px;
	padding: 1px 2px 1px 2px;
	position: absolute;
	display: block;
	border-width:1px;
	border-color:rgb(192,192,192) black black rgb(192,192,192);
}

.ymenubar table,.ymenubar tbody.ymenubar tr,.ymenubar td,.ymenubar div{
	font:normal 8pt tahoma, helvetica, arial, sans-serif;
	padding:4px 0px;
}

.ymenubar span {
	font:normal 8pt tahoma, helvetica, arial, sans-serif;
	padding:4px 20px;
}

.ymenubar .ymb-text{
	font:normal 8pt tahoma, helvetica, arial, sans-serif;
	padding:4px 0px;
}

.ymenubar .ymb-sep2{
	height: 1px;
	background: blue;
	background-repeat: no-repeat;
}
.ymenubar .ymb-sep{
	background-image: url(../images/menu_sep.gif);
	background-position: center;
	background-repeat: repeat-x;
	display: block;
	cursor:default;
	height: 16px;
	padding-left: 0px;
}

.ymenubar .ymb-item-over{
	background-color:#0D2A72;
	color: #ffffff;
	cursor: default;
}