Skip to content

Commit

Permalink
chore(tile): web component parity (#18514)
Browse files Browse the repository at this point in the history
* chore(tile): web component parity

* Apply suggestions from code review

Co-authored-by: kennylam <[email protected]>

* fix(expandable-tile): focus and stories

---------

Co-authored-by: kennylam <[email protected]>
  • Loading branch information
ariellalgilmore and kennylam authored Feb 24, 2025
1 parent 84fd364 commit 862159a
Show file tree
Hide file tree
Showing 14 changed files with 379 additions and 413 deletions.
2 changes: 1 addition & 1 deletion packages/react/src/components/RadioTile/RadioTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export interface RadioTileProps {

/**
* @deprecated please use `decorator` instead.
* **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
* **Experimental**: Provide a `Slug` component to be rendered inside the `RadioTile` component
*/
slug?: React.ReactNode;

Expand Down
6 changes: 1 addition & 5 deletions packages/react/src/components/Tile/Tile.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,7 @@ export const ClickableWithLayer = () => (

export const Selectable = (args) => {
return (
<SelectableTile
id="selectable-tile-1"
name="tiles"
value="selectable"
{...args}>
<SelectableTile id="selectable-tile-1" {...args}>
Selectable
</SelectableTile>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/components/Tile/Tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export interface TileProps extends HTMLAttributes<HTMLDivElement> {

/**
* **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
* when `slug` prop is present
* when an AILabel is present
*/
hasRoundedCorners?: boolean;

Expand Down Expand Up @@ -112,7 +112,7 @@ Tile.propTypes = {

/**
* **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
* when `slug` prop is present
* when an AILabel is present
*/
hasRoundedCorners: PropTypes.bool,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,64 +56,6 @@ div #{$prefix}-selectable-tile::-moz-list-bullet {
margin-block-end: $spacing-05;
}

.ai-label-tile-container {
display: flex;
flex-wrap: wrap;
align-items: flex-start;

#{$prefix}-expandable-tile,
#{$prefix}-selectable-tile,
#{$prefix}-clickable-tile,
#{$prefix}-tile {
margin-block-end: $spacing-09;
margin-inline-end: $spacing-09;
max-inline-size: 320px;
}

#{$prefix}-expandable-tile,
#{$prefix}-selectable-tile .tile-container,
#{$prefix}-clickable-tile .tile-container,
#{$prefix}-tile {
padding-block-end: 90px;
}
}

.ai-label-tile-container h4 {
margin-block-end: $spacing-05;
}

.ai-label-tile-container .ai-data {
display: flex;
padding: $spacing-05 0;
margin-block-start: $spacing-05;
}

.ai-label-tile-container .data-container {
inline-size: 126px;
}

.ai-label-tile-container .data-container:first-of-type {
margin-inline-end: $spacing-05;
}

.ai-label-tile-container p {
@include type-style('body-01');
}

.ai-label-tile-container .data-container p {
@include type-style('label-02');
}

.ai-label-tile-container #{$prefix}-tile-below-the-fold-content {
padding-block-start: $spacing-05;
}

.ai-label-tile-container #{$prefix}-tile-below-the-fold-content p {
@include type-style('label-01');

margin: $spacing-03 0 50px;
}

#{$prefix}-radio-button-group:not(:first-of-type),
#{$prefix}-checkbox-group:not(:first-of-type) {
margin-block-start: $spacing-07;
Expand Down
4 changes: 4 additions & 0 deletions packages/web-components/src/components/ai-label/ai-label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ import { carbonElement as customElement } from '../../globals/decorators/carbon-
*/
@customElement(`${prefix}-ai-label`)
export default class CDSAILabel extends CDSToggleTip {
/**
* @deprecated the slot string will be renamed to "decorator"
*/
@property({ reflect: true })
slot = 'ai-label';

/**
* Specify the correct translation of the AI text
*/
Expand Down
26 changes: 9 additions & 17 deletions packages/web-components/src/components/tile/clickable-tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,7 @@ import CDSLink from '../link/link';
import { TILE_COLOR_SCHEME } from './defs';
import styles from './tile.scss?lit';
import { carbonElement as customElement } from '../../globals/decorators/carbon-element';

// To Do: Replace with an an icon from `@carbon/icons`
// since the hollow AI Label in `ClickableTile` is not interactive
const aiLabelIcon = html` <svg
class="${prefix}--tile--slug-icon"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="23" height="23" />
<path
d="M13.2436 16H11.5996L10.9276 13.864H7.95164L7.29164 16H5.68364L8.49164 7.624H10.4596L13.2436 16ZM10.5436 12.508L9.46364 9.064H9.40364L8.33564 12.508H10.5436ZM17.9341 16H14.1301V14.728H15.2341V8.896H14.1301V7.624H17.9341V8.896H16.8181V14.728H17.9341V16Z"
fill="#161616" />
</svg>`;
import AILabel24 from '@carbon/icons/lib/ai-label/24.js';
/**
* Clickable tile.
*
Expand All @@ -51,6 +37,8 @@ class CDSClickableTile extends CDSLink {

/**
* The color scheme.
*
* @default
*/
@property({ attribute: 'color-scheme', reflect: true })
colorScheme = TILE_COLOR_SCHEME.REGULAR;
Expand All @@ -68,7 +56,7 @@ class CDSClickableTile extends CDSLink {
@property({ type: Boolean, attribute: 'has-rounded-corners' })
hasRoundedCorners = false;

@property({ type: Boolean })
@property({ type: Boolean, attribute: 'ai-label' })
aiLabel = false;

/**
Expand Down Expand Up @@ -96,7 +84,11 @@ class CDSClickableTile extends CDSLink {
*/
protected _renderInner() {
return html`
${super._renderInner()} ${this.aiLabel || this.slug ? aiLabelIcon : ''}
${super._renderInner()}
${this.aiLabel || this.slug
? AILabel24({ class: `${prefix}--tile--ai-label-icon` })
: ''}
<slot name="decorator"></slot>
`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class CDSExpandableTile extends HostListenerMixin(FocusMixin(LitElement)) {
</button>
<slot name="ai-label" @slotchange="${this._handleSlotChange}"></slot>
<slot name="slug" @slotchange="${this._handleSlotChange}"></slot>
<slot name="decorator"></slot>
<div id="content" class="${prefix}--tile-content">
<div><slot name="above-the-fold-content"></slot></div>
<div
Expand Down
49 changes: 30 additions & 19 deletions packages/web-components/src/components/tile/radio-tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,14 @@ import CheckmarkFilled16 from '@carbon/icons/lib/checkmark--filled/16.js';
import { carbonElement as customElement } from '../../globals/decorators/carbon-element';

/**
* Single-selectable tile.
* Radio tile.
*
* @element cds-radio-tile
* @fires cds-radio-tile-selected
* The name of the custom event fired after this selectable tile changes its selected state.
* The name of the custom event fired after this radio tile changes its selected state.
*/
@customElement(`${prefix}-radio-tile`)
class CDSRadioTile extends SelectableTile {
/**
* The `type` attribute of the `<input>`.
*/
protected _inputType = 'radio';

/**
* Handles `change` event on the `<input>` in the shadow DOM.
*/
Expand All @@ -48,42 +43,58 @@ class CDSRadioTile extends SelectableTile {
);
}

protected _handleKeydown = (event: KeyboardEvent) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
}
};

render() {
const {
colorScheme,
checkmarkLabel,
disabled,
hasRoundedCorners,
name,
selected,
value,
_inputType: inputType,
_handleChange: handleChange,
_handleKeydown: handleKeydown,
_hasAILabel: hasAILabel,
} = this;
const classes = classMap({
[`${prefix}--tile`]: true,
[`${prefix}--tile--selectable`]: true,
[`${prefix}--tile--radio`]: true,
[`${prefix}--tile--disabled`]: disabled,
[`${prefix}--tile--is-selected`]: selected,
[`${prefix}--tile--${colorScheme}`]: colorScheme,
[`${prefix}--tile--slug-rounded`]: hasAILabel && hasRoundedCorners,
});

return html`
<input
type="${inputType}"
type="radio"
id="input"
class="${prefix}--tile-input"
tabindex="-1"
?disabled="${disabled}"
tabindex="${selected ? 0 : -1}"
name="${ifDefined(name)}"
value="${ifDefined(value)}"
.checked=${selected}
@change=${handleChange} />
<label for="input" class="${classes}" tabindex="0">
<div class="${prefix}--tile__checkmark">
${CheckmarkFilled16({
children: !checkmarkLabel
? undefined
: svg`<title>${checkmarkLabel}</title>`,
})}
</div>
@change=${!disabled ? handleChange : undefined}
@keydown="${!disabled ? handleKeydown : undefined}" />
<label part="label" for="input" class="${classes}">
${CheckmarkFilled16({
children: !checkmarkLabel
? undefined
: svg`<title>${checkmarkLabel}</title>`,
class: `${prefix}--tile__checkmark`,
})}
<div class="${prefix}--tile-content"><slot></slot></div>
</label>
<slot name="decorator"></slot>
<slot name="ai-label" @slotchange="${this._handleSlotChange}"></slot>
`;
}

Expand Down
Loading

0 comments on commit 862159a

Please sign in to comment.