React-Select, Multi Select and Text Overflow
Asked Answered
B

4

17

I am using React-Select component with multi select. One of the problems I am facing is that if the user select 3 or 4 options the UI looks pretty bad because the text begins to overflow and that causes the component to grow either horizontally and vertically.

I want to have a behavior where the size of the component remains the same and if the user selects more options then it just shows "..." (ellipsis) rather than try to show the newly selected options.

The behavior I want is more inline with this component

http://instructure-react.github.io/react-select-box/

See how it handles multi-select.

I don't want to swap out components now because we have done lots of testing with React-Select.

Can you give me some guide lines on how to achieve this without removing react-select.

Buckingham answered 2/2, 2016 at 15:44 Comment(3)
You should add some css to confine react-select withing its parent container. e.g max-width:100% and give some width to its parent container.Rathskeller
I don't know what CSS I should add to get the desired behavior. the idea is that rather than it growing infinitely it should just show ellipsis after 3 (or x) items have been selected.Buckingham
@Knows Not Much Any solution for this?Talia
I
8

i've managed to achieve both the ellipsis effect and leaving the display at one row, here is a working example https://codesandbox.io/s/v638kx67w7 hope this helps

Ivey answered 2/1, 2019 at 18:47 Comment(2)
When you have longer labels that extend beyond the box and you click again on the caret the whole contents of the value container gets shifted to the left. Somehow a new input element gets created to the right of the text. Could you ever solve this?Thorny
@GregHolst I fixed this by setting searchable={true} and then providing Input component which just renders null (Input: () => null) and therefore it doesn't get added to the right of the text. This comes with the caviats though, but you can work around it.Kittle
I
2

I solved this without losing the Input component like this;

import Select, { components as RSComponents } from "react-select";
   

const ValueContainer = ({ selectProps, children, ...props }) => {
    let [values, input] = children;

    if (Array.isArray(values)) {
      values = selectProps.value.map((x) => x.label).join(', ');
    }

    return (
      <RSComponents.ValueContainer {...props}>
        <div style={{
          maxWidth: "80%",
          whiteSpace: "nowrap",
          textOverflow: "ellipsis",
          overflow: "hidden",
        }}>
          {values}
         </div>
        {input}
      </RSComponents.ValueContainer>
    );
};

const customStyles = useMemo(() => ({
    valueContainer: (provided, state) => ({
        ...provided,
        whiteSpace: "nowrap",
        overflow: "hidden",
        flexWrap: 'nowrap',
    }),
    input: (provided, state) => ({
        ...provided,
        minWidth: '20%'
    }),
}), []);

<Select
    components={{ ValueContainer }}
    isMulti
    styles={customStyles}
    ...
/>
Indiscreet answered 22/8, 2021 at 10:39 Comment(0)
H
0

Just do menuPosition="fixed".

Reference: https://github.com/JedWatson/react-select/issues/810#issuecomment-561551914

Hydrocarbon answered 20/6 at 13:55 Comment(0)
R
-2

This is the generated Html for given react-select element

. react-select-box-container {
  position: relative;
  width: 240px;
  display: inline-block;
  background-color: #fff;
  border-radius: 4px;
  text-align: left;
  box-shadow: 0 0 2px rgba(0, 0, 0, .3);
}

.react-select-box {
  padding: 15px 0;
  display: inline-block;
  cursor: pointer;
  border: none;
  width: 100%;
  text-align: left;
  background-color: transparent;
}

.react-select-box:focus {
  outline: 0;
  box-shadow: 0 0 4px #0493D1;
}

.react-select-box:before {
  content: ' ';
  z-index: 1;
  position: absolute;
  height: 20px;
  top: 15px;
  right: 34px;
  border-left: 1px solid #CBD2D7;
}

.react-select-box:after {
  content: ' ';
  position: absolute;
  z-index: 1;
  top: 23px;
  right: 13px;
  border-top: 6px solid #7B8E9B;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
}

.react-select-box-label,
.react-select-box-option {
  line-height: 16px;
  font-size: 12px;
  font-weight: bold;
  color: #7B8E9B;
}

.react-select-box-label {
  padding: 0 40px 0 20px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #0493D1;
}

.react-select-box-empty .react-select-box-label {
  color: #7B8E9B;
}

