Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contentcard): first implementation #935

Merged
merged 4 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions packages/components/src/common/styles-dictionary/css/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,16 @@
--sds-color-semantic-base-background-secondary: #f3f3f3;
--sds-color-semantic-base-background-secondary-inverse: #3b3b3b;
--sds-color-semantic-base-background-tertiary: #dfdfdf;
--sds-color-semantic-base-border: #6c6c6c;
--sds-color-semantic-base-border-disabled: #c3c3c3;
--sds-color-semantic-base-border-disabled-inverse: #6c6c6c;
--sds-color-semantic-base-border-hover: #000000;
--sds-color-semantic-base-border-hover-inverse: #ffffff;
--sds-color-semantic-base-border-inverse: #c3c3c3;
--sds-color-semantic-base-border-primary: #6c6c6c;
--sds-color-semantic-base-border-primary-disabled: #c3c3c3;
--sds-color-semantic-base-border-primary-disabled-inverse: #6c6c6c;
--sds-color-semantic-base-border-primary-hover: #000000;
--sds-color-semantic-base-border-primary-hover-inverse: #ffffff;
--sds-color-semantic-base-border-primary-inverse: #c3c3c3;
--sds-color-semantic-base-border-on-fill: #ffffff;
--sds-color-semantic-base-border-pressed: #000000;
--sds-color-semantic-base-border-pressed-inverse: #ffffff;
--sds-color-semantic-base-border-table: #c3c3c3;
--sds-color-semantic-base-border-primary-pressed: #000000;
--sds-color-semantic-base-border-primary-pressed-inverse: #ffffff;
--sds-color-semantic-base-border-secondary: #c3c3c3;
--sds-color-semantic-base-divider: #dfdfdf;
--sds-color-semantic-base-divider-inverse: #6c6c6c;
--sds-color-semantic-base-fill-disabled: #dfdfdf;
Expand Down Expand Up @@ -606,16 +606,16 @@
--sds-color-semantic-base-background-secondary: #333333;
--sds-color-semantic-base-background-secondary-inverse: #ededed;
--sds-color-semantic-base-background-tertiary: #494949;
--sds-color-semantic-base-border: #cdcdcd;
--sds-color-semantic-base-border-disabled: #696969;
--sds-color-semantic-base-border-disabled-inverse: #cdcdcd;
--sds-color-semantic-base-border-hover: #ffffff;
--sds-color-semantic-base-border-hover-inverse: #000000;
--sds-color-semantic-base-border-inverse: #696969;
--sds-color-semantic-base-border-primary: #cdcdcd;
--sds-color-semantic-base-border-primary-disabled: #696969;
--sds-color-semantic-base-border-primary-disabled-inverse: #cdcdcd;
--sds-color-semantic-base-border-primary-hover: #ffffff;
--sds-color-semantic-base-border-primary-hover-inverse: #000000;
--sds-color-semantic-base-border-primary-inverse: #696969;
--sds-color-semantic-base-border-on-fill: #000000;
--sds-color-semantic-base-border-pressed: #ffffff;
--sds-color-semantic-base-border-pressed-inverse: #000000;
--sds-color-semantic-base-border-table: #696969;
--sds-color-semantic-base-border-primary-pressed: #ffffff;
--sds-color-semantic-base-border-primary-pressed-inverse: #000000;
--sds-color-semantic-base-border-secondary: #696969;
--sds-color-semantic-base-divider: #494949;
--sds-color-semantic-base-divider-inverse: #cdcdcd;
--sds-color-semantic-base-fill-disabled: #494949;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,43 +98,43 @@
"value": "{sds.color.primitive.gray.200.value}",
"darkValue": "{sds.color.primitive.gray.200.darkValue}"
},
"border": {
"borderPrimary": {
"value": "{sds.color.primitive.gray.600.value}",
"darkValue": "{sds.color.primitive.gray.600.darkValue}"
},
"border-disabled": {
"border-primary-disabled": {
"value": "{sds.color.primitive.gray.300.value}",
"darkValue": "{sds.color.primitive.gray.300.darkValue}"
},
"border-disabled-inverse": {
"border-primary-disabled-inverse": {
"value": "{sds.color.primitive.gray.600.value}",
"darkValue": "{sds.color.primitive.gray.600.darkValue}"
},
"border-hover": {
"border-primary-hover": {
"value": "{sds.color.primitive.gray.900.value}",
"darkValue": "{sds.color.primitive.gray.900.darkValue}"
},
"border-hover-inverse": {
"border-primary-hover-inverse": {
"value": "{sds.color.primitive.gray.50.value}",
"darkValue": "{sds.color.primitive.gray.50.darkValue}"
},
"border-inverse": {
"border-primary-inverse": {
"value": "{sds.color.primitive.gray.300.value}",
"darkValue": "{sds.color.primitive.gray.300.darkValue}"
},
"border-on-fill": {
"value": "{sds.color.primitive.gray.50.value}",
"darkValue": "{sds.color.primitive.gray.50.darkValue}"
},
"border-pressed": {
"border-primary-pressed": {
"value": "{sds.color.primitive.gray.900.value}",
"darkValue": "{sds.color.primitive.gray.900.darkValue}"
},
"border-pressed-inverse": {
"border-primary-pressed-inverse": {
"value": "{sds.color.primitive.gray.50.value}",
"darkValue": "{sds.color.primitive.gray.50.darkValue}"
},
"border-table": {
"border-secondary": {
"value": "{sds.color.primitive.gray.300.value}",
"darkValue": "{sds.color.primitive.gray.300.darkValue}"
},
Expand Down
36 changes: 18 additions & 18 deletions packages/components/src/common/styles-dictionary/json/tailwind.json
Original file line number Diff line number Diff line change
Expand Up @@ -1163,16 +1163,16 @@
"sds-color-semantic-base-background-secondary": "#333333",
"sds-color-semantic-base-background-secondary-inverse": "#ededed",
"sds-color-semantic-base-background-tertiary": "#494949",
"sds-color-semantic-base-border": "#cdcdcd",
"sds-color-semantic-base-border-disabled": "#696969",
"sds-color-semantic-base-border-disabled-inverse": "#cdcdcd",
"sds-color-semantic-base-border-hover": "#ffffff",
"sds-color-semantic-base-border-hover-inverse": "#000000",
"sds-color-semantic-base-border-inverse": "#696969",
"sds-color-semantic-base-border-primary": "#cdcdcd",
"sds-color-semantic-base-border-primary-disabled": "#696969",
"sds-color-semantic-base-border-primary-disabled-inverse": "#cdcdcd",
"sds-color-semantic-base-border-primary-hover": "#ffffff",
"sds-color-semantic-base-border-primary-hover-inverse": "#000000",
"sds-color-semantic-base-border-primary-inverse": "#696969",
"sds-color-semantic-base-border-on-fill": "#000000",
"sds-color-semantic-base-border-pressed": "#ffffff",
"sds-color-semantic-base-border-pressed-inverse": "#000000",
"sds-color-semantic-base-border-table": "#696969",
"sds-color-semantic-base-border-primary-pressed": "#ffffff",
"sds-color-semantic-base-border-primary-pressed-inverse": "#000000",
"sds-color-semantic-base-border-secondary": "#696969",
"sds-color-semantic-base-divider": "#494949",
"sds-color-semantic-base-divider-inverse": "#cdcdcd",
"sds-color-semantic-base-fill-disabled": "#494949",
Expand Down Expand Up @@ -1332,16 +1332,16 @@
"sds-color-semantic-base-background-secondary": "#f3f3f3",
"sds-color-semantic-base-background-secondary-inverse": "#3b3b3b",
"sds-color-semantic-base-background-tertiary": "#dfdfdf",
"sds-color-semantic-base-border": "#6c6c6c",
"sds-color-semantic-base-border-disabled": "#c3c3c3",
"sds-color-semantic-base-border-disabled-inverse": "#6c6c6c",
"sds-color-semantic-base-border-hover": "#000000",
"sds-color-semantic-base-border-hover-inverse": "#ffffff",
"sds-color-semantic-base-border-inverse": "#c3c3c3",
"sds-color-semantic-base-border-primary": "#6c6c6c",
"sds-color-semantic-base-border-primary-disabled": "#c3c3c3",
"sds-color-semantic-base-border-primary-disabled-inverse": "#6c6c6c",
"sds-color-semantic-base-border-primary-hover": "#000000",
"sds-color-semantic-base-border-primary-hover-inverse": "#ffffff",
"sds-color-semantic-base-border-primary-inverse": "#c3c3c3",
"sds-color-semantic-base-border-on-fill": "#ffffff",
"sds-color-semantic-base-border-pressed": "#000000",
"sds-color-semantic-base-border-pressed-inverse": "#ffffff",
"sds-color-semantic-base-border-table": "#c3c3c3",
"sds-color-semantic-base-border-primary-pressed": "#000000",
"sds-color-semantic-base-border-primary-pressed-inverse": "#ffffff",
"sds-color-semantic-base-border-secondary": "#c3c3c3",
"sds-color-semantic-base-divider": "#dfdfdf",
"sds-color-semantic-base-divider-inverse": "#6c6c6c",
"sds-color-semantic-base-fill-disabled": "#dfdfdf",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,26 +187,26 @@ $sds-color-semantic-base-background-secondary-inverse: #3b3b3b;
$sds-color-semantic-base-background-secondary-inverse-dark: #ededed;
$sds-color-semantic-base-background-tertiary: #dfdfdf;
$sds-color-semantic-base-background-tertiary-dark: #494949;
$sds-color-semantic-base-border: #6c6c6c;
$sds-color-semantic-base-border-dark: #cdcdcd;
$sds-color-semantic-base-border-disabled: #c3c3c3;
$sds-color-semantic-base-border-disabled-dark: #696969;
$sds-color-semantic-base-border-disabled-inverse: #6c6c6c;
$sds-color-semantic-base-border-disabled-inverse-dark: #cdcdcd;
$sds-color-semantic-base-border-hover: #000000;
$sds-color-semantic-base-border-hover-dark: #ffffff;
$sds-color-semantic-base-border-hover-inverse: #ffffff;
$sds-color-semantic-base-border-hover-inverse-dark: #000000;
$sds-color-semantic-base-border-inverse: #c3c3c3;
$sds-color-semantic-base-border-inverse-dark: #696969;
$sds-color-semantic-base-border-primary: #6c6c6c;
$sds-color-semantic-base-border-primary-dark: #cdcdcd;
$sds-color-semantic-base-border-primary-disabled: #c3c3c3;
$sds-color-semantic-base-border-primary-disabled-dark: #696969;
$sds-color-semantic-base-border-primary-disabled-inverse: #6c6c6c;
$sds-color-semantic-base-border-primary-disabled-inverse-dark: #cdcdcd;
$sds-color-semantic-base-border-primary-hover: #000000;
$sds-color-semantic-base-border-primary-hover-dark: #ffffff;
$sds-color-semantic-base-border-primary-hover-inverse: #ffffff;
$sds-color-semantic-base-border-primary-hover-inverse-dark: #000000;
$sds-color-semantic-base-border-primary-inverse: #c3c3c3;
$sds-color-semantic-base-border-primary-inverse-dark: #696969;
$sds-color-semantic-base-border-on-fill: #ffffff;
$sds-color-semantic-base-border-on-fill-dark: #000000;
$sds-color-semantic-base-border-pressed: #000000;
$sds-color-semantic-base-border-pressed-dark: #ffffff;
$sds-color-semantic-base-border-pressed-inverse: #ffffff;
$sds-color-semantic-base-border-pressed-inverse-dark: #000000;
$sds-color-semantic-base-border-table: #c3c3c3;
$sds-color-semantic-base-border-table-dark: #696969;
$sds-color-semantic-base-border-primary-pressed: #000000;
$sds-color-semantic-base-border-primary-pressed-dark: #ffffff;
$sds-color-semantic-base-border-primary-pressed-inverse: #ffffff;
$sds-color-semantic-base-border-primary-pressed-inverse-dark: #000000;
$sds-color-semantic-base-border-secondary: #c3c3c3;
$sds-color-semantic-base-border-secondary-dark: #696969;
$sds-color-semantic-base-divider: #dfdfdf;
$sds-color-semantic-base-divider-dark: #494949;
$sds-color-semantic-base-divider-inverse: #6c6c6c;
Expand Down
14 changes: 14 additions & 0 deletions packages/components/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ export function filterProps<T extends Props, K extends keyof T>(

return result;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const mergeRefs = (refs: any[]) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really cool util function 💡 🔥 !!

// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (element: any) => {
refs.forEach((ref) => {
if (typeof ref === "function") {
ref(element);
} else if (ref != null) {
ref.current = element;
}
});
};
};
12 changes: 12 additions & 0 deletions packages/components/src/common/warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export enum SDSWarningTypes {
TooltipSubtitle = "tooltipSubtitle",
TooltipWidth = "tooltipWidth",
TooltipInvertStyle = "tooltipInvertStyle",
ContentCardActionsOnlyButtons = "contentCardActionsOnlyButtons",
ClickableContentCardNumberOfButtons = "clickableContentCardNumberOfButtons",
}

export const SDS_WARNINGS = {
Expand Down Expand Up @@ -58,6 +60,16 @@ export const SDS_WARNINGS = {
message:
"Warning: Tooltips using the inverted or sdsStyle prop will be deprecated. Please use hasInvertedStyle instead!",
},
[SDSWarningTypes.ContentCardActionsOnlyButtons]: {
hasWarned: false,
message:
"Warning: Only SDS buttons could be used within ContentCard Actions component slot!",
},
[SDSWarningTypes.ClickableContentCardNumberOfButtons]: {
hasWarned: false,
message:
"Warning: Clickable Content Cards can only have one or no buttons!",
},
Comment on lines +63 to +72
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great warnings! So user friendly ❤️

};

export const showWarningIfFirstOccurence = (warningType: SDSWarningTypes) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const StyledAutocompleteBase = styled(Autocomplete, {
// look at the useDetectUserTabbing hook.
&[data-user-is-tabbing="true"]:focus-within {
border-radius: 4px;
outline: 2px solid ${semanticColors?.base?.borderHover};
outline: 2px solid ${semanticColors?.base?.borderPrimaryHover};
outline-offset: 1px;
}

Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/core/Button/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getShadows,
getSpaces,
fontBodySemiboldXxs,
fontBody,
} from "src/core/styles";
import { focusVisibleA11yStyle } from "src/core/styles/common/mixins/a11y";
import { ButtonProps } from ".";
Expand Down Expand Up @@ -65,14 +66,16 @@ const ButtonStyles = (props: ButtonExtraProps): SerializedStyles => {

const disabledBorder =
variant === "outlined"
? `inset 0 0 0 1px ${semanticColors?.base?.borderDisabled}`
? `inset 0 0 0 1px ${semanticColors?.base?.borderPrimaryDisabled}`
: "none";

const boxshadow =
variant === "outlined"
? `inset 0 0 0 1px ${semanticColors?.accent?.border}`
: "none";

fontBody("xs", "semibold");

return css`
background-color: ${backgroundColor};
border: none;
Expand Down
50 changes: 50 additions & 0 deletions packages/components/src/core/ContentCard/ContentCard.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { CardProps } from "@mui/material";

interface BaseContentCardProps extends CardProps {
sdsType?: "wide" | "narrow";
overlineText?: string;
titleText?: string;
subtitleText?: string;
metadataText?: string;
boundingBox?: boolean;
decorativeBorder?: boolean;
children?: React.ReactNode;
clickableCard?: boolean;
buttonsPosition?: "left" | "right";
}

export interface ImageContentCardProps extends BaseContentCardProps {
visualElementType: "image";
image?: React.ReactNode;
imagePosition?: "left" | "right";
imagePadding?: boolean;
imageSize?: number;
icon?: never;
}

export interface IconContentCardProps extends BaseContentCardProps {
visualElementType: "icon";
icon?: React.ReactNode;
image?: never;
imageSize?: never;
imagePosition?: never;
imagePadding?: never;
Comment on lines +28 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, why the types are never here? Here and below

Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses the visualElementType prop as the union type discriminator, so there can be three different types of ContentCard: an ImageContentCard, an IconContentCard, and a regular one without any media elements.

When we set image?: never; on the IconContentCard, for example, it forces TypeScript to throw an error if the user adds an image prop when visualElementType="icon", and so on.

Does that make sense? 🥸

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh!! Thanks so much for the explanation 💡 That totally makes sense now thank you!

}

export interface NoneContentCardProps extends BaseContentCardProps {
visualElementType: "none";
icon?: never;
image?: never;
imagePosition?: never;
imagePadding?: never;
imageSize?: never;
}

export type ContentCardProps =
| ImageContentCardProps
| IconContentCardProps
| NoneContentCardProps;

export const CONTENT_CARD_DEFAULT_IMAGE_MEDIA_SIZE = 300;
export const CONTENT_CARD_WIDE_TYPE_MIN_WIDTH_LOW_BOUNDARY = 595;
export const CONTENT_CARD_WIDE_TYPE_MIN_WIDTH_HIGH_BOUNDARY = 605;
Loading