Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Tabs Component #870

Merged
merged 8 commits into from
Mar 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
class Tabs
constructor: (@el) ->
@$tabList = $(@el)
@$tabs = @$tabList.find("li:not(.tabs-dropdown)")
@tabs = @$tabs.toArray()
@$tabList.append("<li class='tabs-dropdown'><a href='#'></a><ul></ul></li>")
@$dropdown = @$tabList.find(".tabs-dropdown")
@setWidths()
@initEvents()

initEvents: ->
$(window).on "resize", @overflowTabs
@overflowTabs()

setWidths: ->
@tabWidths = @tabs.map (tab) ->
tab.offsetWidth
@totalTabsWidth = @tabWidths.reduce (previousValue, currentValue) ->
previousValue + currentValue

overflowTabs: =>
containerWidth = @$tabList[0].offsetWidth
@lastKnownWidth = containerWidth unless @lastKnownWidth
widthDifference = @totalTabsWidth - containerWidth
widthDifferenceWithDropdown = widthDifference + @dropdownWidth()
dropdownActive = @$dropdown.find("li").length

if containerWidth <= @lastKnownWidth
# The window is being sized down or we've just loaded the page
if (dropdownActive and widthDifferenceWithDropdown > 0) or (not dropdownActive and widthDifference > 0)
@hideTabsToFit(widthDifferenceWithDropdown)
if containerWidth > @lastKnownWidth
# The window is getting larger
@showTabsToFit(widthDifference)

@lastKnownWidth = containerWidth

dropdownWidth: ->
# If the dropdown isn't initiated we need to provide
# our best guess of the size it will take up
@$dropdown[0].offsetWidth or 50

hideTabsToFit: (widthDifference) ->
@$tabList.addClass("tabs-overflowed")
tabs = @tabs.slice().reverse()

for tab in tabs
# Bail if things are now fitting
return if widthDifference <= 0
# Skip items already in the dropdown or active
continue if $(tab).hasClass("in-dropdown") or $(tab).hasClass("active")

tabWidth = tab.offsetWidth
@totalTabsWidth -= tabWidth
widthDifference -= tabWidth
$(tab).appendTo(@$dropdown.find("ul")).addClass("in-dropdown")

showTabsToFit: (widthDifference) ->
for tab, i in @tabs.slice()
# Skip items that aren't already in the dropdown
continue unless $(tab).hasClass("in-dropdown")

# Get our tab's width from the array
# We can't measure it here because it's hidden in the dropdown
tabWidth = @tabWidths[i]

# Bail if there's no room for this tab
break if widthDifference + tabWidth > 0

@totalTabsWidth += tabWidth
widthDifference += tabWidth
$(tab).insertBefore(@$dropdown).removeClass("in-dropdown")

# Reset styles if our dropdown is now empty
if @$dropdown.find("li").length is 0
@$tabList.removeClass("tabs-overflowed")

window.onload = ->
new Tabs(el) for el in $(".tabs")
108 changes: 108 additions & 0 deletions backend/app/assets/stylesheets/spree/backend/components/_tabs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
.tabs {
@include display(flex);
margin: 1em 0;
border-bottom: 1px solid $color-border;
white-space: nowrap;

&,
ul {
padding-left: 0;
list-style: none;
}

a {
padding: 1em;
}
}

.tabs > li:not(.in-dropdown) {
@include flex-grow(0);
@include flex-shrink(0);

// Move down one pixel to sit on top of the ul's border-bottom
position: relative;
top: 1px;

> a {
display: block;
border: 1px solid $color-border;
border-radius: 2px 2px 0 0;
line-height: 1;
}

&:not(:first-child) > a {
border-left: none;
}

&:not(.active) > a {
background: $color-tbl-thead;
}

&.active > a,
&.active:hover {
background: white;
border-bottom-color: white;
color: $color-body-text;
}

&:not(.active):hover > a {
background: darken($color-tbl-thead, 5%);
color: $color-link;
}
}