.react-select-box-click-outside-layer {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
}

.react-select-box-clear {
  position: absolute;
  top: 15px;
  right: 0;
  width: 35px;
  height: 20px;
  background-color: #fff;
  text-indent: -9999em;
  z-index: 3;
  border: none;
}

.react-select-box-clear:before {
  content: '×';
  position: absolute;
  top: 2px;
  left: 10px;
  z-index: 1;
  background-color: #7B8E9B;
  border-radius: 100%;
  font-size: 13px;
  color: #fff;
  line-height: 1;
  width: 15px;
  height: 15px;
  text-indent: 0;
  text-align: center;
}

.react-select-box-clear:hover,
.react-select-box-clear:focus {
  outline: 0;
}

.react-select-box-clear:hover:before,
.react-select-box-clear:focus:before {
  background-color: #0493D1;
}

.react-select-box-hidden {
  display: none
}

.react-select-box-options {
  margin: 2px 0 0;
  position: absolute;
  padding: 10px 0;
  width: 240px;
  top: 100%;
  left: 0;
  z-index: 4;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 0 2px rgba(0, 0, 0, .3);
}

.react-select-box-options-list {
  list-style: none outside;
  margin: 0;
  padding: 0;
}

.react-select-box-option {
  padding: 10px 20px;
  margin: 0;
  cursor: pointer;
  display: block;
  line-height: 1.2;
  text-decoration: none;
}

.react-select-box-option:hover {
  color: #0493D1;
  background-color: #f4f4f4;
}

.react-select-box-option-selected {
  color: #CBD2D7;
}

.react-select-box-multi .react-select-box-option {
  padding-left: 42px;
  position: relative;
}

.react-select-box-multi .react-select-box-option:before {
  content: ' ';
  position: absolute;
  line-height: 1;
  text-align: center;
  left: 20px;
  top: 9px;
  border-radius: 3px;
  height: 12px;
  width: 12px;
  margin-right: 10px;
  border: 1px solid #7B8E9B;
  background: #f9f9f9;
  vertical-align: middle;
}

.react-select-box-multi .react-select-box-option-selected:before {
  content: '✓';
}

.react-select-box-multi .react-select-box-option-selected {
  color: #1F3344;
}

.react-select-box-option:focus,
.react-select-box-option-focused {
  color: #0493D1;
  outline: 0;
  background-color: #DDE2E5;
}

.react-select-box-close {
  color: #0493D1;
  text-transform: uppercase;
  background-color: transparent;
  border: none;
  padding: 5px 0;
  display: block;
  text-align: center;
  width: 100%;
  font-weight: bold;
  cursor: pointer;
  outline: none;
}

.react-select-box-close:hover,
.react-select-box-close:focus {
  text-decoration: underline;
}

.react-select-box-empty .react-select-box-close {
  color: #CBD2D7;
}

.react-select-box-native {
  position: absolute;
  left: -99999em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div class="react-select-box-container react-select-box-multi react-select-box-empty">
  <button id="react-select-box-2" class="react-select-box" tabindex="0" aria-hidden="true">
        <div class="react-select-box-label">
          Favorite Colors
        </div></button>

  <div class="react-select-box-options react-select-box-hidden" aria-hidden="true" tabindex="0">
    <div class="react-select-box-off-screen">
      <a id="react-select-box-2-0" href="#" class="react-select-box-option" tabindex="-1">Red</a>
      <a id="react-select-box-2-1" href="#" class="react-select-box-option" tabindex="-1">Green</a>
      <a id="react-select-box-2-2" href="#" class="react-select-box-option" tabindex="-1">Blue</a>
    </div>
    <button class="react-select-box-close">Close</button>
  </div>

  <div class="react-select-box-native">
    <label for="react-select-box-2-native-select">Favorite Colors</label>
    <select id="react-select-box-2-native-select" multiple="multiple">
            <option value="red">
              Red
            </option>
    
            <option value="green">
              Green
            </option>
    
            <option value="blue">
              Blue
            </option>
          </select>
  </div>
</div>
Rathskeller answered 3/2, 2016 at 8:45 Comment(3)
let me give this a tryBuckingham
Doesn't change the behavior for meEffrontery
@ryan4888 use some inline css styles thenRathskeller

© 2022 - 2024 — McMap. All rights reserved.