Skip to content

Commit

Permalink
feat: add 'ItemDetailsGroup', rm nestability of 'ItemDetails'
Browse files Browse the repository at this point in the history
  • Loading branch information
trevor-anderson committed Mar 18, 2023
1 parent e47444c commit dc9e623
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 55 deletions.
12 changes: 4 additions & 8 deletions src/layouts/CoreItemView/CoreItemView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ export const CoreItemView = ({
</StyledCoreContentViewLayout>
);

const StyledCoreContentViewLayout = styled(CoreContentViewLayout)(({ theme }) => ({
const StyledCoreContentViewLayout = styled(CoreContentViewLayout)({
"& .core-content-view-children-container": {
overflowY: "auto !important",
// child of scroll container:
"& > div": {
alignSelf: "center",
width: theme.variables.isMobilePageLayout ? "100%" : "calc(100% - 2rem)" // <-- -2rem helps view to always look centered, with OR without scrollbar
}
overflowX: "hidden",
overflowY: "auto"
}
}));
});
61 changes: 19 additions & 42 deletions src/layouts/CoreItemView/ItemDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Box from "@mui/material/Box";
import Text from "@mui/material/Typography";
import { ItemDetailsLabel } from "./ItemDetailsLabel";

// TODO Create a separate ItemDetailsGroup component

/**
* Displays one or more item properties.
* - Can be nested for grouping related properties together.
Expand All @@ -25,14 +27,7 @@ export const ItemDetails = ({
children,
emptyFallback = <Text>--</Text>,
...containerProps // any remaining props are passed to the containing div
}: {
header?: React.ReactNode;
label?: string;
labelVariant?: React.ComponentProps<typeof ItemDetailsLabel>["variant"];
labelIcon?: React.ComponentProps<typeof ItemDetailsLabel>["icon"];
children?: React.ReactNode;
emptyFallback?: React.ReactNode;
} & React.ComponentProps<typeof ItemDetailsContainer>) => (
}: ItemDetailsProps) => (
<ItemDetailsContainer className="item-details item-details-container" {...containerProps}>
{(header || label) && (
<div className="item-details-header">
Expand All @@ -52,8 +47,7 @@ export const ItemDetails = ({
);

const ItemDetailsContainer = styled(Box)(({ theme }) => ({
border: `2px solid ${theme.palette.divider}`,
borderRadius: "0.35rem",
maxWidth: "100%",

"& *": {
overflow: "hidden",
Expand All @@ -63,17 +57,17 @@ const ItemDetailsContainer = styled(Box)(({ theme }) => ({
// HEADER:

"& > .item-details-header": {
height: "auto",
width: "100%",
padding: "1rem",
padding: 0,
display: "flex",
flexDirection: "row",
alignItems: "center",
borderWidth: "0 0 2px 0",
borderStyle: "solid",
borderColor: theme.palette.divider,

"& .MuiTypography-root": {
color: theme.palette.text.primary
"& > .item-details-label": {
color: theme.palette.text.primary,
marginTop: 0,
opacity: "0.7"
},

"& > svg:first-of-type": {
Expand All @@ -84,34 +78,17 @@ const ItemDetailsContainer = styled(Box)(({ theme }) => ({
// CONTENT:

"& > .item-details-content": {
padding: "1.25rem",
display: "flex",
flexDirection: "column",
gap: "2rem"
},

/* NESTED ItemDetails:
- may be placed within HEADER or CONTENT
- no borders
- no padding
- label opacity set to 0.7, no margin-top
- header height set to auto
*/
"& > .item-details-header, .item-details-content": {
"& div.item-details-container": {
border: "none",
"& > div.item-details-header": {
height: "auto",
padding: "0",
border: "none",
"& > .item-details-label": {
marginTop: 0,
opacity: "0.7"
}
},
"& > div.item-details-content": {
padding: "0"
}
}
}
}));

