Use Accordion component from new macaw (#3712)

This commit is contained in:
Paweł Chyła 2023-07-10 10:24:34 +02:00 committed by GitHub
parent 093388c46f
commit 0ea8f32378
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 220 additions and 381 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---
Replace all old Accordion components with new from macaw-ui

View file

@ -1,15 +1,15 @@
// @ts-strict-ignore
import Skeleton from "@dashboard/components/Skeleton";
import { ReorderEvent } from "@dashboard/types";
import { Accordion, Divider, Typography } from "@material-ui/core";
import { Typography } from "@material-ui/core";
import { Accordion, Divider } from "@saleor/macaw-ui/next";
import React from "react";
import { defineMessages, useIntl } from "react-intl";
import AssignmentListFooter from "./AssignmentListFooter";
import AssignmentListHeader from "./AssignmentListHeader";
import Item from "./Item";
import SortableContainer from "./SortableContainer";
import { useExpanderStyles, useStyles } from "./styles";
import { useStyles } from "./styles";
import { AssignmentListProps } from "./types";
const messages = defineMessages({
@ -32,7 +32,6 @@ const AssignmentList: React.FC<AssignmentListProps> = props => {
const intl = useIntl();
const classes = useStyles();
const expanderClasses = useExpanderStyles();
const handleSortStart = () => {
document.body.classList.add(classes.grabbing);
@ -46,12 +45,20 @@ const AssignmentList: React.FC<AssignmentListProps> = props => {
const hasMoreItemsToBeSelected = totalCount !== items.length;
return (
<Accordion classes={expanderClasses}>
<AssignmentListHeader
assignCount={items.length}
itemsName={itemsName}
loading={loading}
/>
<Accordion paddingX={7} paddingBottom={2} paddingTop={4}>
<Accordion.Item value="accordionItemId">
<Accordion.Trigger paddingBottom={4}>
{loading ? (
<Skeleton />
) : (
<Typography variant="subtitle2" color="textSecondary">
{`${items.length} ${itemsName.toLowerCase()}`}
</Typography>
)}
<Accordion.TriggerButton dataTestId="expand-icon" />
</Accordion.Trigger>
<Accordion.Content>
<Divider />
{loading ? (
<Skeleton className={classes.skeleton} />
@ -91,6 +98,8 @@ const AssignmentList: React.FC<AssignmentListProps> = props => {
)}
</>
)}
</Accordion.Content>
</Accordion.Item>
</Accordion>
);
};

View file

@ -1,38 +0,0 @@
import HorizontalSpacer from "@dashboard/components/HorizontalSpacer";
import Skeleton from "@dashboard/components/Skeleton";
import { Typography } from "@material-ui/core";
import { AccordionSummary } from "@saleor/macaw-ui";
import React from "react";
import { useHeaderStyles } from "./styles";
interface AssignmentListHeaderProps {
assignCount: number;
itemsName: string;
loading: boolean;
}
const AssignmentListHeader: React.FC<AssignmentListHeaderProps> = ({
assignCount,
itemsName,
loading,
}) => {
const { container, skeleton, ...accordion } = useHeaderStyles();
return (
<div className={container}>
<AccordionSummary className={accordion.root}>
{loading ? (
<Skeleton className={skeleton} />
) : (
<Typography variant="subtitle2" color="textSecondary">
{`${assignCount} ${itemsName.toLowerCase()}`}
</Typography>
)}
</AccordionSummary>
<HorizontalSpacer spacing={1.5} />
</div>
);
};
export default AssignmentListHeader;

View file

@ -1,5 +1,5 @@
import DeletableItem from "@dashboard/components/DeletableItem";
import { Divider, Typography } from "@material-ui/core";
import { Divider, Text } from "@saleor/macaw-ui/next";
import React from "react";
import { SortableElement, SortableElementProps } from "react-sortable-hoc";
@ -28,7 +28,7 @@ const Item = SortableElement(
data-test-id="button-drag-handle"
/>
)}
<Typography>{name}</Typography>
<Text size="small">{name}</Text>
</div>
<DeletableItem id={id} onDelete={onDelete} />
</div>

View file

@ -53,7 +53,6 @@ export const useHeaderStyles = makeStyles(
export const useStyles = makeStyles(
theme => ({
container: {
padding: theme.spacing(1, 0),
display: "flex",
flexDirection: "row",
justifyContent: "space-between",

View file

@ -1,39 +1,11 @@
import { Typography } from "@material-ui/core";
import AddIcon from "@material-ui/icons/Add";
import RemoveIcon from "@material-ui/icons/Remove";
import { IconButton, makeStyles } from "@saleor/macaw-ui";
import clsx from "clsx";
import React from "react";
import Hr from "../Hr";
const useStyles = makeStyles(
theme => ({
content: {
padding: theme.spacing(3, 0),
},
expandButton: {
position: "relative",
right: theme.spacing(-2),
top: theme.spacing(0.5),
},
root: {
border: `1px solid ${theme.palette.divider}`,
borderRadius: 12,
padding: theme.spacing(0, 3),
},
title: {
display: "flex",
justifyContent: "space-between",
},
titleText: {
padding: theme.spacing(2, 0),
},
}),
{
name: "Accordion",
},
);
import {
Accordion as AccordionMacaw,
Box,
Divider,
sprinkles,
Text,
} from "@saleor/macaw-ui/next";
import React, { useState } from "react";
export interface AccordionProps {
className?: string;
@ -42,38 +14,52 @@ export interface AccordionProps {
title: string;
}
const AccordionItemId = "accordionItemId";
const Accordion: React.FC<AccordionProps> = ({
children,
className,
initialExpand,
quickPeek,
title,
...props
className,
}) => {
const classes = useStyles({});
const [expanded, setExpanded] = React.useState(!!initialExpand);
const [openedAccordionId, setOpendAccordionId] = useState<undefined | string>(
!!initialExpand ? AccordionItemId : undefined,
);
return (
<div className={clsx(classes.root, className)} {...props}>
<div className={classes.title}>
<Typography className={classes.titleText}>{title}</Typography>
<div className={classes.expandButton}>
<IconButton
variant="secondary"
onClick={() => setExpanded(!expanded)}
<div className={className}>
<AccordionMacaw
value={openedAccordionId}
onValueChange={value => setOpendAccordionId(value)}
className={sprinkles({
borderStyle: "solid",
borderWidth: 1,
borderColor: "neutralPlain",
paddingX: 4,
borderRadius: 5,
})}
>
{expanded ? <RemoveIcon /> : <AddIcon />}
</IconButton>
</div>
</div>
{(expanded || !!quickPeek) && (
<AccordionMacaw.Item value={AccordionItemId}>
<AccordionMacaw.Trigger>
<Text paddingY={3} variant="body" size="small">
{title}
</Text>
<AccordionMacaw.TriggerButton dataTestId="expand-icon" />
</AccordionMacaw.Trigger>
<AccordionMacaw.Content>
<Divider />
<Box paddingY={3}>{children}</Box>
</AccordionMacaw.Content>
</AccordionMacaw.Item>
{!openedAccordionId && !!quickPeek && (
<>
<Hr />
<div className={classes.content}>
{quickPeek ? (expanded ? children : quickPeek) : children}
</div>
<Divider />
<Box paddingY={4}>{quickPeek}</Box>
</>
)}
</AccordionMacaw>
</div>
);
};

View file

@ -88,6 +88,7 @@ export const Attributes: React.FC<AttributesProps> = ({
}}
/>
</Text>
<Accordion.TriggerButton dataTestId="expand-icon" />
</Accordion.Trigger>
<Accordion.Content>
{attributes.length > 0 && (

View file

@ -17,9 +17,10 @@ export const ChannelAvailabilityItemWrapper: React.FC<
> = ({ data: { name }, messages, children }) => (
<Accordion data-test-id="channel-availability-item">
<Accordion.Item value="channel-availability-item" gap={9}>
<Accordion.Trigger buttonDataTestId="expand-icon">
<Accordion.Trigger>
<Text variant={"bodyEmp"}>{name}</Text>
<Label text={messages.availableDateText} />
<Accordion.TriggerButton dataTestId="expand-icon" />
</Accordion.Trigger>
<Accordion.Content paddingLeft={3}>{children}</Accordion.Content>
</Accordion.Item>

View file

@ -39,7 +39,7 @@ const FilterContentBodyNameField: React.FC<FilterContentBodyNameFieldProps> = ({
}
label={filter.label}
onClick={event => event.stopPropagation()}
onChange={() =>
onChange={() => {
onFilterPropertyChange({
payload: {
name: filter.name,
@ -48,8 +48,8 @@ const FilterContentBodyNameField: React.FC<FilterContentBodyNameFieldProps> = ({
},
},
type: "set-property",
})
}
});
}}
/>
</div>
);

View file

@ -1,80 +1,8 @@
import { Typography } from "@material-ui/core";
import {
Accordion,
AccordionDetails,
AccordionSummary,
makeStyles,
} from "@saleor/macaw-ui";
import { Accordion, Box, sprinkles, Text } from "@saleor/macaw-ui/next";
import React from "react";
import TimelineEventHeader, { TitleElement } from "./TimelineEventHeader";
const useStyles = makeStyles(
theme => ({
dot: {
backgroundColor: theme.palette.primary.main,
borderRadius: "100%",
height: 7,
left: -28,
position: "absolute",
top: 6,
width: 7,
},
panel: {
"& .MuiAccordionDetails-root": {
padding: 0,
paddingTop: theme.spacing(2),
},
"&.Mui-expanded": {
margin: 0,
minHeight: 0,
},
"&:before": {
display: "none",
},
background: "none",
display: "",
margin: 0,
minHeight: 0,
width: "100%",
},
panelExpander: {
"&.MuiAccordionSummary-root.Mui-expanded": {
minHeight: 0,
},
"&> .MuiAccordionSummary-content": {
margin: 0,
},
"&> .MuiAccordionSummary-expandIcon": {
padding: 0,
position: "absolute",
right: theme.spacing(24),
},
margin: 0,
minHeight: 0,
padding: 0,
},
root: {
"&:last-child:after": {
background: theme.palette.background.default,
content: "''",
height: "calc(50% - 4px)",
left: -26,
position: "absolute",
top: "calc(50% + 4px)",
width: "2px",
},
alignItems: "center",
display: "flex",
marginBottom: theme.spacing(3),
marginTop: 0,
position: "relative",
width: "100%",
},
}),
{ name: "TimelineEvent" },
);
export interface TimelineEventProps {
children?: React.ReactNode;
date: string;
@ -88,24 +16,48 @@ export const TimelineEvent: React.FC<TimelineEventProps> = props => {
const { children, date, secondaryTitle, title, titleElements, hasPlainDate } =
props;
const classes = useStyles(props);
const hasChildren =
children && React.Children.toArray(children).filter(Boolean).length > 0;
return (
<div className={classes.root}>
<span className={classes.dot} />
{children ? (
<Accordion className={classes.panel} elevation={0}>
<AccordionSummary className={classes.panelExpander}>
<Box
display="flex"
alignItems="center"
marginBottom={5}
position="relative"
width="100%"
>
<Box
as="span"
position="absolute"
backgroundColor="interactiveNeutralPressing"
borderRadius="100%"
__height="7px"
__width="7px"
__left="-28px"
__top={hasChildren ? "13px" : "5px"}
/>
{hasChildren ? (
<Accordion
className={sprinkles({
width: "100%",
})}
>
<Accordion.Item value="accordionItemId">
<Accordion.Trigger>
<TimelineEventHeader
title={title}
date={date}
titleElements={titleElements}
hasPlainDate={hasPlainDate}
/>
</AccordionSummary>
<AccordionDetails>
<Typography>{children}</Typography>
</AccordionDetails>
>
<Accordion.TriggerButton dataTestId="expand-icon" />
</TimelineEventHeader>
</Accordion.Trigger>
<Accordion.Content>
<Text>{children}</Text>
</Accordion.Content>
</Accordion.Item>
</Accordion>
) : (
<TimelineEventHeader
@ -116,7 +68,7 @@ export const TimelineEvent: React.FC<TimelineEventProps> = props => {
hasPlainDate={hasPlainDate}
/>
)}
</div>
</Box>
);
};
TimelineEvent.displayName = "TimelineEvent";

View file

@ -1,46 +1,10 @@
import useNavigator from "@dashboard/hooks/useNavigator";
import { Typography } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import React from "react";
import { Box, sprinkles, Text } from "@saleor/macaw-ui/next";
import React, { ReactNode } from "react";
import { DateTime } from "../Date";
import Link from "../Link";
const useStyles = makeStyles(
theme => ({
container: {
alignItems: "start",
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
width: "100%",
},
title: {
wordBreak: "break-all",
},
date: {
color: theme.typography.caption.color,
paddingLeft: 24,
whiteSpace: "nowrap",
},
elementsContainer: {
alignItems: "center",
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
},
secondaryTitle: {
color: "#9e9e9e",
fontSize: 14,
marginTop: theme.spacing(2),
},
titleElement: {
marginRight: theme.spacing(0.5),
},
}),
{ name: "TimelineEventHeader" },
);
export interface TitleElement {
text: string;
link?: string;
@ -52,26 +16,43 @@ export interface TimelineEventHeaderProps {
titleElements?: TitleElement[];
secondaryTitle?: string;
hasPlainDate?: boolean;
children?: ReactNode;
}
export const TimelineEventHeader: React.FC<
TimelineEventHeaderProps
> = props => {
const { title, date, titleElements, secondaryTitle, hasPlainDate } = props;
const { title, date, titleElements, secondaryTitle, hasPlainDate, children } =
props;
const navigate = useNavigator();
const classes = useStyles(props);
return (
<div className={classes.container}>
{title && <Typography className={classes.title}>{title}</Typography>}
<Box
display="flex"
alignItems="center"
flexDirection="row"
justifyContent="space-between"
width="100%"
>
{title && (
<Text variant="caption" size="large" wordBreak="break-all">
{title}
</Text>
)}
{titleElements && (
<div className={classes.elementsContainer}>
<Box
display="flex"
alignItems="center"
flexDirection="row"
flexWrap="wrap"
>
{titleElements.filter(Boolean).map(({ text, link }) => {
if (link) {
return (
<Link
className={classes.titleElement}
className={sprinkles({
marginRight: 0.5,
})}
onClick={() => navigate(link)}
>
{text}
@ -80,20 +61,26 @@ export const TimelineEventHeader: React.FC<
}
return (
<Typography className={classes.titleElement}>{text}</Typography>
<Text variant="caption" size="large" marginRight={0.5}>
{text}
</Text>
);
})}
</div>
</Box>
)}
<Typography className={classes.date}>
<Box display="flex" alignItems="center" gap={5} marginLeft="auto">
{children}
<Text
variant="caption"
size="large"
color="textNeutralSubdued"
whiteSpace="nowrap"
>
<DateTime date={date} plain={hasPlainDate} />
</Typography>
{secondaryTitle && (
<Typography className={classes.secondaryTitle}>
{secondaryTitle}
</Typography>
)}
</div>
</Text>
</Box>
{secondaryTitle && <Text marginTop={2}>{secondaryTitle}</Text>}
</Box>
);
};

View file

@ -9,7 +9,7 @@ const useStyles = makeStyles(
marginBottom: vars.spacing.px,
},
root: {
marginTop: vars.spacing["s1.5"],
marginTop: vars.spacing[1.5],
paddingLeft: vars.spacing[6],
paddingRight: vars.spacing[6],
},

View file

@ -1,13 +1,6 @@
import { CardContent, Typography } from "@material-ui/core";
import { Accordion, AccordionSummary } from "@saleor/macaw-ui";
import { Accordion, sprinkles, Text } from "@saleor/macaw-ui/next";
import React from "react";
import {
useAccordionStyles,
useExpanderStyles,
useSummaryStyles,
} from "./styles";
interface ChannelListProps {
summary: string;
}
@ -15,22 +8,22 @@ interface ChannelListProps {
export const ChannelsList: React.FC<ChannelListProps> = ({
summary,
children,
}) => {
const classes = useAccordionStyles();
const expanderClasses = useExpanderStyles({});
const summaryClasses = useSummaryStyles({});
return (
<Accordion classes={expanderClasses}>
<CardContent className={classes.summaryContent}>
<AccordionSummary
className={summaryClasses.root}
data-test-id="channels-variant-availability-summary"
}) => (
<Accordion>
<Accordion.Item value="channelListItem">
<Accordion.Trigger
className={sprinkles({
paddingX: 6,
paddingTop: 0,
paddingBottom: 8,
})}
>
<Typography variant="caption">{summary}</Typography>
</AccordionSummary>
</CardContent>
{children}
<Text variant="caption" size="large">
{summary}
</Text>
<Accordion.TriggerButton dataTestId="expand-icon" />
</Accordion.Trigger>
<Accordion.Content>{children}</Accordion.Content>
</Accordion.Item>
</Accordion>
);
};

View file

@ -1,56 +0,0 @@
import { makeStyles } from "@saleor/macaw-ui";
export const useAccordionStyles = makeStyles(
() => ({
summaryContent: {
paddingTop: 0,
},
}),
{ name: "VariantDetailsChannelsAvailabilityCard" },
);
export const useExpanderStyles = makeStyles(
() => ({
expanded: {},
root: {
boxShadow: "none",
margin: 0,
padding: 0,
"&:before": {
content: "none",
},
"&$expanded": {
margin: 0,
border: "none",
},
},
}),
{ name: "VariantDetailsChannelsAvailabilityCardExpander" },
);
export const useSummaryStyles = makeStyles(
() => ({
expanded: {},
root: {
width: "100%",
border: "none",
margin: 0,
padding: 0,
minHeight: 0,
"&$expanded": {
minHeight: 0,
},
},
content: {
margin: 0,
"&$expanded": {
margin: 0,
},
},
}),
{ name: "VariantDetailsChannelsAvailabilityCardExpanderSummary" },
);