Skip to content

Commit

Permalink
refactor(slice-machine-ui): merge cards into SharedSliceCard (#1184)
Browse files Browse the repository at this point in the history
  • Loading branch information
bapmrl authored Oct 23, 2023
1 parent a37a5da commit 509036c
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 290 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/user-flows/scenario_slice_association.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe.skip("I am an existing SM user (Next) and I want to associate a Slice t
cy.visit(`/custom-types/${customTypeId}`);

cy.get("[data-cy=update-slices]").click();
cy.get(`[data-cy=shared-slice-selection-card-${sliceId}]`).click();
cy.get(`[data-cy=shared-slice-card-${sliceId}]`).click();
cy.get("[data-cy=update-slices-modal]").submit();

customTypeBuilder.save();
Expand Down
2 changes: 1 addition & 1 deletion cypress/pages/UpdateSliceZoneModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class UpdateSliceZoneModal {
}

selectSlice(sliceId) {
cy.get(`[data-cy=shared-slice-selection-card-${sliceId}]`).click();
cy.get(`[data-cy=shared-slice-card-${sliceId}]`).click();
return this;
}

Expand Down
2 changes: 1 addition & 1 deletion cypress/pages/customTypes/customTypeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class CustomTypeBuilder extends BaseBuilder {
async addSliceToSliceZone(sliceId) {
await cy.findAllByText(/Add slices/)[0].click();
this.updateSliceZoneButton.click();
cy.get(`[data-cy=shared-slice-selection-card-${sliceId}]`).click();
cy.get(`[data-cy=shared-slice-card-${sliceId}]`).click();
cy.get("[data-cy=update-slices-modal]").submit();
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { countMissingScreenshots } from "@src/domain/slice";
import { useScreenshotChangesModal } from "@src/hooks/useScreenshotChangesModal";
import { ModelStatus } from "@lib/models/common/ModelStatus";
import { LocalOrRemoteCustomType } from "@lib/models/common/ModelData";
import { SharedSliceViewCard } from "@src/features/slices/sliceCards/SharedSliceViewCard";
import { SharedSliceCard } from "@src/features/slices/sliceCards/SharedSliceCard";

interface ChangesItemsProps extends ModelStatusInformation {
unSyncedCustomTypes: LocalOrRemoteCustomType[];
Expand Down Expand Up @@ -119,16 +119,18 @@ export const ChangesItems: React.FC<ChangesItemsProps> = ({
renderElem={(slice) => {
const modelStatus = modelsStatuses.slices[slice.model.id];
return (
<SharedSliceViewCard
<SharedSliceCard
action={{ type: "status", authStatus, isOnline, modelStatus }}
isDeletedSlice={modelStatus === ModelStatus.Deleted}
isDeleted={modelStatus === ModelStatus.Deleted}
mode="navigation"
onUpdateScreenshot={() => {
onOpenModal({
sliceFilterFn: (s) =>
s.filter((e) => e.model.id === slice.model.id),
});
}}
slice={slice}
variant="solid"
/>
);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import useSliceMachineActions from "@src/modules/useSliceMachineActions";
import { ToasterType } from "@src/modules/toaster";
import { CustomTypeFormat } from "@slicemachine/manager";
import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
import { NonSharedSliceViewCard } from "@src/features/slices/sliceCards/NonSharedSliceViewCard";
import { SharedSliceViewCard } from "@src/features/slices/sliceCards/SharedSliceViewCard";
import { NonSharedSliceCard } from "@src/features/slices/sliceCards/NonSharedSliceCard";
import { SharedSliceCard } from "@src/features/slices/sliceCards/SharedSliceCard";
import { useLab } from "@src/features/labs/labsList/useLab";

interface SlicesListProps {
Expand Down Expand Up @@ -69,20 +69,20 @@ export const SlicesList: React.FC<SlicesListProps> = ({
renderElem={(slice) => {
if (slice.type !== "SharedSlice") {
const nonSharedSlice = slice.payload as NonSharedSliceInSliceZone;
return <NonSharedSliceViewCard slice={nonSharedSlice} path={path} />;
return <NonSharedSliceCard slice={nonSharedSlice} path={path} />;
} else {
const sharedSlice = slice.payload as ComponentUI;
return (
<SharedSliceViewCard
<SharedSliceCard
action={{
type: "remove",
onRemove: () => {
onRemoveSharedSlice(sharedSlice.model.id);
},
}}
isDeletedSlice={false}
onUpdateScreenshot={undefined}
mode="navigation"
slice={sharedSlice}
variant="solid"
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FieldArray } from "formik";
import Grid from "@components/Grid";
import { SliceZoneFormValues } from "./UpdateSliceZoneModal";
import { ComponentUI } from "@lib/models/common/ComponentUI";
import { SharedSliceSelectionCard } from "@src/features/slices/sliceCards/SharedSliceSelectionCard";
import { SharedSliceCard } from "@src/features/slices/sliceCards/SharedSliceCard";

const UpdateSliceZoneModalList: React.FC<{
availableSlices: ReadonlyArray<ComponentUI>;
Expand All @@ -23,8 +23,10 @@ const UpdateSliceZoneModalList: React.FC<{
false;
const isInSliceZone = values.sliceKeys.includes(slice.model.id);
return (
<SharedSliceSelectionCard
<SharedSliceCard
action={{ type: "checkbox" }}
isComingSoon={isComingSoon}
mode="selection"
onSelectedChange={(selected) => {
if (selected) {
arrayHelpers.push(slice.model.id);
Expand All @@ -34,6 +36,7 @@ const UpdateSliceZoneModalList: React.FC<{
}}
selected={isInSliceZone}
slice={slice}
variant="outlined"
/>
);
}}
Expand Down
7 changes: 4 additions & 3 deletions packages/slice-machine/pages/slices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { SliceMachineStoreType } from "@src/redux/type";
import useSliceMachineActions from "@src/modules/useSliceMachineActions";
import { getLibraries, getRemoteSlices } from "@src/modules/slices";
import { useScreenshotChangesModal } from "@src/hooks/useScreenshotChangesModal";
import { SharedSliceViewCard } from "@src/features/slices/sliceCards/SharedSliceViewCard";
import { SharedSliceCard } from "@src/features/slices/sliceCards/SharedSliceCard";
import { SLICES_CONFIG } from "@src/features/slices/slicesConfig";
import { SliceToastMessage } from "@components/ToasterContainer";

Expand Down Expand Up @@ -171,7 +171,7 @@ const SlicesIndex: React.FunctionComponent = () => {
elems={components}
defineElementKey={(slice) => slice.model.name}
renderElem={(slice) => (
<SharedSliceViewCard
<SharedSliceCard
action={{
type: "menu",
onRemove: () => {
Expand All @@ -183,7 +183,7 @@ const SlicesIndex: React.FunctionComponent = () => {
openRenameSliceModal();
},
}}
isDeletedSlice={false}
mode="navigation"
onUpdateScreenshot={() => {
onOpenModal({
sliceFilterFn: (s) =>
Expand All @@ -193,6 +193,7 @@ const SlicesIndex: React.FunctionComponent = () => {
});
}}
slice={slice}
variant="solid"
/>
)}
gridGap="32px 16px"
Expand Down
20 changes: 13 additions & 7 deletions packages/slice-machine/src/components/Card/Card.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,18 @@ export const size = styleVariants({
});

export const variant = styleVariants({
solid: [sprinkles({ backgroundColor: colors.grey3 })],
outlined: [sprinkles({ backgroundColor: colors.grey2 })],
solid: [
sprinkles({
backgroundColor: colors.grey3,
borderColor: selectors.checked(colors.purple10),
}),
],
outlined: [
sprinkles({
backgroundColor: colors.grey2,
borderColor: selectors.checked(colors.purple8),
}),
],
});

export const interactive = style({
Expand All @@ -40,10 +50,7 @@ export const interactive = style({
export const interactiveVariant = {
solid: sprinkles({
backgroundColor: selectors.focusVisible(colors.grey5),
borderColor: {
...selectors.checked(colors.purple10),
...selectors.focusVisible(colors.purple10),
},
borderColor: selectors.focusVisible(colors.purple10),
}),
outlined: sprinkles({
backgroundColor: {
Expand All @@ -53,7 +60,6 @@ export const interactiveVariant = {
},
borderColor: {
...selectors.active(colors.purple9),
...selectors.checked(colors.purple8),
...selectors.focusVisible(colors.purple8),
},
}),
Expand Down
3 changes: 2 additions & 1 deletion packages/slice-machine/src/components/Card/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ type Story = StoryObj<typeof meta>;
const meta = {
component: Card,
argTypes: {
checked: { if: { arg: "interactive" } },
children: { control: { disable: true } },
component: { control: { disable: true }, if: { arg: "interactive" } },
disabled: { if: { arg: "interactive" } },
href: { if: { arg: "interactive" } },
onClick: { if: { arg: "interactive" } },
replace: { if: { arg: "interactive" } },
size: { control: "select", options: ["small", "medium"] },
variant: { control: "select", options: ["solid", "outlined"] },
},
Expand All @@ -35,6 +35,7 @@ export default meta;

export const Default = {
args: {
checked: false,
children: (
<>
<CardMedia overlay={<></>} />
Expand Down
89 changes: 51 additions & 38 deletions packages/slice-machine/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,88 +17,101 @@ import * as styles from "./Card.css";

type CardProps = PropsWithChildren<
{
checked?: boolean;
size?: keyof typeof styles.size;
style?: CSSProperties;
variant?: keyof typeof styles.variant;
} & (
| { interactive?: false }
| ({ interactive: true; href: string } & {
component?: "a" | FC<LinkProps>;
})
| ({ interactive: true; href?: undefined } & {
checked?: boolean;
| // Props for rendering a non-interactive `div` element.
NarrowedCardProps<{ interactive?: false }>
// Props for rendering an interactive `div` element.
| NarrowedCardProps<{
interactive: true;
disabled?: boolean;
onClick?: (event: MouseEvent) => void;
})
}>
// Props for rendering an `a` element.
| NarrowedCardProps<{ interactive: true; href: string; component?: "a" }>
// Props for rendering any link `component`.
| NarrowedCardProps<{
interactive: true;
href: string;
component: FC<LinkProps>;
replace?: boolean;
}>
)
>;

// This type is used to spread the `Card`'s `otherProps` before they can be
// narrowed down.
type NarrowedCardProps<T> = NarrowedProps<
T,
"component" | "disabled" | "href" | "interactive" | "onClick" | "replace"
>;

/**
* Construct a type with the properties of T and a set of optional properties K
* (excluding those already in type T).
*/
type NarrowedProps<T, K extends PropertyKey> = T &
Omit<Partial<Record<K, never>>, keyof T>;

type LinkProps = {
href: string | UrlObject;
onClick?: (event: MouseEvent) => void;
};

export const Card: FC<CardProps> = (props) => {
const { size = "medium", variant = "solid" } = props;
const {
checked = false,
size = "medium",
variant = "solid",
interactive: _interactive,
disabled: _disabled,
onClick: _onClick,
href: _href,
component = "a",
replace: _replace,
...otherProps
} = props;
const elementProps = {
...otherProps,
className: clsx(styles.root, styles.size[size], styles.variant[variant], {
[styles.interactive]: props.interactive,
[styles.interactiveVariant[variant]]: props.interactive,
}),
"data-state": checked === true ? "checked" : undefined,
};
if (props.interactive === true && props.href === undefined) {
const {
size: _size,
variant: _variant,
interactive: _interactive,
checked,
disabled,
onClick,
...otherProps
} = props;
return (
<div
{...otherProps}
{...elementProps}
// TODO: add missing ARIA attributes and keyboard event handlers.
data-disabled={disabled === true ? "" : undefined}
data-state={checked === true ? "checked" : undefined}
data-disabled={props.disabled === true ? "" : undefined}
onClick={(event) => {
if (disabled === true || onClick === undefined) return;
if (props.disabled === true || props.onClick === undefined) return;
const target = event.target as HTMLElement;
if (findFocusableAncestor(target) === event.currentTarget) {
onClick(event);
props.onClick(event);
}
}}
tabIndex={disabled === true ? undefined : 0}
tabIndex={props.disabled === true ? undefined : 0}
/>
);
} else if (props.interactive === true) {
const {
size: _size,
variant: _variant,
interactive: _interactive,
component = "a",
...otherProps
} = props;
return createElement(component, {
...otherProps,
...elementProps,
href: props.href,
onClick: (event) => {
const target = event.target as HTMLElement;
if (findFocusableAncestor(target) !== event.currentTarget) {
event.preventDefault();
}
},
...(component === "a" ? {} : { replace: props.replace }),
});
} else {
const {
size: _size,
variant: _variant,
interactive: _interactive,
...otherProps
} = props;
return <div {...otherProps} {...elementProps} />;
return <div {...elementProps} />;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import useSliceMachineActions from "@src/modules/useSliceMachineActions";
import { ToasterType } from "@src/modules/toaster";
import { getFieldMappingFingerprint } from "@src/domain/slice";

import { NonSharedSliceViewCardProps } from "../sliceCards/NonSharedSliceViewCard";
import { NonSharedSliceCardProps } from "../sliceCards/NonSharedSliceCard";
import { ConvertLegacySliceAsNewSliceDialog } from "./ConvertLegacySliceAsNewSliceDialog";
import { ConvertLegacySliceAsNewVariationDialog } from "./ConvertLegacySliceAsNewVariationDialog";
import { ConvertLegacySliceMergeWithIdenticalDialog } from "./ConvertLegacySliceMergeWithIdenticalDialog";
Expand All @@ -30,7 +30,7 @@ import {
LegacySliceConversionType,
} from "./types";

type ConvertLegacySliceButtonProps = NonSharedSliceViewCardProps;
type ConvertLegacySliceButtonProps = NonSharedSliceCardProps;

export const ConvertLegacySliceButton: FC<ConvertLegacySliceButtonProps> = ({
slice,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LibraryUI } from "@models/common/LibraryUI";
import { ComponentUI } from "@models/common/ComponentUI";

import { NonSharedSliceViewCardProps } from "../sliceCards/NonSharedSliceViewCard";
import { NonSharedSliceCardProps } from "../sliceCards/NonSharedSliceCard";

export type ConvertLegacySliceAndTrackArgs = {
libraryID: string;
Expand Down Expand Up @@ -34,4 +34,4 @@ export type DialogProps = {
libraries: readonly LibraryUI[];
localSharedSlices: ComponentUI[];
identicalSlices: IdenticalSlice[];
} & Pick<NonSharedSliceViewCardProps, "path" | "slice">;
} & Pick<NonSharedSliceCardProps, "path" | "slice">;
Loading

0 comments on commit 509036c

Please sign in to comment.