Here is a code snippet to do a full js tab for wicket (tabs on the left) : TabPanel
[java]
package com.theveniceproject.cow.editors.ui.widgets;

import java.util.List;

import org.apache.wicket.ResourceReference;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.Loop;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

public class TabPanel extends Panel {

    private List tabs;
    private IModel tabCount;
    
    private static final ResourceReference DEFAULT_CSS = new ResourceReference(LeftTabPanel.class, "css/TabPanel.css");

    public TabPanel(String id, List<AbstractTab> tabs) {
        super(id, new Model());
        setOutputMarkupId(true);
        
        checkTabs(tabs);
        
        add(HeaderContributor.forCss(getCss()));
        add(HeaderContributor.forJavaScript(LeftTabPanel.class, "TabPanel.js"));
        
        //create a model for the tabs size
        this.tabs = tabs;
        tabCount = new AbstractReadOnlyModel()
        {
            private static final long serialVersionUID = 1L;

            public Object getObject()
            {
                return new Integer(LeftTabPanel.this.tabs.size());
            }
        };
        createTabs();
        createContents();
    }
    
    /**
     * Return the css to use to layout tabs
     * @return the css to use to layout tabs
     */
    public ResourceReference getCss() {
        return DEFAULT_CSS;
    }

    @Override
    protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
        // TODO Auto-generated method stub
        super.onComponentTagBody(markupStream, openTag);
        getResponse().write("<script type=\"text/javascript\">var " + getMarkupId() + "Tabs = new TabManager('" + getMarkupId() + "'); ");   
    }
    
    /**
     * Method to check if tabs is all rightd
     * @param tabs tabs list
     */
    private void checkTabs(List<AbstractTab> tabs){
        if (tabs == null)
        {
            throw new IllegalArgumentException("argument [tabs] cannot be null");
        }

        if (tabs.size() < 1)
        {
            throw new IllegalArgumentException(
                    "argument [tabs] must contain a list of at least one tab");
        }
    }
    
    /**
     * Create tabs on the left of the component
     * @param tabsContainer
     */
    protected void createTabs(){
        add(new Loop("tabs", tabCount)
        {
            private static final long serialVersionUID = 1L;

            protected void populateItem(LoopItem item)
            {
                final int index = item.getIteration();
                final ITab tab = ((ITab)LeftTabPanel.this.tabs.get(index));
                
                final boolean selected = index == 0;
                
                WebMarkupContainer tabContent = new WebMarkupContainer("tab"){
                    @Override
                    protected void onComponentTag(ComponentTag tag) {
                        super.onComponentTag(tag);
                        tag.put("class", "tabs");
                        //connect onClick event
                        tag.put("onClick", LeftTabPanel.this.getMarkupId() + "Tabs.selectTab(this)");
                    } 
                   
                    @Override
                    protected void onBeforeRender() {
                        super.onBeforeRender();
                        if (selected){
                            add(new AttributeAppender("class", new Model("selected"), " "));
                        }
                    }
                };
                tabContent.add(new Label("title", tab.getTitle()));
                item.add(tabContent);
            }

        });
    }
    
    
    /**
     * Create the tab content using {@link AbstractTab} Panel
     */
    private void createContents(){
        add(new Loop("contents", tabCount)
        {
            private static final long serialVersionUID = 1L;

            protected void populateItem(LoopItem item)
            {
                final int index = item.getIteration();
                final ITab tab = ((ITab)LeftTabPanel.this.tabs.get(index));
                
                final boolean selected = index == 0;
                
                item.add(tab.getPanel("innerPanel"));
                
                if (!selected){
                    item.add(new AttributeAppender("style", true, new Model("display:none"), ";"));
                }
            }
        });
    }

}



TabPanel.html
<wicket:panel>
	<table width="100%" class="leftTab" cellpadding="0" cellspacing="0">
  		<tr valign="top">
			<td width="120px">
				<div wicket:id="tabs">
					<div wicket:id="tab">
						<span wicket:id="title"></span>
					</div>
				</div>
			</td>
			<td>
				<div class="content">
					<div  wicket:id="contents">
						<div wicket:id="innerPanel">
							content
						</div>
					</div>
				</div>
			</td>
		</tr>
	 </table>
</wicket:panel>


TabPanel.js
function TabManager(/**String*/ id){
	this.id = id;
	this.table = document.getElementById(id).getElementsByTagName("table")[0];
	
	/**
	 * Select the given tab and show its content
	 */
	this.selectTab = function(/** div */ tab){
		this._clearSelected();
		addClass(tab, "selected");
		this.setContentSelected(tab);
	}
	
	/**
	 * Return the list of domNode representing tabs
	 */
	this._getTabs /** Node[] */ = function(){
		return this.table.rows.item(0).cells.item(0).childNodes;
	}
	
	/**
	 * return the list of domNode Representing Content
	 */
	this._getContents /** Node[] */ = function(){
		return this.table.rows.item(0).cells.item(1).getElementsByTagName("div")[0].childNodes;
	}
	
	/**
	 * Clear Selection 
	 */
	this._clearSelected = function(){
		var tabs = this._getTabs();
		for (var i=0; i<tabs.length; i++){
			if (tabs[i].nodeName == "DIV"){
				removeClass(tabs[i].getElementsByTagName('div')[0], "selected");
			}
		}
	}
	
	/**
	 * Select the right Content making it visible block
	 */
	this.setContentSelected = function(/** div */ tab){
		var tabs = this._getTabs();
		var pos = 0;
		for (var i=0; i<tabs.length; i++){
			if (tabs[i].nodeName == "DIV"){
				if (tab == tabs[i].getElementsByTagName('div')[0]){
					break;
				}
				pos ++;
			}
		}
		var contents = this._getContents();
		var contentPos = 0;
		for (var i=0; i<contents.length; i++){
			if (contents[i].nodeName == "DIV"){
				if (contentPos == pos){
					contents[i].style.display="block";
				}else{
					contents[i].style.display="none";	
				}
				contentPos ++;
			}
		}
	}
}



function addClass(/**DomNode*/ node, /** String */ cssclass){
	if (!new RegExp('\\b'+cssclass+'\\b').test(node.className)){
		node.className+=node.className?' '+cssclass:cssclass;
	}
}

function removeClass(/**DomNode*/ node, /** String */ cssclass){
	var rep=node.className.match(' '+cssclass)?' '+cssclass:cssclass;
    node.className=node.className.replace(rep,'');
}


TabPanel.css
table.leftTab {
	border-spacing: 0px;
}

table.leftTab * div.tabs{
	padding:4px 15px 4px 6px;
	color:white;
	cursor:pointer;
	font-size:12px;
	font-weight:bold;
	white-space:nowrap;
	background-image: url('sidetabsDefault.gif');
	background-repeat: no-repeat;
}

table.leftTab * div.selected{
	color:blue;
	cursor: default;
	background-image: url('sidetabsSelected.gif');
}

table.leftTab * .content {
	border:2px solid blue;
	min-height: 300px;
	padding: 10px 25px 10px 25px;
	font-family:'Arial',sans-serif;
	font-size:12px;
}

table.leftTab * .content * table{
	font-family:'Arial',sans-serif;
	font-size:12px;
}

table.leftTab * .content * label{
	font-weight:bold;
	margin-right:50px;
}