.tabs-overflowed.tabs > li:not(.tabs-dropdown) {
@include flex-grow(1);
@include flex-shrink(1);
}

.tabs-dropdown {
@include flex-grow(0);
@include flex-shrink(0);
position: relative;

.tabs:not(.tabs-overflowed) & {
display: none;
}

> a {
position: relative;
background: white;
z-index: 1;

&:before {
content: "\f107";
font-family: FontAwesome;
-webkit-font-smoothing: antialiased;
}
}

&:hover > a {
background: white;
}

&:not(:hover) ul {
display: none;
}

ul {
@include position(absolute, calc(100% - 1px) 0 null null);
z-index: 1;
}
}

.tabs li.in-dropdown {
a {
display: block;
border: 1px solid $color-border;
background: white;
}

&:not(:first-child) a {
border-top: none;
}

&:last-child a {
border-radius: 0 0 3px 3px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@import 'spree/backend/components/sidebar';
@import 'spree/backend/components/number_field_update';
@import 'spree/backend/components/stock_table';
@import 'spree/backend/components/tabs';

@import 'font-awesome';
@import 'spree/backend/plugins/powertip';
Expand Down
3 changes: 3 additions & 0 deletions backend/app/controllers/spree/admin/style_guide_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ def index
'building_forms',
'validation'
],
components: [
'tabs'
],
messaging: [
'loading',
'flashes',
Expand Down
28 changes: 14 additions & 14 deletions backend/app/views/spree/admin/shared/_order_submenu.html.erb
Original file line number Diff line number Diff line change
@@ -1,61 +1,61 @@
<nav class="menu">
<ul data-hook="admin_order_tabs">
<nav>
<ul class="tabs" data-hook="admin_order_tabs">
<% if (@order.shipments.count == 0 || @order.shipped_shipments.count == 0) %>
<li<%== ' class="active"' if current == 'Cart' %> data-hook='admin_order_tabs_order_details'>
<li class="<%= "active" if current == "Cart" %>" data-hook='admin_order_tabs_order_details'>
<%= link_to_with_icon 'shopping-cart', Spree.t(:cart), cart_admin_order_url(@order) %>
</li>
<% end %>

<% if checkout_steps.include?("address") %>
<li<%== ' class="active"' if current == 'Customer Details' %> data-hook='admin_order_tabs_customer_details'>
<li class="<%= "active" if (current == "Customer Details") %>" data-hook='admin_order_tabs_customer_details'>
<% if can?(:update, @order) %>
<%= link_to_with_icon 'user', Spree.t(:customer_details), edit_admin_order_customer_url(@order) %>
<%= link_to_with_icon 'user', Spree.t(:customer), edit_admin_order_customer_url(@order) %>
<% else %>
<%= link_to_with_icon 'user', Spree.t(:customer_details), admin_order_customer_url(@order) %>
<%= link_to_with_icon 'user', Spree.t(:customer), admin_order_customer_url(@order) %>
<% end %>
</li>
<% end %>

<li<%== ' class="active"' if current == 'Shipments' %> data-hook='admin_order_tabs_order_details'>
<li class="<%= "active" if current == "Shipments" %>" data-hook='admin_order_tabs_order_details'>
<%= link_to_with_icon 'edit', Spree::Shipment.model_name.human(count: :other), edit_admin_order_url(@order) %>
</li>

<% if can? :display, Spree::Adjustment %>
<li<%== ' class="active"' if current == 'Adjustments' %> data-hook='admin_order_tabs_adjustments'>
<li class="<%= "active" if current == "Adjustments" %>" data-hook='admin_order_tabs_adjustments'>
<%= link_to_with_icon 'cogs', Spree::Adjustment.model_name.human(count: :other), admin_order_adjustments_url(@order) %>
</li>
<% end %>

<% if can?(:display, Spree::Payment) %>
<li<%== ' class="active"' if current == 'Payments' %> data-hook='admin_order_tabs_payments'>
<li class="<%= "active" if current == "Payments" %>" data-hook='admin_order_tabs_payments'>
<%= link_to_with_icon 'credit-card', Spree::Payment.model_name.human(count: :other), admin_order_payments_url(@order) %>
</li>
<% end %>

<% if [email protected]? && can?(:update, @order) %>
<li<%== ' class="active"' if current == 'Confirm' %> data-hook='admin_order_tabs_confirm'>
<li class="<%= "active" if current == "Confirm" %>" data-hook='admin_order_tabs_confirm'>
<%= link_to_with_icon 'check', Spree.t(:confirm), confirm_admin_order_url(@order) %>
</li>
<% end %>

<% if can? :display, Spree::ReturnAuthorization %>
<% if @order.completed? %>
<li<%== ' class="active"' if current == 'Return Authorizations' %> data-hook='admin_order_tabs_return_authorizations'>
<%= link_to_with_icon 'share', Spree::ReturnAuthorization.model_name.human(count: :other), admin_order_return_authorizations_url(@order) %>
<li class="tab <%= "active" if current == "Return Authorizations" %>" data-hook='admin_order_tabs_return_authorizations'>
<%= link_to_with_icon 'share', Spree.t('admin.tab.rma'), admin_order_return_authorizations_url(@order) %>
</li>
<% end %>
<% end %>

<% if can? :display, Spree::CustomerReturn %>
<% if @order.completed? %>
<li<%== ' class="active"' if current == 'Customer Returns' %>>
<li class="<%= "active" if current == "Customer Returns" %>">
<%= link_to_with_icon 'download', Spree::CustomerReturn.model_name.human(count: :other), admin_order_customer_returns_url(@order) %>
</li>
<% end %>
<% end %>

<% if can?(:manage, Spree::OrderCancellations) && @order.inventory_units.cancelable.present? %>
<%= content_tag('li', :class => ('active' if current == 'Cancel Inventory'), :data => {:hook => 'admin_order_tabs_cancel_inventory'}) do %>
<%= content_tag('li', class: "#{'active' if current == 'Cancel Inventory'}", :data => {:hook => 'admin_order_tabs_cancel_inventory'}) do %>
<%= link_to_with_icon 'cancel', Spree.t(:cancel_inventory), admin_order_cancellations_path(@order) %>
<% end %>
<% end %>
Expand Down
3 changes: 3 additions & 0 deletions backend/app/views/spree/admin/shared/_order_tabs.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@

<% content_for :sidebar do %>
<%= render "spree/admin/shared/order_summary", checkout_steps: @order.checkout_steps %>
<% end %>

<% content_for :tabs do %>
<%= render "spree/admin/shared/order_submenu", current: current, checkout_steps: @order.checkout_steps %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<%- snippet = capture do %>
<ul class="tabs">
<li class="active"><a href="#">Product Details</a></li>
<li><a href="#">Images</a></li>
<li><a href="#">Variants</a></li>
<li><a href="#">Product Properties</a></li>
<li><a href="#">Stock Management</a></li>
</ul>
<%- end %>

<div class="style-guide-result">
<%= snippet %>
</div>

<div class="style-guide-code">
<pre><code class="language-html"><%= escape_once snippet %></code></pre>
</div>
5 changes: 5 additions & 0 deletions backend/app/views/spree/layouts/admin.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<div class="container">
<div class="row">
<div class="<%= 'with-sidebar ' if content_for?(:sidebar) %>" id="content" data-hook>
<% if content_for?(:tabs) %>
<div class="sixteen columns">
<%= yield :tabs %>
</div>
<% end %>
<div class="<%= if content_for?(:sidebar) then 'twelve' else 'sixteen' end %> columns">
<%= render :partial => 'spree/admin/shared/table_filter' %>
<%= yield %>
Expand Down
2 changes: 1 addition & 1 deletion backend/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
end
end

resources :style_guide
resources :style_guide, only: [:index]
end

get '/admin', to: 'admin/root#index', as: :admin
Expand Down
Loading