How can I make sematic-ui-react Tab responsive?
Asked Answered
R

3

5

I'm developing a react application and I recently start to use semantic ui react module.

Unfortunately I'm not able to make the Tab object responsive...

A really simple script to show this is:

import React from 'react'
import { withRouter } from 'react-router-dom'

import {Tab} from 'semantic-ui-react';

// import NavSection from './NavSection'

var sections = ["SectionA","SectionB","SectionC","SectionD","SectionE","SectionF"]

const NavigatorHeader = () => (
<div>
  <h1>Navigator</h1>
  <div>
    <Tab menu={{ pointing: true }} panes={getPanes(sections)} />
  </div>
</div>
)

export default withRouter(NavigatorHeader)


function getPanes(sections){
  return sections.map( function(section){
    return {
      menuItem: section,
      render: () =>
        <Tab.Pane attacched="false">
          <div>
            <p>
            Some Text that we can change tab from tab. E.g. with the title: <b>{section}</b>
            </p>
          </div>
        </Tab.Pane>
    }
  })
}

The tabs look great, inline, but if I reduce the screen they just overflow, while I was expecting they would have moved to a second line.

Look like that this is coming from the Selenium-ui css I'm using (https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css). Current version is 2.3.1 but if I go back to use a version before 2.0.0, it was responsive.. is there a way to obtain the same behavior with the new version?

Thanks, Michele. Thanks, Michele.

Rubenstein answered 28/3, 2018 at 15:7 Comment(0)
R
14

Based on the previous answer I found an easier way to achieve this.

I defined a CSS with the values suggested:

.wrapped{
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

and then just passed that additional class to the menu

<Tab menu={{ pointing: true, className: "wrapped" }} panes={getPanes(sections)} />

That solved the problem without any additional javascript.

Rubenstein answered 23/4, 2018 at 15:57 Comment(1)
This worked for me, but I also had to add width: 83vw to make it wrap to multiple rows and keep it on the screen.Bladdernut
S
2

Here is a solution that I created some time ago in regular Semantic. It behaves like Bootstrap and does not require a second set of menu items. It requires just a tiny bit of JS and CSS. The JS:

$(function() {
// Set up to handle wrapping of tab menu (tab actuator) items
    $(window).resize(function() {
      checkIfWrapped();
    });

    checkIfWrapped(); // Make sure the function is fired upon document ready
});

// Detect whether a Semantic UI tabular menu is wrapped
function checkIfWrapped() {
    var pos_top_1st = $('.tabular.menu .item').first().position().top;
    $('.tabular.menu .item:not(first-child)').each(function() {
        var pos_top = $(this).position().top;
        if (pos_top > pos_top_1st) {
            $(this).parent().addClass('wrapped');
            return;
        } else if (pos_top == pos_top_1st) {
            $(this).parent().removeClass('wrapped');
        }
    });

The HTML structure. (Note that placing the .tabular.menu .item-s inside a div within the overall .tabular.menu allows the use of a separate .right.menu within the .tabular.menu if desired) :

      <div id="tabs-menu" class="ui top attached tabular menu">
          <div id="qj-tabs">
              <div class="tab item"></div>
              <div class="tab item"></div>
              <div class="tab item"></div>
          </div>
          <div class="right menu">
              <a class="tab item"><i class="add icon"></i> Add Job</a>
              <a class="tab item"><i class="copy icon"></i> Copy Item</a>
          </div>
      </div>
          <div class="botttom attached tab segment"></div>
          <div class="botttom attached tab segment"></div>
    </div>

The CSS:

#qj-tabs {
  display: flex !important;   /* Will not work unless defined as display: flex */
  flex-direction: row !important;
  flex-wrap: wrap !important;
}

#tabs-menu .wrapped .item {
  border-radius: 5px !important;
  border: 1px lightgray solid !important; /*  Just styling for the default theme here */
  margin: 0 2px 2px 0 !important;
}

