From f7065bcb00028c79a8253ad8478600ed5a0d3bb2 Mon Sep 17 00:00:00 2001 From: TJ Egan Date: Fri, 24 May 2024 15:21:26 -0400 Subject: [PATCH] feat(RadioTile): update `RadioTile` to accept `Slug`, phase 3 updates (#16227) * feat(RadioTile): update RadioTile to accept Slug, phase 3 updates * chore(test): update snapshots * fix(RadioTile): fixed issue with feature flag variant * style(RadioTile): fix focus styles on RadioTile * Update packages/react/src/components/Slug/slug-story.scss --------- Co-authored-by: Alison Joseph Co-authored-by: Guilherme Datilio Ribeiro Co-authored-by: Taylor Jones --- .../__snapshots__/PublicAPI-test.js.snap | 6 + .../src/components/RadioTile/RadioTile.tsx | 36 +++ .../components/Slug/Slug-examples.stories.js | 245 ++++++++++++------ .../react/src/components/Slug/slug-story.scss | 22 ++ .../styles/scss/components/tile/_tile.scss | 36 ++- 5 files changed, 267 insertions(+), 78 deletions(-) diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index f9e65cf49374..3fb61718ecb1 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -6436,6 +6436,9 @@ Map { "disabled": Object { "type": "bool", }, + "hasRoundedCorners": Object { + "type": "bool", + }, "id": Object { "type": "string", }, @@ -6449,6 +6452,9 @@ Map { "required": Object { "type": "bool", }, + "slug": Object { + "type": "node", + }, "tabIndex": Object { "type": "number", }, diff --git a/packages/react/src/components/RadioTile/RadioTile.tsx b/packages/react/src/components/RadioTile/RadioTile.tsx index 44749a5f5912..f270d5759b95 100644 --- a/packages/react/src/components/RadioTile/RadioTile.tsx +++ b/packages/react/src/components/RadioTile/RadioTile.tsx @@ -42,6 +42,12 @@ export interface RadioTileProps { */ disabled?: boolean; + /** + * **Experimental**: Specify if the `ExpandableTile` component should be rendered with rounded corners. + * Only valid when `slug` prop is present + */ + hasRoundedCorners?: boolean; + /** * Provide a unique id for the underlying ``. */ @@ -72,6 +78,11 @@ export interface RadioTileProps { | React.KeyboardEvent ) => void; + /** + * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component + */ + slug?: React.ReactNode; + /** * Specify the tab index of the underlying ``. */ @@ -100,6 +111,8 @@ const RadioTile = React.forwardRef(function RadioTile( id, onChange = noopFn, tabIndex = 0, + hasRoundedCorners, + slug, required, ...rest }: RadioTileProps, @@ -111,10 +124,13 @@ const RadioTile = React.forwardRef(function RadioTile( customClassName, `${prefix}--tile`, `${prefix}--tile--selectable`, + `${prefix}--tile--radio`, { [`${prefix}--tile--is-selected`]: checked, [`${prefix}--tile--light`]: light, [`${prefix}--tile--disabled`]: disabled, + [`${prefix}--tile--slug`]: slug, + [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners, } ); const v12TileRadioIcons = useFeatureFlag('enable-v12-tile-radio-icons'); @@ -145,6 +161,14 @@ const RadioTile = React.forwardRef(function RadioTile( } } + // Slug is always size `xs` + let normalizedSlug; + if (slug && slug['type']?.displayName === 'Slug') { + normalizedSlug = React.cloneElement(slug as React.ReactElement, { + size: 'xs', + }); + } + return (
{icon()} {children} + {normalizedSlug}
); @@ -192,6 +217,12 @@ RadioTile.propTypes = { */ disabled: PropTypes.bool, + /** + * Specify if the `ExpandableTile` component should be rendered with rounded corners. + * Only valid when `slug` prop is present + */ + hasRoundedCorners: PropTypes.bool, + /** * Provide a unique id for the underlying ``. */ @@ -223,6 +254,11 @@ RadioTile.propTypes = { */ required: PropTypes.bool, + /** + * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component + */ + slug: PropTypes.node, + /** * Specify the tab index of the underlying ``. */ diff --git a/packages/react/src/components/Slug/Slug-examples.stories.js b/packages/react/src/components/Slug/Slug-examples.stories.js index a77382082b4f..a423b5aa9f36 100644 --- a/packages/react/src/components/Slug/Slug-examples.stories.js +++ b/packages/react/src/components/Slug/Slug-examples.stories.js @@ -30,6 +30,9 @@ import { TileAboveTheFoldContent, TileBelowTheFoldContent, } from '../Tile'; +import { default as RadioTile } from '../RadioTile'; +import TileGroup from '../TileGroup/TileGroup'; +import { FeatureFlags } from '../FeatureFlags'; import { IconButton } from '../IconButton'; import { ArrowRight, @@ -697,75 +700,9 @@ export const _Tile = { }, }, render: (args) => ( -
- -

Title

-

- Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit at - consectetur turpis mauris gravida penatibus. -

-
-
-

Data Quality

-

85%

-
-
-

Label text

-

16%

-
-
-
- -

Title

-

- Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit at - consectetur turpis mauris gravida penatibus. -

-
-
-

Data Quality

-

85%

-
-
-

Label text

-

16%

-
-
-
- -

Title

-

- Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit at - consectetur turpis mauris gravida penatibus. -

-
-
-

Data Quality

-

85%

-
-
-

Label text

-

16%

-
-
-
- - + <> +
+

Title

Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit @@ -781,15 +718,171 @@ export const _Tile = {

16%

- - -
Expanded Section
+ + +

Title

Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit - at consectetur turpis mauris. + at consectetur turpis mauris gravida penatibus.

-
- - +
+
+

Data Quality

+

85%

+
+
+

Label text

+

16%

+
+
+ + + + +

Title

+

+ Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit + at consectetur turpis mauris gravida penatibus. +

+
+
+

Data Quality

+

85%

+
+
+

Label text

+

16%

+
+
+
+ +
Expanded Section
+

+ Lorem ipsum dolor sit amet consectetur. Posuere duis fermentum sit + at consectetur turpis mauris. +

+
+
+ + +
+ +
+ + Option 1 + +
+
+ + Option 2 + +
+
+ + Option 3 + +
+
+
+
+
+
+ + + Option 1 + + + Option 2 + + + Option 3 + + +
+
+
+
+ + + + Option 1 + + + Option 2 + + + Option 3 + + + +
+ ), }; diff --git a/packages/react/src/components/Slug/slug-story.scss b/packages/react/src/components/Slug/slug-story.scss index f2093e0557e6..6af2dee0b80d 100644 --- a/packages/react/src/components/Slug/slug-story.scss +++ b/packages/react/src/components/Slug/slug-story.scss @@ -1,5 +1,6 @@ @use '@carbon/styles/scss/type'; @use '@carbon/styles/scss/theme'; +@use '@carbon/react/scss/components/tile'; .slug-container-example { display: flex; @@ -164,3 +165,24 @@ .sbdocs-slug .cds--toggletip-content { font-size: 0.875rem; } + +.slug-selectable-tile-container .cds--tile-group > div { + display: flex; +} + +.slug-selectable-tile-container .cds--tile-group > div > div { + width: 33%; +} + +.slug-selectable-tile-container .cds--tile-group .slug-radio-tile, +.slug-selectable-tile-container .cds--tile-group .slug-selectable-tile { + margin-inline-end: 1rem; + height: 200px; +} + +.slug-experimental-radio-tile-container { + @include tile.tile( + $enable-experimental-tile-contrast: true, + $enable-v12-tile-radio-icons: true + ); +} diff --git a/packages/styles/scss/components/tile/_tile.scss b/packages/styles/scss/components/tile/_tile.scss index f20bc70833d6..271998101f15 100644 --- a/packages/styles/scss/components/tile/_tile.scss +++ b/packages/styles/scss/components/tile/_tile.scss @@ -391,6 +391,24 @@ $-icon-container-size: calc(#{layout.density('padding-inline')} * 2 + 1rem); inset-inline-end: $spacing-08; } + .#{$prefix}--tile.#{$prefix}--tile--selectable.#{$prefix}--tile--radio + > .#{$prefix}--slug { + inset-inline-end: $spacing-05; + transition: inset-inline-end $duration-fast-02 motion(standard, productive); + + @if ( + enabled('enable-v12-tile-radio-icons') or + $enable-experimental-tile-contrast + ) { + inset-inline-end: $spacing-08; + } + } + + .#{$prefix}--tile.#{$prefix}--tile--selectable.#{$prefix}--tile--radio.#{$prefix}--tile--is-selected + > .#{$prefix}--slug { + inset-inline-end: $spacing-08; + } + .#{$prefix}--tile.#{$prefix}--tile--clickable > .#{$prefix}--slug { pointer-events: none; } @@ -435,7 +453,8 @@ $-icon-container-size: calc(#{layout.density('padding-inline')} * 2 + 1rem); } .#{$prefix}--tile--slug.#{$prefix}--tile--selectable:focus, - .#{$prefix}--tile--slug.#{$prefix}--tile--clickable:focus { + .#{$prefix}--tile--slug.#{$prefix}--tile--clickable:focus, + .#{$prefix}--tile-input:focus + .#{$prefix}--tile--slug.#{$prefix}--tile { outline-offset: -1px; } @@ -463,10 +482,23 @@ $-icon-container-size: calc(#{layout.density('padding-inline')} * 2 + 1rem); .#{$prefix}--tile--slug.#{$prefix}--tile--clickable .#{$prefix}--tile-content { position: relative; - z-index: 1; cursor: pointer; } + .#{$prefix}--tile--slug.#{$prefix}--tile--selectable + .#{$prefix}--tile-content, + .#{$prefix}--tile--slug.#{$prefix}--tile--clickable .#{$prefix}--tile-content, + .#{$prefix}--tile--slug.#{$prefix}--tile--selectable + > .#{$prefix}--tile__checkmark, + .#{$prefix}--tile--slug.#{$prefix}--tile--is-selected .#{$prefix}--slug { + z-index: 1; + } + + .#{$prefix}--tile--slug.#{$prefix}--tile--selectable + .#{$prefix}--slug:has(> .cds--popover--open) { + z-index: 2; + } + .#{$prefix}--tile--slug.#{$prefix}--tile--selectable > .#{$prefix}--slug, .#{$prefix}--tile--slug.#{$prefix}--tile--selectable > .#{$prefix}--tile__checkmark {