Проблемы с оформлением с помощью средства выбора месяца React

#css #reactjs #twitter-bootstrap #flexbox #react-bootstrap

#css #reactjs #twitter-bootstrap #flexbox #react-bootstrap

Вопрос:

Я создал средство выбора диапазона месяцев с помощью React, и у меня возникли некоторые проблемы со стилем. Размеры кнопок слишком велики, что увеличивает размер всплывающего окна.

Это мой код:

 import React, { FunctionComponent, useEffect, useReducer } from "react";
import {
  Button,
  Popover,
  Intent,
  Position,
  Tag,
  Icon
} from "@blueprintjs/core";
import { Row, Col } from "react-bootstrap";
import { IconNames } from "@blueprintjs/icons";

const monthNames = [
  "",
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec"
];

const MonthSelector = ({ month, year, onSelectYear, startYear, endYear }) => {
  const [state, setState] = useReducer(
    (state, newState) => ({
      ...state,
      ...newState
    }),
    {
      yearState: year,
      monthState: month
    }
  );

  useEffect(() => {
    onSelectYear({
      month: state.monthState,
      year: state.yearState
    });
  }, [state]);

  const styles = {
    yearNav: {
      display: "flex",
      alignItems: "center",
      margin: "0 1px 5px"
    },
    yearButton: {
      flex: "1",
      textAlign: "center",
      margin: "0 2px"
    },
    yearButtonText: {
      verticalAlign: "middle",
      fontWeight: "bold"
    },
    monthContainer: {
      display: "inline-block",
      padding: "1px",
      width: "33.33%",
      boxSizing: "border-box"
    },
    monthButton: {
      lineHeight: "3em",
      textAlign: "center",
      width: "100%"
    }
  };

  const onPrevYear = () => {
    setState({ yearState: state.yearState - 1 });
  };

  const onNextYear = () => {
    setState({ yearState: state.yearState   1 });
  };

  const onSelect = (month) => {
    setState({ monthState: month });
  };

  const renderMonth = (monthItem) => {
    const selected = month === monthItem amp;amp; year === state.yearState;

    return (
      <div style={styles.monthContainer} key={monthItem}>
        <Button
          intent={selected ? Intent.PRIMARY : Intent.NONE}
          style={styles.monthButton}
          onClick={() => onSelect(monthItem)}
        >
          {monthNames[monthItem]}
        </Button>
      </div>
    );
  };

  const months = [];
  for (let i = 1; i <= 12; i  ) {
    months.push(renderMonth(i));
  }

  console.log("yearState", state.yearState);
  console.log("startYear.year", startYear.year);

  return (
    <div>
      <div style={styles.yearNav}>
        <Button
          small
          onClick={onPrevYear}
          icon={IconNames.CHEVRON_LEFT}
          minimal
          disabled={state.yearState <= startYear.year}
        />
        <div style={styles.yearButton}>
          <span style={styles.yearButtonText} className="block-header">
            {state.yearState}
          </span>
        </div>
        <Button
          small
          onClick={onNextYear}
          icon={IconNames.CHEVRON_RIGHT}
          minimal
          disabled={state.yearState >= endYear.year}
        />
      </div>
      <div style={styles.months}>{months}</div>
    </div>
  );
};

const MonthRangePicker = ({ startYear, endYear, onChange }) => {
  const [state, setState] = useReducer(
    (state, newState) => ({
      ...state,
      ...newState
    }),
    {
      startState: startYear,
      endState: endYear
    }
  );

  useEffect(() => {
    onChange(state.startState, state.endState);
  }, [state]);

  const onSetStart = (startState) => {
    setState({ startState });
  };

  const onSetEnd = (endState) => {
    setState({ endState });
  };

  console.log("month picker state", state);

  return (
    <Popover
      position={Position.BOTTOM}
      fill
      content={
        <React.Fragment>
          <div className="text-center p-1">
            <Tag large>{`${monthNames[state.startState.month]}-${
              state.startState.year
            }`}</Tag>
            <Icon icon={IconNames.ARROW_RIGHT} iconSize={20} />
            <Tag large>{`${monthNames[state.endState.month]}-${
              state.endState.year
            }`}</Tag>
          </div>
          <Row className="container-fluid">
            <Col className="form-group" md={6}>
              <MonthSelector
                month={state.startState.month}
                year={state.startState.year}
                onSelectYear={onSetStart}
                startYear={startYear}
                endYear={endYear}
              />
            </Col>
            <Col className="form-group" md={6}>
              <MonthSelector
                month={state.endState.month}
                year={state.endState.year}
                onSelectYear={onSetEnd}
                startYear={startYear}
                endYear={endYear}
              />
            </Col>
          </Row>
        </React.Fragment>
      }
    >
      <div className="d-flex justify-content-center">
        <Button
          className="text-center"
          intent={Intent.PRIMARY}
          text="Open Month Range Picker"
        />
      </div>
    </Popover>
  );
};

export default MonthRangePicker;
  

Исходный результат:

введите описание изображения здесь

Ожидаемый результат: аналогичный стиль, как

введите описание изображения здесь

Я хочу, чтобы кнопки были расположены рядом в соответствии с ожидаемым результатом, чтобы всплывающее окно не имело большой ширины. Пожалуйста, посоветуйте.

Вот мой код:

https://codesandbox.io/s/admiring-mendeleev-efglm?file=/src/App.js:0-4841

Комментарии:

1. Вы ищете что-то подобное? nimb.ws/53lmGW

2. Нет. Мне нужна сетка 3×4 для месяцев, но в более сжатом виде с плотно упакованными кнопками. Спасибо

3. Или это так? nimb.ws/p41Fk6

4. Да, это работает.

5. Не могли бы вы опубликовать решение, пожалуйста?

Ответ №1:

Я внес несколько изменений в код:

  1. Присвоил класс yearNav и выбрал следующий элемент для его стилизации. Вероятно, потому, что я не смог найти div до monthContainer в коде. Сделал элемент в виде встроенного контейнера сетки со столбцами, равными 3.
  2. Увеличено min-width количество кнопок до 45 пикселей.
  3. Удалил класс Row и завернул его внутрь container-fluid . Это избавляет от неравномерного заполнения, о котором вы говорили в комментариях.
  4. Если вы хотите лучше отображать его на мобильных устройствах, я включил медиа-запрос, чтобы ширина была в порядке.

Редактор Codesandbox: https://codesandbox.io/s/heuristic-night-fvllg?file=/src/App.js

Вывод Codesandbox

Комментарии:

1. месяцы расположены по прямой линии. Не могли бы вы обновить ссылку?

2. Я использовал ту же ссылку, чтобы получить снимок экрана.