Css 来自notistack的React Snackbar组件无法在其GUI中处理长文本,因为在窗口较小的情况下,文本会消失
我是一个新的反应界面库,如材料界面和notistack。在我的项目中,像这样的组件正在与一些样式/css一起使用。在整个react应用程序中,当有一个长的动态文本放在这个Snackbar组件中时,它的GUI会受到干扰,文本会被切断并从组件中消失。我该如何处理这些信息,并使其具有响应性,以便它能够处理其中很长的文本 以下是文件SanckbarProvider.tsx中Snackbar组件的代码Css 来自notistack的React Snackbar组件无法在其GUI中处理长文本,因为在窗口较小的情况下,文本会消失,css,reactjs,material-ui,snackbar,notistack,Css,Reactjs,Material Ui,Snackbar,Notistack,我是一个新的反应界面库,如材料界面和notistack。在我的项目中,像这样的组件正在与一些样式/css一起使用。在整个react应用程序中,当有一个长的动态文本放在这个Snackbar组件中时,它的GUI会受到干扰,文本会被切断并从组件中消失。我该如何处理这些信息,并使其具有响应性,以便它能够处理其中很长的文本 以下是文件SanckbarProvider.tsx中Snackbar组件的代码 import React from "react"; import { Snac
import React from "react";
import {
SnackbarProvider as NisSnackbarProvider,
SnackbarProviderProps,
} from "notistack";
import { Fade } from "@material-ui/core";
import { TransitionProps } from "@material-ui/core/transitions";
import { makeStyles } from "@material-ui/core/styles";
import { CloseButton } from "./CloseButton";
const variantStyle = (color: string, backgroundColor: string) => ({
height: "36px;",
color: `${color} !important`,
backgroundColor: `${backgroundColor} !important`,
opacity: "0.95 !important",
borderRadius: "3px;",
boxShadow: "0 2px 10px 0 rgba(0,0,0,0.1);",
alignContent: "center",
marginRight: "-4px !important",
});
const useStyles = makeStyles(() => ({
success: variantStyle("#3AA658", "#BBE9B6"),
error: variantStyle("#FFFFFF", "#D07B7B"),
warning: variantStyle("#FFFFFF", "#EC9E4D"),
info: variantStyle("#FFFFFF", "#6da4d0"),
}));
const FadeTransition = (props: TransitionProps) => <Fade {...props}/>;
const SnackbarProvider = ({ children }: SnackbarProviderProps): JSX.Element => {
const classes = useStyles();
return (
<NisSnackbarProvider
classes={{
variantSuccess: classes.success,
variantError: classes.error,
variantWarning: classes.warning,
variantInfo: classes.info,
}}
action={key => <CloseButton id={key} />}
maxSnack={7}
anchorOrigin={{vertical: "bottom", horizontal: "right"}}
autoHideDuration={3000}
transitionDuration={{enter: 1000, exit: 500}}
TransitionComponent={FadeTransition}
variant={"success"}
preventDuplicate
>
{children}
</NisSnackbarProvider>
);
};
export default SnackbarProvider;
从“React”导入React;
进口{
SnackbarProvider作为NisSnackbarProvider,
SnackbarProviderProps,
}来自“诺蒂斯塔克”;
从“@material ui/core”导入{Fade}”;
从“@material ui/core/transitions”导入{TransitionProps}”;
从“@material ui/core/styles”导入{makeStyles}”;
从“/CloseButton”导入{CloseButton};
常量variantStyle=(颜色:string,背景颜色:string)=>({
高度:“36px;”,
颜色:`${color}!重要`,
backgroundColor:“${backgroundColor}!重要”,
不透明度:“0.95!重要”,
边界半径:“3px;”,
盒子阴影:“0 2px 10px 0 rgba(0,0,0,0.1);”,
内容:“中心”,
marginRight:“-4px!重要”,
});
const useStyles=makeStyles(()=>({
成功:variantStyle(“#3AA658”、“#BBE9B6”),
错误:variantStyle(“#FFFFFF”,“#d07bb”),
警告:variantStyle(“#FFFFFF”),“#EC9E4D”),
信息:variantStyle(“#FFFFFF”),“#6da4d0”),
}));
常量FadeTransition=(道具:TransitionProps)=>;
const SnackbarProvider=({children}:SnackbarProviderProps):JSX.Element=>{
const classes=useStyles();
返回(
}
MaxSnapshot={7}
anchorOrigin={{垂直:“底部”,水平:“右侧”}
自动隐藏={3000}
transitionDuration={{enter:1000,exit:500}
TransitionComponent={FadeTransition}
变量={“成功”}
防止重复
>
{儿童}
);
};
导出默认SnackbarProvider;
这是app.tsx中的主要应用程序组件
const ContentWrapper = styled.div<WrapperProps>`
overflow-x: hidden;
background: ${(props) => (props.showBackground ? "white" : "transparent")};
height: calc(100vh);
`;
const LinearProgressWrapper = styled.div`
position: absolute;
top: ${LINEAR_PROGRESS_TOP_POSITION};
left: 0;
width: 100%;
z-index: 100;
`;
const LinearProgressStyled = styled(LinearProgress)`
height: 6px;
`;
const App = (): JSX.Element => {
const dispatch = useDispatch();
const size = useScreenSize();
const loginState = useSelector(loginSelector);
const showLoadingIndicator = useSelector(pendingApiCallsExist);
const { authenticated } = loginState;
const selectedScreen = useSelector((state: IRootState) => state.ui.view);
const shouldShowBigTopbar = !!(selectedScreen === ViewTypes.WorkspacesList && IS_MAC_OS);
// for some reasons, after logout, sizesReducer is reset.
// So it's needed to manually trigger recalculation
useLayoutEffect(() => {
if (size.height !== -1) {
dispatch(resizeAction(size));
}
}, [authenticated, dispatch, size]);
return (
<StylesProvider injectFirst>
<MuiThemeProvider theme={maTheme}>
<ThemeProvider theme={maTheme}>
<I18nextProvider i18n={i18n}>
<SnackbarProvider>
<Socket url={SOCKET_URL}/>
<ContentWrapper
showBackground={shouldShowBigTopbar}
>
<Router history={routerHistory}>
<Routes />
{showLoadingIndicator && <LinearProgressWrapper>
<LinearProgressStyled />
</LinearProgressWrapper>}
<SnackbarsList />
</Router>
</ContentWrapper>
</SnackbarProvider>
</I18nextProvider>
</ThemeProvider>
</MuiThemeProvider>
</StylesProvider>
);
};
export default App;
const ContentWrapper=styled.div`
溢出x:隐藏;
背景:${(道具)=>(props.showBackground?“白色”:“透明”)};
高度:计算(100vh);
`;
常量LinearProgressWrapper=styled.div`
位置:绝对位置;
顶部:${LINEAR_PROGRESS_top_POSITION};
左:0;
宽度:100%;
z指数:100;
`;
常量LinearProgressStyled=已设置样式(LinearProgress)`
高度:6px;
`;
常量App=():JSX.Element=>{
const dispatch=usedpatch();
常量大小=使用屏幕大小();
const loginState=useSelector(loginSelector);
常量showLoadingIndicator=useSelector(PendingPicallSexist);
const{authenticated}=loginState;
const selectedScreen=useSelector((状态:IRootState)=>state.ui.view);
const showldbigtopbar=!!(selectedScreen==ViewTypes.WorkspacesList&&IS\u MAC\u OS);
//由于某些原因,注销后,sizesReducer将重置。
//因此需要手动触发重新计算
useLayoutEffect(()=>{
如果(尺寸.高度!=-1){
调度(调整大小(大小));
}
},[认证、发送、大小];
返回(
{showLoadingIndicator&&
}
);
};
导出默认应用程序;
这是呈现info和moreinfo snackbar的代码
import React, { useState } from "react";
import {
Card,
CardActions,
Collapse,
IconButton,
Paper,
Typography,
} from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import CloseIcon from "@material-ui/icons/Close";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import { SnackbarMessage, useSnackbar } from "notistack";
import { autoUpdater } from "electron-updater";
const infoBase = {
alignContent: "center",
backgroundColor: "#D07B7B",
borderRadius: "3px;",
boxShadow: "0 2px 10px 0 rgba(0,0,0,0.1);",
color: "#FFFFFF",
marginRight: "-4px",
opacity: "0.95",
padding: "6px 16px",
};
const useStyles = makeStyles((theme) => ({
card: {
marginRight: "-4px",
maxWidth: 440,
minWidth: 344,
},
info: {
...infoBase,
height: "36px",
},
icons: {
marginLeft: "auto !important",
marginRight: "-8px",
paddingLeft: "16px",
},
expand: {
color: "#FFFFFF",
padding: "8px 8px",
transform: "rotate(0deg)",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest,
}),
},
expandOpen: {
transform: "rotate(180deg)",
},
moreInfo: {
...infoBase,
maxHeight: "156px",
overflowWrap: "break-word",
},
}));
interface IProps {
id: string | number,
info: string,
moreInfo: string,
}
const MoreInfoSnackbar = (props: IProps): JSX.Element => {
const {id, info, moreInfo} = props;
const classes = useStyles();
const { closeSnackbar } = useSnackbar();
const [expanded, setExpanded] = useState(false);
const handleExpandClick = () => setExpanded(!expanded);
const handleDismiss = () => closeSnackbar(id);
// TODO: What the heck to do with this? - very, very hacky!
const renderErrorIcon = () => (
<svg className="MuiSvgIcon-root" focusable="false" viewBox="0 0 28 28"
aria-hidden="true"
style={{fontSize: "20px", marginInlineEnd: "8px"}}
>
<path
d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z">
</path>
</svg>
);
const renderActionIcons = () => (
<div className={classes.icons}>
<IconButton
style={{
transform: expanded ? "rotate(180deg)" : "",
}}
aria-label="Show more"
className={classes.expand}
onClick={handleExpandClick}
>
<ExpandMoreIcon />
</IconButton>
<IconButton className={classes.expand} onClick={handleDismiss}>
<CloseIcon />
</IconButton>
</div>
);
const renderInfo = () => (
<CardActions className={classes.info}>
{renderErrorIcon()}
<Typography gutterBottom>
{info}
</Typography>
{renderActionIcons()}
</CardActions>
);
const renderMoreInfo = () => (
<Collapse in={expanded} timeout="auto" unmountOnExit>
<Paper className={classes.moreInfo}>
<Typography gutterBottom>
{moreInfo}
</Typography>
</Paper>
</Collapse>
);
return (
<Card className={classes.card}>
{renderInfo()}
{renderMoreInfo()}
</Card>
);
};
type IErrors = {
info: string
moreInfo: string
}
const processMessage = (message: React.ReactNode): IErrors => {
if (typeof message === "string") {
return {info: message, moreInfo: ""};
}
if (Array.isArray(message)) {
const info = typeof message[0] === "string" ? message[0] : "";
const moreInfo = typeof message[1] === "string" ? message[1] : "";
return {info, moreInfo};
}
return {info: "", moreInfo: ""};
};
/**
This is the set callback signature that notistack allows for returning
a customized snackbar.
It is not straightforward to get more data into the custom snackbar.
So we leverage the message param. It can be a string or an array.
We could use a JSON string and then parse it to get a bunch more options
but for now, we are just adding an extra "moreInfo" string
Works with a message array of [message, moreInfo], I.e:
import { getMoreInfoSnackbar } from "../../snacks/MoreInfoSnackbar";
...
enqueueSnackbar(
["something went wrong", "More detailed info, accessed via dropdown"],
{
content: getMoreInfoSnackbar,
persist: true,
},
);
*/
export const getMoreInfoSnackbar = (key: React.ReactText, message: React.ReactNode): SnackbarMessage => {
const {info, moreInfo} = processMessage(message);
return <MoreInfoSnackbar id={key} info={info} moreInfo={moreInfo}/>;
};
export default MoreInfoSnackbar;
import React,{useState}来自“React”;
进口{
卡片
卡片行动,
崩溃
IconButton,
纸张
排版,
}来自“@材料界面/核心”;
从“@material ui/core/styles”导入{makeStyles}”;
从“@material ui/icons/Close”导入CloseIcon;
从“@material ui/icons/ExpandMore”导入ExpandMoreIcon;
从“notistack”导入{SnackbarMessage,useSnackbar};
从“electron updater”导入{autoUpdater};
常量信息库={
内容:“中心”,
背景颜色:“D07B7B”,
边界半径:“3px;”,
盒子阴影:“0 2px 10px 0 rgba(0,0,0,0.1);”,
颜色:“FFFFFF”,
marginRight:“-4px”,
不透明度:“0.95”,
填充:“6px 16px”,
};
const useStyles=makeStyles((主题)=>({
卡片:{
marginRight:“-4px”,
最大宽度:440,
最小宽度:344,
},
信息:{
…信息库,
高度:“36px”,
},
图标:{
marginLeft:“自动!重要”,
marginRight:“-8px”,
填充左:“16px”,
},
扩展:{
颜色:“FFFFFF”,
填充:“8px 8px”,
变换:“旋转(0度)”,
转换:theme.transitions.create(“转换”{
持续时间:theme.transitions.duration.shortest,
}),
},
expandOpen:{
变换:“旋转(180度)”,
},
更多信息:{
…信息库,
最大高度:“156px”,
溢出包装:“打断单词”,
},
}));
接口IProps{
id:字符串|编号,
信息:字符串,
更多信息:字符串,
}
const MoreInfoSnackbar=(props:IProps):JSX.Element=>{
const{id,info,moreInfo}=props;
const classes=useStyles();
const{closeSnackbar}=useSnackbar();
const[expanded,setExpanded]=useState(false);
const handleExpandClick=()=>setExpanded(!expanded);
const handleDismiss=()=>closeSnackbar(id);
//托多:这他妈的怎么办?-非常非常讨厌!
const renderErrorIcon=()=>(
);
常量渲染=()=>(
);
常量renderInfo=()=>(
{renderErrorIcon()}
{info}
{renderActions()}
);
常量renderMoreInfo=()=>(
{moreInfo}
);
返回(
{renderInfo()}
{renderMoreInfo()}
);
};
类型错误={
信息:字符串
更多信息:字符串
}
const processMessage=(消息:React.ReactNode):IErrors=>{
如果(消息类型==“字符串”){
返回{info:message,moreInfo::};
}
如果(A)