#tabs-menu .wrapped .active.item {
    background-color: lightgray;
}
Simony answered 7/4, 2018 at 20:13 Comment(3)
Thanks for this. A question: how do you trigger the function? are you setting a listener into the ComponentDidMount?Rubenstein
No. The first function shown (document ready function - $(function() { xxxxx }) sets things up so that if the window is re-sized, then checkIfWrapped() is fired. It also fires checkIfWrapped() upon document ready.Simony
I'm not using jQuery so I can't use directly this, but I think it put me in the right way.Rubenstein
X
2

This is what i did some weeks ago in regular Semanitic-ui.

! function($) {

  var WinReszier = (function() {
    var registered = [];
    var inited = false;
    var timer;
    var resize = function(ev) {
      clearTimeout(timer);
      timer = setTimeout(notify, 100);
    };
    var notify = function() {
      for (var i = 0, cnt = registered.length; i < cnt; i++) {
        registered[i].apply();
      }
    };
    return {
      register: function(fn) {
        registered.push(fn);
        if (inited === false) {
          $(window).bind('resize', resize);
          inited = true;
        }
      },
      unregister: function(fn) {
        for (var i = 0, cnt = registered.length; i < cnt; i++) {
          if (registered[i] == fn) {
            delete registered[i];
            break;
          }
        }
      }
    };
  }());

  var TabDrop = function(element, options) {
    this.element = $(element);
    var $this = this;
    this.dropdown = $('<div class="ui item right dropdown" data-popup data-content="' + options.text + '" data-position="bottom center">' +
      options.icon +
      '<div class="menu"></div>' +
      '</div>').appendTo($this.element);

    this.click = function() {
      $this.element.removeClass("pointing");
      $this.element.find("a.item").not(this).removeClass("active");
    };

    this.reverseclick = function(el) {
      $this.element.find(".item.right.dropdown .menu a.item").removeClass("active selected");
      $this.element.addClass("pointing");
    };

    WinReszier.register($.proxy(this.layout, this));
    this.layout();
    $(".ui.dropdown").dropdown();
    $("[data-popup]").popup();
  };

  TabDrop.prototype = {
    constructor: TabDrop,

    layout: function() {
      var $main = this;
      var $this = this.element;
      var $drpdwn = this.dropdown;
      var $fullwidth = $this.width() - 25;

      this.element
        .append($drpdwn.find('.ui.item.right'))
        .find('a.item')
        .not('.item.right.dropdown')
        .each(function() {
          var $blockLenght = parseInt($(this).width());
          var $space = $fullwidth - $blockLenght;
          if ($space > $blockLenght) {
            $(this).click($main.reverseclick)
            if ($drpdwn.find('.menu a').length > 0) {
              var $reverse = $drpdwn.find('.menu a:first-child');
              $reverse.click($main.reverseclick).removeClass("selected")
              $reverse.insertBefore($drpdwn);
            }
          } else {
            var $dropItem = $(this)
            $dropItem.click($main.click)
            $drpdwn.find('.menu').append($dropItem);
          }
          $fullwidth = $space;
        });
    }
  };

  $.fn.tabdrop = function(option) {
    return this.each(function() {
      var $this = $(this),
        data = $this.data('tabdrop'),
        options = typeof option === 'object' && option;
      if (!data) {
        $this.data('tabdrop', (data = new TabDrop(this, $.extend({},
          $.fn.tabdrop.defaults, options))));
      }
      if (typeof option == 'string') {
        data[option]();
      }

    });
  };

  $.fn.tabdrop.defaults = {
    text: 'More',
    icon: '<i class="icon align justify m-0"></i>'
  };

  $.fn.tabdrop.Constructor = TabDrop;

}(window.jQuery);

var Tabs = {
  tabDrop: function() {
    setTimeout(function() {
      $('.tabdrop').tabdrop({
        text: 'More Configuration'
      });
    }, 1000)
  }
};
$(document).on("ready", function() {
  $('.menu .item').tab();
  Tabs.tabDrop();
  $(window).resize(function() {
    Tabs.tabDrop();
  });
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.js"></script>
<div class="ui top attached pointing menu tabdrop">
  <a class="item" data-tab="tab1">Tab Item 1</a>
  <a class="item" data-tab="tab2">Tab Item 2</a>
  <a class="item" data-tab="tab3">Tab Item 3</a>
  <a class="item" data-tab="tab4">Tab Item 4</a>
  <a class="item" data-tab="tab5">Tab Item (A very long tab title)</a>
</div>
Xeroderma answered 12/9, 2018 at 16:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.