Skip to content

Commit

Permalink
Merge pull request #6908 from Sage/tile_highlight
Browse files Browse the repository at this point in the history
feat(tile): add support for adding highlight border via the  prop
  • Loading branch information
edleeks87 committed Aug 28, 2024
2 parents 61efbff + f3c3419 commit b9fe7e5
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 5 deletions.
7 changes: 7 additions & 0 deletions src/components/tile/tile-test.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
TILE_BORDER_VARIANTS,
TILE_ORIENTATIONS,
TILE_THEMES,
TILE_HIGHLIGHT_VARIANTS,
} from "./tile.config";
import Box from "../box";
import Textarea from "../textarea";
Expand Down Expand Up @@ -37,6 +38,12 @@ export default {
type: "select",
},
},
highlightVariant: {
options: [undefined, ...TILE_HIGHLIGHT_VARIANTS],
control: {
type: "select",
},
},
},
};

Expand Down
25 changes: 23 additions & 2 deletions src/components/tile/tile.component.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React from "react";
import * as DesignTokens from "@sage/design-tokens/js/base/common";
import { SpaceProps, WidthProps } from "styled-system";
import StyledTile from "./tile.style";

import StyledTile, { StyledHighlight } from "./tile.style";
import TileContext from "./__internal__/tile.context";
import filterStyledSystemPaddingProps from "../../style/utils/filter-styled-system-padding-props";
import filterStyledSystemMarginProps from "../../style/utils/filter-styled-system-margin-props";
import computeContentPadding from "./__internal__/compute-content-padding";
import tagComponent, { TagProps } from "../../__internal__/utils/helpers/tags";
import { TILE_HIGHLIGHT_VARIANTS } from "./tile.config";

type DesignTokensType = keyof typeof DesignTokens;
type HighlightVariantType = typeof TILE_HIGHLIGHT_VARIANTS[number];