export type ItemDetailsProps = {
header?: React.ReactNode;
label?: string;
labelVariant?: React.ComponentProps<typeof ItemDetailsLabel>["variant"];
labelIcon?: React.ComponentProps<typeof ItemDetailsLabel>["icon"];
children?: React.ReactNode;
emptyFallback?: React.ReactNode;
} & React.ComponentProps<typeof ItemDetailsContainer>;
102 changes: 102 additions & 0 deletions src/layouts/CoreItemView/ItemDetailsGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { styled, alpha } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Text from "@mui/material/Typography";
import { ItemDetailsLabel } from "./ItemDetailsLabel";
import type { ItemDetailsProps } from "./ItemDetails";

/**
* Displays one or more ItemDetails components as a group.
*/
export const ItemDetailsGroup = ({
header,
label,
labelVariant,
labelIcon,
children,
emptyFallback = <Text>--</Text>,
...containerProps // any remaining props are passed to the containing div
}: ItemDetailsProps) => (
<ItemDetailsGroupContainer
className="item-details-group item-details-group-container"
{...containerProps}
>
{(header || label) && (
<Paper className="item-details-group-header" elevation={0}>
{label && (
<>
{labelIcon}
<ItemDetailsLabel variant={labelVariant}>{label}</ItemDetailsLabel>
</>
)}
{header}
</Paper>
)}
<div className="item-details-group-content">
{typeof children === "string" ? <Text>{children || "--"}</Text> : children ?? emptyFallback}
</div>
</ItemDetailsGroupContainer>
);

const ItemDetailsGroupContainer = styled(Box)(({ theme }) => ({
...(theme.palette.mode === "light" && {
border: `2px solid ${theme.palette.divider}`
}),
borderRadius: "0.35rem",
overflow: "hidden",

"& *": {
textOverflow: "ellipsis"
},

// HEADER:

"& > .item-details-group-header": {
width: "100%",
padding: "1rem",
overflow: "hidden",
display: "flex",
flexDirection: "row",
alignItems: "center",
borderWidth: "0 0 1px 0",
borderStyle: "solid",
borderColor: alpha(theme.palette.divider, 0.05),
borderRadius: "0.35rem 0.35rem 0 0",

"& > .MuiTypography-root": {
color: theme.palette.text.primary
},

"& > svg:first-of-type": {
marginRight: "0.75rem"
}
},

// CONTENT:

"& > .item-details-group-content": {
position: "relative",
zIndex: 1,
padding: "1.25rem",
borderRadius: "0 0 0.35rem 0.35rem",
display: "flex",
flexDirection: "column",
gap: "1.5rem 2rem",

"&::before": {
content: '""',
position: "absolute",
zIndex: 2,
pointerEvents: "none",
top: 0,
left: "-10px",
display: "block",
height: "calc(100% + 20px)",
width: "110%",
boxShadow:
theme.palette.mode === "dark"
? "inset 0 1px 5px 1px rgba(0,0,0,0.2)"
: "inset 0 1px 5px 0 rgba(0,0,0,0.05)"
}
}
}));
8 changes: 6 additions & 2 deletions src/layouts/CoreItemView/ItemDetailsLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const ItemDetailsLabel = ({
icon,
variant = "h6",
style = {},
sx = {},
children,
...props
}: { icon?: React.ReactNode } & React.ComponentProps<typeof Text>) => (
Expand All @@ -16,13 +17,16 @@ export const ItemDetailsLabel = ({
margin: "0.25rem 0",
fontSize: "0.9rem",
lineHeight: "1rem",
fontWeight: "200",
textTransform: "uppercase",
overflowX: "hidden",
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
...style
}}
sx={({ palette }) => ({
fontWeight: palette.mode === "dark" ? 200 : "normal",
...(sx as any)
})}
{...props}
>
{children}
Expand Down
7 changes: 4 additions & 3 deletions src/layouts/CoreItemView/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { CoreItemView } from "./CoreItemView";
export { ItemDetails } from "./ItemDetails";
export { ItemDetailsLabel } from "./ItemDetailsLabel";
export * from "./CoreItemView";
export * from "./ItemDetails";
export * from "./ItemDetailsGroup";
export * from "./ItemDetailsLabel";

0 comments on commit dc9e623

Please sign in to comment.