React 月份选择器的样式问题
Styling issues with React month picker
我使用 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 && 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
我对代码做了一些修改:
- 已将 class 分配给 yearNav 并选择了下一个元素来为其设置样式。可能是因为我无法在代码中的 monthContainer 之前找到 div。将元素设为列设置为 3 的内联网格容器。
- 将按钮的
min-width
增加到 45px。
- 删除行 class 并将其包裹在
container-fluid
中。这消除了您在评论中谈论的不均匀填充。
- 如果你想在移动设备上以更好的方式展示它,我已经包含了媒体查询,这样宽度就可以了。
Codesandbox 编辑器:https://codesandbox.io/s/heuristic-night-fvllg?file=/src/App.js
我使用 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 && 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
我对代码做了一些修改:
- 已将 class 分配给 yearNav 并选择了下一个元素来为其设置样式。可能是因为我无法在代码中的 monthContainer 之前找到 div。将元素设为列设置为 3 的内联网格容器。
- 将按钮的
min-width
增加到 45px。 - 删除行 class 并将其包裹在
container-fluid
中。这消除了您在评论中谈论的不均匀填充。 - 如果你想在移动设备上以更好的方式展示它,我已经包含了媒体查询,这样宽度就可以了。
Codesandbox 编辑器:https://codesandbox.io/s/heuristic-night-fvllg?file=/src/App.js