export interface TileProps extends SpaceProps, WidthProps, TagProps {
/** Sets the theme of the tile */
Expand Down Expand Up @@ -44,6 +47,8 @@ export interface TileProps extends SpaceProps, WidthProps, TagProps {
* Set a percentage-based height for the whole Tile component, relative to its parent.
*/
height?: string | number;
/** Sets the highlight variant */
highlightVariant?: HighlightVariantType;
}

export const Tile = ({
Expand All @@ -56,14 +61,15 @@ export const Tile = ({
height,
borderWidth,
borderVariant,
highlightVariant,
...rest
}: TileProps) => {
const isHorizontal = orientation === "horizontal";
const paddingProps = filterStyledSystemPaddingProps({ p, ...rest });
const marginProps = filterStyledSystemMarginProps(rest);
const contentPaddingProps = computeContentPadding(paddingProps, isHorizontal);

return (
const tile = (
<StyledTile
variant={variant}
width={width}
Expand All @@ -84,6 +90,21 @@ export const Tile = ({
</TileContext.Provider>
</StyledTile>
);

if (highlightVariant) {
return (
<StyledHighlight
variant={highlightVariant}
roundness={roundness}
aria-hidden
data-role={`tile-${highlightVariant}-highlight`}
>
{tile}
</StyledHighlight>
);
}

return tile;
};

export default Tile;
8 changes: 8 additions & 0 deletions src/components/tile/tile.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,11 @@ export const TILE_BORDER_VARIANTS = [
"positive",
"caution",
];
export const TILE_HIGHLIGHT_VARIANTS = [
"gradient",
"success",
"neutral",
"error",
"warning",
"info",
];
29 changes: 29 additions & 0 deletions src/components/tile/tile.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,35 @@ Use `justifyContent` to place your content inside the width allocated to the cel

<Canvas of={TileStories.Align} />


### Highlight variants

Setting the `highlightVariant` prop will add a highlight to the Tile on the left border.

#### Gradient

<Canvas of={TileStories.HighlightVariantGradientStory} />

#### Success

<Canvas of={TileStories.HighlightVariantSuccessStory} />

#### Neutral

<Canvas of={TileStories.HighlightVariantNeutralStory} />

#### Error

<Canvas of={TileStories.HighlightVariantErrorStory} />

#### Warning

<Canvas of={TileStories.HighlightVariantWarningStory} />

#### Info

<Canvas of={TileStories.HighlightVariantInfoStory} />

### Tile

<ArgTypes of={TileStories} />
Expand Down
15 changes: 15 additions & 0 deletions src/components/tile/tile.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { mount } from "enzyme";
import { render, screen } from "@testing-library/react";
import { Tile, TileContent } from ".";
import StyledTileContent from "./tile-content/tile-content.style";
import {
Expand All @@ -11,6 +12,7 @@ import {
import { TileProps } from "./tile.component";
import { rootTagTest } from "../../__internal__/utils/helpers/tags/tags-specs";
import StyledTile from "./tile.style";
import { TILE_HIGHLIGHT_VARIANTS } from "./tile.config";

function renderTile(props: TileProps) {
return mount(
Expand Down Expand Up @@ -185,3 +187,16 @@ describe("Tile", () => {
rootTagTest(wrapper.find(StyledTile), "tile", "foo", "bar");
});
});

test.each<TileProps["highlightVariant"]>(TILE_HIGHLIGHT_VARIANTS)(
"should render with the highlight element when `highlightVariant` is passed %s",
(highlightVariant) => {
render(<Tile highlightVariant={highlightVariant} />);
const highlightElement = screen.getByTestId(
`tile-${highlightVariant}-highlight`
);

expect(highlightElement).toBeVisible();
expect(highlightElement).toHaveAttribute("aria-hidden");
}
);
114 changes: 114 additions & 0 deletions src/components/tile/tile.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1021,3 +1021,117 @@ export const Align: Story = () => {
);
};
Align.storyName = "Responsive Tile with Align Content";

export const HighlightVariantGradientStory: Story = () => {
return (
<>
<Tile highlightVariant="gradient">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
<br />
<Tile highlightVariant="gradient" roundness="large">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
</>
);
};
HighlightVariantGradientStory.storyName = "Highlight variant gradient story";

export const HighlightVariantSuccessStory: Story = () => {
return (
<>
<Tile highlightVariant="success">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
<br />
<Tile highlightVariant="success" roundness="large">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
</>
);
};
HighlightVariantSuccessStory.storyName = "Highlight variant success story";

export const HighlightVariantNeutralStory: Story = () => {
return (
<>
<Tile highlightVariant="neutral">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
<br />
<Tile highlightVariant="neutral" roundness="large">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
</>
);
};
HighlightVariantNeutralStory.storyName = "Highlight variant neutral story";

export const HighlightVariantErrorStory: Story = () => {
return (
<>
<Tile highlightVariant="error">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
<br />
<Tile highlightVariant="error" roundness="large">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
</>
);
};
HighlightVariantErrorStory.storyName = "Highlight variant error story";

export const HighlightVariantWarningStory: Story = () => {
return (
<>
<Tile highlightVariant="warning">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
<br />
<Tile highlightVariant="warning" roundness="large">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
</>
);
};
HighlightVariantWarningStory.storyName = "Highlight variant warning story";

export const HighlightVariantInfoStory: Story = () => {
return (
<>
<Tile highlightVariant="info">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
<br />
<Tile highlightVariant="info" roundness="large">
<TileContent>Test Body One</TileContent>
<TileContent>Test Body Two</TileContent>
<TileContent>Test Body Three</TileContent>
</Tile>
</>
);
};
HighlightVariantInfoStory.storyName = "Highlight variant info story";
48 changes: 45 additions & 3 deletions src/components/tile/tile.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ import { space, SpaceProps } from "styled-system";
import baseTheme from "../../style/themes/base";
import computeSizing from "../../style/utils/element-sizing";
import { TileProps } from "./tile.component";
import StyledTileContent from "./tile-content/tile-content.style";

type StyledTileProps = Pick<
TileProps,
"borderWidth" | "borderVariant" | "variant" | "width" | "roundness" | "height"
| "borderWidth"
| "borderVariant"
| "variant"
| "width"
| "roundness"
| "height"
| "highlightVariant"
> & { isHorizontal?: boolean } & SpaceProps;

const getBorderColor = (
Expand Down Expand Up @@ -47,6 +54,24 @@ const getBorderRadius = (roundness: TileProps["roundness"]) => {
}
};

const getHeighlightVariant = (variant: TileProps["highlightVariant"]) => {
switch (variant) {
case "success":
return "var(--colorsSemanticPositive500)";
case "neutral":
return "var(--colorsSemanticNeutral500)";
case "error":
return "var(--colorsSemanticNegative500)";
case "warning":
return "var(--colorsSemanticCaution500)";
case "info":
return "var(--colorsSemanticInfo500)";
default:
// gradient is default
return "linear-gradient(0deg, rgb(143, 73, 254) 5%, rgb(0, 146, 219) 50%, rgb(19, 160, 56) 95%)";
}
};

const StyledTile = styled.div<StyledTileProps>`
${({
borderVariant,
Expand All @@ -65,12 +90,12 @@ const StyledTile = styled.div<StyledTileProps>`
border-radius: ${getBorderRadius(roundness)};
--tileBorderRadius: ${getBorderRadius(roundness)};
> *:first-child {
> *:first-child:not(${StyledTileContent}) {
border-top-left-radius: calc(${getBorderRadius(roundness)} - 1px);
border-top-right-radius: calc(${getBorderRadius(roundness)} - 1px);
}
> *:last-child {
> *:last-child:not(${StyledTileContent}) {
border-bottom-left-radius: calc(${getBorderRadius(roundness)} - 1px);
border-bottom-right-radius: calc(${getBorderRadius(roundness)} - 1px);
}
Expand Down Expand Up @@ -109,4 +134,21 @@ StyledTile.defaultProps = {
theme: baseTheme,
};

export const StyledHighlight = styled.div<{
variant: Required<TileProps["highlightVariant"]>;
roundness: TileProps["roundness"];
}>`
height: 100%;
width: 100%;
position: relative;
background: ${({ variant }) => getHeighlightVariant(variant)};
border-radius: ${({ roundness }) => getBorderRadius(roundness)};
${StyledTile} {
border-left: 0;
left: 4px;
width: calc(100% - 4px);
}
`;

export default StyledTile;

0 comments on commit b9fe7e5

Please sign in to comment.