Skip to content

Commit d12a9e1

Browse files
authored
feat(uui-card): Adds checkbox for selection (#1138)
* UUICard: adds "uui-checkbox" dependency * Adds `renderCheckbox()` method to "uui-card" component * "uui-card-media": adds `renderCheckbox()` * "uui-card-block-type": adds `renderCheckbox()` * "uui-card-content-node": adds `renderCheckbox()` * "uui-card-user": adds `renderCheckbox()` * Updates card stories with "Only Selectable" removing "selectOnly" from the "Selectable" story * Removed navigatable focus from the select-checkbox * Set cards `tabindex=-1` when `selectOnly` is enabled * Refactored `rel` attribute value/markup * Cards markup tidy-up
1 parent 0bcc80f commit d12a9e1

File tree

12 files changed

+173
-80
lines changed

12 files changed

+173
-80
lines changed

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/uui-card-block-type/lib/uui-card-block-type.element.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,19 @@ export class UUICardBlockTypeElement extends UUICardElement {
4949
${this.href ? this.#renderLink() : this.#renderButton()}
5050
<!-- Select border must be right after #open-part -->
5151
<div id="select-border"></div>
52-
52+
${this.selectable ? this.renderCheckbox() : nothing}
5353
<slot name="tag"></slot>
5454
<slot name="actions"></slot>
5555
`;
5656
}
5757

5858
#renderButton() {
59+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
5960
return html`
6061
<button
6162
id="open-part"
6263
class="uui-text"
63-
tabindex=${this.disabled ? (nothing as any) : '0'}
64+
tabindex=${ifDefined(tabIndex)}
6465
@click=${this.handleOpenClick}
6566
@keydown=${this.handleOpenKeydown}>
6667
${this.#renderContent()}
@@ -69,19 +70,16 @@ export class UUICardBlockTypeElement extends UUICardElement {
6970
}
7071

7172
#renderLink() {
73+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
74+
const rel = this.target === '_blank' ? 'noopener noreferrer' : undefined;
7275
return html`
7376
<a
7477
id="open-part"
7578
class="uui-text"
76-
tabindex=${this.disabled ? (nothing as any) : '0'}
79+
tabindex=${ifDefined(tabIndex)}
7780
href=${ifDefined(!this.disabled ? this.href : undefined)}
7881
target=${ifDefined(this.target || undefined)}
79-
rel=${ifDefined(
80-
this.rel ||
81-
ifDefined(
82-
this.target === '_blank' ? 'noopener noreferrer' : undefined,
83-
),
84-
)}>
82+
rel=${ifDefined(this.rel || rel)}>
8583
${this.#renderContent()}
8684
</a>
8785
`;
@@ -97,7 +95,7 @@ export class UUICardBlockTypeElement extends UUICardElement {
9795
return html`
9896
<div id="content">
9997
<span title="${this.name}" id="name">${this.name}</span>
100-
<small title="${this.description}">${this.description}<slot name="description"></slot></small>
98+
<small title="${ifDefined(this.description)}">${this.description}<slot name="description"></slot></small>
10199
</div></div>
102100
`;
103101
}

packages/uui-card-block-type/lib/uui-card-block-type.story.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,19 @@ export const Background: Story = {
7070

7171
export const Image: Story = {
7272
args: {
73-
slot: html`<img
74-
src="https://umbraco.com/media/v5gf3w2a/umbraco-toolkit-wide.svg"
75-
alt="" />`,
73+
slot: html`<img src="https://placedog.net/1447/?random" alt="" />`,
74+
},
75+
};
76+
77+
export const Selectable: Story = {
78+
args: {
79+
selectable: true,
80+
},
81+
};
82+
83+
export const OnlySelectable: Story = {
84+
args: {
85+
selectable: true,
86+
selectOnly: true,
7687
},
7788
};

packages/uui-card-content-node/lib/uui-card-content-node.element.ts

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,37 +86,39 @@ export class UUICardContentNodeElement extends UUICardElement {
8686
}
8787

8888
#renderButton() {
89-
return html`<button
90-
id="open-part"
91-
tabindex=${this.disabled ? (nothing as any) : 0}
92-
@click=${this.handleOpenClick}
93-
@keydown=${this.handleOpenKeydown}>
94-
${this.#renderContent()}
95-
</button>`;
89+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
90+
return html`
91+
<button
92+
id="open-part"
93+
tabindex=${ifDefined(tabIndex)}
94+
@click=${this.handleOpenClick}
95+
@keydown=${this.handleOpenKeydown}>
96+
${this.#renderContent()}
97+
</button>
98+
`;
9699
}
97100

98101
#renderLink() {
99-
return html`<a
100-
id="open-part"
101-
tabindex=${this.disabled ? (nothing as any) : 0}
102-
href=${ifDefined(!this.disabled ? this.href : undefined)}
103-
target=${ifDefined(this.target || undefined)}
104-
rel=${ifDefined(
105-
this.rel ||
106-
ifDefined(
107-
this.target === '_blank' ? 'noopener noreferrer' : undefined,
108-
),
109-
)}>
110-
${this.#renderContent()}
111-
</a>`;
102+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
103+
const rel = this.target === '_blank' ? 'noopener noreferrer' : undefined;
104+
return html`
105+
<a
106+
id="open-part"
107+
tabindex=${ifDefined(tabIndex)}
108+
href=${ifDefined(!this.disabled ? this.href : undefined)}
109+
target=${ifDefined(this.target || undefined)}
110+
rel=${ifDefined(this.rel || rel)}>
111+
${this.#renderContent()}
112+
</a>
113+
`;
112114
}
113115

114116
public render() {
115117
return html`
116118
${this.href ? this.#renderLink() : this.#renderButton()}
117119
<!-- Select border must be right after #open-part -->
118120
<div id="select-border"></div>
119-
121+
${this.selectable ? this.renderCheckbox() : nothing}
120122
<slot name="tag"></slot>
121123
<slot name="actions"></slot>
122124
`;
@@ -226,6 +228,11 @@ export class UUICardContentNodeElement extends UUICardElement {
226228
:host(:not([disabled])) #open-part:hover #default {
227229
color: var(--uui-color-interactive-emphasis);
228230
}
231+
232+
#select-checkbox {
233+
top: var(--uui-size-5);
234+
left: var(--uui-size-6);
235+
}
229236
`,
230237
];
231238
}

packages/uui-card-content-node/lib/uui-card-content-node.story.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,16 @@ export const CustomIcon: Story = {
7676
'icon slot': html`<uui-icon slot="icon" name="wand"></uui-icon>`,
7777
},
7878
};
79+
80+
export const Selectable: Story = {
81+
args: {
82+
selectable: true,
83+
},
84+
};
85+
86+
export const OnlySelectable: Story = {
87+
args: {
88+
selectable: true,
89+
selectOnly: true,
90+
},
91+
};

packages/uui-card-media/lib/uui-card-media.element.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ export class UUICardMediaElement extends UUICardElement {
7171
}
7272

7373
#renderButton() {
74+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
7475
return html`
7576
<button
7677
id="open-part"
77-
tabindex=${this.disabled ? (nothing as any) : '0'}
78+
tabindex=${ifDefined(tabIndex)}
7879
@click=${this.handleOpenClick}
7980
@keydown=${this.handleOpenKeydown}>
8081
${this.#renderContent()}
@@ -83,18 +84,15 @@ export class UUICardMediaElement extends UUICardElement {
8384
}
8485

8586
#renderLink() {
87+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
88+
const rel = this.target === '_blank' ? 'noopener noreferrer' : undefined;
8689
return html`
8790
<a
8891
id="open-part"
89-
tabindex=${this.disabled ? (nothing as any) : '0'}
92+
tabindex=${ifDefined(tabIndex)}
9093
href=${ifDefined(!this.disabled ? this.href : undefined)}
9194
target=${ifDefined(this.target || undefined)}
92-
rel=${ifDefined(
93-
this.rel ||
94-
ifDefined(
95-
this.target === '_blank' ? 'noopener noreferrer' : undefined,
96-
),
97-
)}>
95+
rel=${ifDefined(this.rel || rel)}>
9896
${this.#renderContent()}
9997
</a>
10098
`;
@@ -118,7 +116,7 @@ export class UUICardMediaElement extends UUICardElement {
118116
${this.href ? this.#renderLink() : this.#renderButton()}
119117
<!-- Select border must be right after .open-part -->
120118
<div id="select-border"></div>
121-
119+
${this.selectable ? this.renderCheckbox() : nothing}
122120
<slot name="tag"></slot>
123121
<slot name="actions"></slot>`;
124122
}
@@ -208,7 +206,6 @@ export class UUICardMediaElement extends UUICardElement {
208206
#content {
209207
position: relative;
210208
display: flex;
211-
width: 100%;
212209
flex-direction: column;
213210
font-family: inherit;
214211
box-sizing: border-box;

packages/uui-card-media/lib/uui-card-media.story.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,16 @@ export const Image: Story = {
9292
chromatic: { disableSnapshot: true },
9393
},
9494
};
95+
96+
export const Selectable: Story = {
97+
args: {
98+
selectable: true,
99+
},
100+
};
101+
102+
export const OnlySelectable: Story = {
103+
args: {
104+
selectable: true,
105+
selectOnly: true,
106+
},
107+
};

packages/uui-card-user/lib/uui-card-user.element.ts

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -40,53 +40,58 @@ export class UUICardUserElement extends UUICardElement {
4040
}
4141

4242
#renderButton() {
43-
return html`<div
44-
id="open-part"
45-
tabindex=${this.disabled ? (nothing as any) : '0'}
46-
@click=${this.handleOpenClick}
47-
@keydown=${this.handleOpenKeydown}>
48-
${this.#renderContent()}
49-
</div>`;
43+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
44+
return html`
45+
<div
46+
id="open-part"
47+
tabindex=${ifDefined(tabIndex)}
48+
@click=${this.handleOpenClick}
49+
@keydown=${this.handleOpenKeydown}>
50+
${this.#renderContent()}
51+
</div>
52+
`;
5053
}
5154

5255
#renderLink() {
53-
return html`<a
54-
id="open-part"
55-
tabindex=${this.disabled ? (nothing as any) : '0'}
56-
href=${ifDefined(!this.disabled ? this.href : undefined)}
57-
target=${ifDefined(this.target || undefined)}
58-
rel=${ifDefined(
59-
this.rel ||
60-
ifDefined(
61-
this.target === '_blank' ? 'noopener noreferrer' : undefined,
62-
),
63-
)}>
64-
${this.#renderContent()}
65-
</a>`;
56+
const tabIndex = !this.disabled ? (this.selectOnly ? -1 : 0) : undefined;
57+
const rel = this.target === '_blank' ? 'noopener noreferrer' : undefined;
58+
return html`
59+
<a
60+
id="open-part"
61+
tabindex=${ifDefined(tabIndex)}
62+
href=${ifDefined(!this.disabled ? this.href : undefined)}
63+
target=${ifDefined(this.target || undefined)}
64+
rel=${ifDefined(this.rel || rel)}>
65+
${this.#renderContent()}
66+
</a>
67+
`;
6668
}
6769

6870
#renderContent() {
69-
return html`<div id="content">
70-
${this._avatarSlotHasContent
71-
? nothing
72-
: html`<uui-avatar
73-
class="avatar"
74-
name=${this.name}
75-
size="m"></uui-avatar>`}
76-
<slot
77-
name="avatar"
78-
class="avatar"
79-
@slotchange=${this._avatarSlotChanged}></slot>
80-
<span title="${this.name}">${this.name}</span>
81-
<slot></slot>
82-
</div>`;
71+
return html`
72+
<div id="content">
73+
${this._avatarSlotHasContent
74+
? nothing
75+
: html`<uui-avatar
76+
class="avatar"
77+
name=${this.name}
78+
size="m"></uui-avatar>`}
79+
<slot
80+
name="avatar"
81+
class="avatar"
82+
@slotchange=${this._avatarSlotChanged}></slot>
83+
<span title="${this.name}">${this.name}</span>
84+
<slot></slot>
85+
</div>
86+
`;
8387
}
8488

8589
public render() {
8690
return html`
8791
${this.href ? this.#renderLink() : this.#renderButton()}
8892
<!-- Select border must be right after #open-part -->
8993
<div id="select-border"></div>
94+
${this.selectable ? this.renderCheckbox() : nothing}
9095
<slot name="tag"></slot>
9196
<slot name="actions"></slot>
9297
`;

packages/uui-card-user/lib/uui-card-user.story.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,16 @@ export const Actions: Story = {
7676
>`,
7777
},
7878
};
79+
80+
export const Selectable: Story = {
81+
args: {
82+
selectable: true,
83+
},
84+
};
85+
86+
export const OnlySelectable: Story = {
87+
args: {
88+
selectable: true,
89+
selectOnly: true,
90+
},
91+
};

0 commit comments

Comments
 (0)