diff --git a/packages/uui-card-content-node/lib/uui-card-content-node.element.ts b/packages/uui-card-content-node/lib/uui-card-content-node.element.ts index e0bc56d86..80658db04 100644 --- a/packages/uui-card-content-node/lib/uui-card-content-node.element.ts +++ b/packages/uui-card-content-node/lib/uui-card-content-node.element.ts @@ -24,11 +24,30 @@ export class UUICardContentNodeElement extends UUICardElement { @property({ type: String }) name = ''; + /** + * Node details + * @type {string} + * @attr + * @default '' + */ + @property({ type: String }) + detail = ''; + @state() private _iconSlotHasContent = false; - protected fallbackIcon = - ''; + protected fallbackIcon = ` + + + `; private _onSlotIconChange(event: Event) { this._iconSlotHasContent = @@ -41,18 +60,37 @@ export class UUICardContentNodeElement extends UUICardElement { return html``; } + protected renderDetail() { + return html`${this.detail}`; + } + + #renderContent() { + return html` + + + + + ${this._iconSlotHasContent === false + ? this._renderFallbackIcon() + : ''} + +
${this.name}
+
+ ${this.renderDetail()} +
+ `; + } + #renderButton() { - return html`
- - - ${this._iconSlotHasContent === false ? this._renderFallbackIcon() : ''} - - ${this.name} -
`; + ${this.#renderContent()} + `; } #renderLink() { @@ -67,11 +105,7 @@ export class UUICardContentNodeElement extends UUICardElement { this.target === '_blank' ? 'noopener noreferrer' : undefined, ), )}> - - - ${this._iconSlotHasContent === false ? this._renderFallbackIcon() : ''} - - ${this.name} + ${this.#renderContent()} `; } @@ -81,7 +115,6 @@ export class UUICardContentNodeElement extends UUICardElement {
- `; @@ -94,7 +127,6 @@ export class UUICardContentNodeElement extends UUICardElement { min-width: 250px; flex-direction: column; justify-content: space-between; - padding: var(--uui-size-3) var(--uui-size-4); } slot[name='tag'] { @@ -132,30 +164,57 @@ export class UUICardContentNodeElement extends UUICardElement { line-height: calc(2 * var(--uui-size-3)); } - #icon { - font-size: 1.2em; - margin-right: var(--uui-size-1); - } - #open-part { display: flex; position: relative; font-weight: 700; align-items: center; cursor: pointer; + flex-grow: 1; + padding: var(--uui-size-space-4) var(--uui-size-space-5); + } + + #content { + align-self: stretch; + display: flex; + flex-direction: column; } - :host([disabled]) #open-part { + #item { + position: relative; + display: flex; + align-self: stretch; + line-height: normal; + align-items: center; + margin-top: var(--uui-size-1); + } + + #icon { + font-size: 1.2em; + margin-right: var(--uui-size-1); + } + + :host([selectable]) #open-part { + padding: 0; + margin: var(--uui-size-space-4) var(--uui-size-space-5); + } + + :host([disabled]) #name { pointer-events: none; } - #open-part:hover { + :host(:not([disabled])) #open-part:hover #icon { + color: var(--uui-color-interactive-emphasis); + } + :host(:not([disabled])) #open-part:hover #name { text-decoration: underline; color: var(--uui-color-interactive-emphasis); } - - #name { - margin-top: 4px; + :host(:not([disabled])) #open-part:hover #detail { + color: var(--uui-color-interactive-emphasis); + } + :host(:not([disabled])) #open-part:hover #default { + color: var(--uui-color-interactive-emphasis); } `, ]; diff --git a/packages/uui-card-media/lib/uui-card-media.element.ts b/packages/uui-card-media/lib/uui-card-media.element.ts index a1b625a89..f950356ae 100644 --- a/packages/uui-card-media/lib/uui-card-media.element.ts +++ b/packages/uui-card-media/lib/uui-card-media.element.ts @@ -23,6 +23,15 @@ export class UUICardMediaElement extends UUICardElement { @property({ type: String }) name = ''; + /** + * Media detail + * @type {string} + * @attr detail + * @default '' + */ + @property({ type: String }) + detail?: string; + /** * Media file extension, without "." * @type {string} @@ -68,15 +77,7 @@ export class UUICardMediaElement extends UUICardElement { tabindex=${this.disabled ? (nothing as any) : '0'} @click=${this.handleOpenClick} @keydown=${this.handleOpenKeydown}> - - ${this.name} + ${this.#renderContent()} `; } @@ -94,16 +95,20 @@ export class UUICardMediaElement extends UUICardElement { this.target === '_blank' ? 'noopener noreferrer' : undefined, ), )}> + ${this.#renderContent()} + + `; + } + + #renderContent() { + return html` +
- ${this.name} - + ${this.name} + ${this.detail} +
`; } @@ -162,28 +167,18 @@ export class UUICardMediaElement extends UUICardElement { #open-part { position: absolute; - bottom: 0; - width: 100%; - background-color: var(--uui-color-surface); + z-index: 1; + inset: 0; color: var(--uui-color-interactive); border: none; cursor: pointer; - border-top: 1px solid var(--uui-color-divider); - border-radius: 0 0 var(--uui-border-radius) var(--uui-border-radius); display: flex; - justify-content: flex-start; - align-items: center; - font-family: inherit; - font-size: var(--uui-type-small-size); - box-sizing: border-box; - padding: var(--uui-size-2) var(--uui-size-4); - text-align: left; - word-break: break-word; + flex-direction: column; + justify-content: flex-end; } :host([disabled]) #open-part { pointer-events: none; - background: var(--uui-color-disabled); color: var(--uui-color-contrast-disabled); } @@ -197,6 +192,35 @@ export class UUICardMediaElement extends UUICardElement { opacity: 0; } + #content { + position: relative; + display: flex; + width: 100%; + align-items: center; + font-family: inherit; + font-size: var(--uui-type-small-size); + box-sizing: border-box; + text-align: left; + word-break: break-word; + padding-top: var(--uui-size-space-3); + } + + #content::before { + content: ''; + position: absolute; + inset: 0; + z-index: -1; + border-top: 1px solid var(--uui-color-divider); + border-radius: 0 0 var(--uui-border-radius) var(--uui-border-radius); + background-color: var(--uui-color-surface); + pointer-events: none; + opacity: 0.96; + } + + #name { + font-weight: 700; + } + :host( [image]:not([image='']):hover, [image]:not([image='']):focus, @@ -210,6 +234,18 @@ export class UUICardMediaElement extends UUICardElement { transition-delay: 0s; } + :host([selectable]) #open-part { + inset: var(--uui-size-space-3) var(--uui-size-space-4); + } + :host(:not([selectable])) #content { + padding: var(--uui-size-space-3) var(--uui-size-space-4); + } + :host([selectable]) #content::before { + inset: calc(var(--uui-size-space-3) * -1) + calc(var(--uui-size-space-4) * -1); + top: 0; + } + /* #info-icon { margin-right: var(--uui-size-2); diff --git a/packages/uui-card-user/lib/uui-card-user.element.ts b/packages/uui-card-user/lib/uui-card-user.element.ts index e6dc71267..226b5e021 100644 --- a/packages/uui-card-user/lib/uui-card-user.element.ts +++ b/packages/uui-card-user/lib/uui-card-user.element.ts @@ -44,7 +44,7 @@ export class UUICardUserElement extends UUICardElement { tabindex=${this.disabled ? (nothing as any) : '0'} @click=${this.handleOpenClick} @keydown=${this.handleOpenKeydown}> - ${this.name} + ${this.#renderContent()} `; } @@ -60,24 +60,32 @@ export class UUICardUserElement extends UUICardElement { this.target === '_blank' ? 'noopener noreferrer' : undefined, ), )}> - ${this.name} + ${this.#renderContent()} `; } - public render() { - return html` + #renderContent() { + return html`
${this._avatarSlotHasContent ? nothing : html``} - ${this.href ? this.#renderLink() : this.#renderButton()} + ${this.name} +
`; + } + + public render() { + return html` + ${this.href ? this.#renderLink() : this.#renderButton()} + +
`; @@ -88,10 +96,6 @@ export class UUICardUserElement extends UUICardElement { css` :host { min-width: 250px; - flex-direction: column; - justify-content: space-between; - padding: var(--uui-size-3); - align-items: center; } slot:not([name])::slotted(*) { @@ -113,8 +117,8 @@ export class UUICardUserElement extends UUICardElement { slot[name='actions'] { position: absolute; - top: var(--uui-size-4); - right: var(--uui-size-4); + top: var(--uui-size-space-4); + right: var(--uui-size-space-4); display: flex; justify-content: right; @@ -127,35 +131,46 @@ export class UUICardUserElement extends UUICardElement { opacity: 1; } - #avatar { - margin: var(--uui-size-3); + #open-part { + cursor: pointer; + flex-grow: 1; + padding: var(--uui-size-space-5) var(--uui-size-space-4); } - slot[name='icon']::slotted(*) { - font-size: 1.2em; + :host([disabled]) #open-part { + pointer-events: none; } - #open-part { + #open-part:hover #content { + color: var(--uui-color-interactive-emphasis); + } + #open-part:hover #content > span { + text-decoration: underline; + } + + :host([selectable]) #open-part { + padding: 0; + margin: var(--uui-size-space-5) var(--uui-size-space-4); + } + + #content { display: flex; + flex-direction: column; position: relative; - font-weight: 700; align-items: center; - cursor: pointer; margin: 0 0 3px 0; } - :host([disabled]) #open-part { - pointer-events: none; - } - - #open-part > span { + #content > span { vertical-align: center; margin-top: 3px; + font-weight: 700; } - #open-part:hover { - text-decoration: underline; - color: var(--uui-color-interactive-emphasis); + .avatar { + font-size: 1.5em; + margin-top: var(--uui-size-space-1); + margin-bottom: var(--uui-size-space-2); } `, ]; diff --git a/packages/uui-card/lib/uui-card.element.ts b/packages/uui-card/lib/uui-card.element.ts index 197dfc90f..f1e61443f 100644 --- a/packages/uui-card/lib/uui-card.element.ts +++ b/packages/uui-card/lib/uui-card.element.ts @@ -102,24 +102,18 @@ export class UUICardElement extends SelectOnlyMixin( transition: box-shadow 100ms ease-out; } - :host(*) { - /* TODO: implement globally shared outline style */ + :host([selectable]:focus-visible) { outline-color: var(--uui-color-focus); - outline-offset: 4px; + outline-width: var(--uui-card-border-width); + outline-style: solid; + outline-offset: var(--uui-card-border-width); } - :host(*) * { + :host() * { /* TODO: implement globally shared outline style */ outline-color: var(--uui-color-focus); } - :host(:focus) { - outline-color: var(--uui-color-focus); - outline-width: var(--uui-card-border-width); - outline-style: solid; - outline-offset: var(--uui-card-border-width); - } - :host([error])::before { content: ''; position: absolute; @@ -133,48 +127,110 @@ export class UUICardElement extends SelectOnlyMixin( border-radius: var(--uui-border-radius); } - :host([selectable]) { - cursor: pointer; + button { + font-size: inherit; + font-family: inherit; + border: 0; + padding: 0; + background-color: transparent; + text-align: left; + color: var(--uui-color-text); } - :host([disabled]) { - background: var(--uui-color-disabled); - color: var(--uui-color-disabled-contrast); + a { + text-decoration: none; + color: inherit; } - :host([selectable])::after { - content: ''; + button:focus, + a:focus { + outline-color: var(--uui-color-focus); + outline-width: var(--uui-card-border-width); + outline-style: solid; + outline-offset: var(--uui-card-border-width); + border-radius: var(--uui-border-radius); + } + + :host([selectable]) { + cursor: pointer; + } + :host([selectable]) #select-border { position: absolute; + z-index: 2; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; pointer-events: none; - inset: calc(var(--uui-card-border-width) * -1); - width: calc(100% + calc(var(--uui-card-border-width) * 2)); - height: calc(100% + calc(var(--uui-card-border-width) * 2)); - box-sizing: border-box; - border: var(--uui-card-border-width) solid var(--uui-color-selected); - border-radius: calc( - var(--uui-border-radius) + var(--uui-card-border-width) - ); - transition: opacity 100ms ease-out; opacity: 0; + transition: opacity 120ms; + } + :host([selectable]) #select-border::after { + content: ''; + position: absolute; + width: 100%; + height: 100%; + box-sizing: border-box; + border: 2px solid var(--uui-color-selected); + border-radius: calc(var(--uui-border-radius) + 2px); + box-shadow: + 0 0 4px 0 var(--uui-color-selected), + inset 0 0 2px 0 var(--uui-color-selected); + } + :host([selected]) #select-border { + opacity: 1; } - :host([selectable]:hover)::after { + :host([selectable]:not([selected]):hover) #select-border { opacity: 0.33; } - :host([selectable][selected]:hover)::after { - opacity: 0.66; + :host([selectable][selected]:hover) #select-border { + opacity: 0.8; + } + + :host([selectable]:not([selected])) #open-part:hover + #select-border { + opacity: 0; } - :host([selectable][selected])::after { + :host([selectable][selected]) #open-part:hover + #select-border { opacity: 1; } + :host([selectable]:not([selected]):hover) #select-border::after { + animation: not-selected--hover 1.2s infinite; + } + @keyframes not-selected--hover { + 0%, + 100% { + opacity: 0.66; + } + 50% { + opacity: 1; + } + } + + :host([selectable][selected]:hover) #select-border::after { + animation: selected--hover 1.4s infinite; + } + @keyframes selected--hover { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.66; + } + } + :host([selectable]) #open-part:hover + #select-border::after { + animation: none; + } + :host([select-only]) *, :host([select-only]) ::slotted(*) { pointer-events: none; } - a { - text-decoration: none; - color: inherit; + :host([disabled]) { + background: var(--uui-color-disabled); + color: var(--uui-color-disabled-contrast); } `, ]; diff --git a/packages/uui-css/lib/uui-text.css b/packages/uui-css/lib/uui-text.css index 364dd1bfd..9fdd33eab 100644 --- a/packages/uui-css/lib/uui-text.css +++ b/packages/uui-css/lib/uui-text.css @@ -1,3 +1,15 @@ +.uui-h1, +.uui-h2, +.uui-h3, +.uui-h4, +.uui-h5, +.uui-a, +.uui-p, +.uui-p-lead, +.uui-small, +.uui-quoteblock, +.uui-ul, +.uui-ol, .uui-text { font-family: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; @@ -6,7 +18,7 @@ } .uui-text h1, -.uui-text .uui-h1 { +.uui-h1 { font-size: var(--uui-type-h1-size); line-height: var(--uui-size-layout-4); font-weight: 300; @@ -20,13 +32,13 @@ } .uui-text h1.--no-top-margin, .uui-text h1:first-child, -.uui-text .uui-h1.--no-top-margin, -.uui-text .uui-h1:first-child { +.uui-h1.--no-top-margin, +.uui-h1:first-child { margin-top: 0; } .uui-text h2, -.uui-text .uui-h2 { +.uui-h2 { font-size: var(--uui-type-h2-size); line-height: var(--uui-size-layout-3); font-weight: 300; @@ -40,13 +52,13 @@ } .uui-text h2.--no-top-margin, .uui-text h2:first-child, -.uui-text .uui-h2.--no-top-margin, -.uui-text .uui-h2:first-child { +.uui-h2.--no-top-margin, +.uui-h2:first-child { margin-top: 0; } .uui-text h3, -.uui-text .uui-h3 { +.uui-h3 { font-size: var(--uui-type-h3-size); line-height: var(--uui-size-large); font-weight: 300; @@ -56,13 +68,13 @@ } .uui-text h3.--no-top-margin, .uui-text h3:first-child, -.uui-text .uui-h3.--no-top-margin, -.uui-text .uui-h3:first-child { +.uui-h3.--no-top-margin, +.uui-h3:first-child { margin-top: 0; } .uui-text h4, -.uui-text .uui-h4 { +.uui-h4 { font-size: var(--uui-type-h4-size); line-height: 21px; font-weight: 400; @@ -72,13 +84,13 @@ } .uui-text h4.--no-top-margin, .uui-text h4:first-child, -.uui-text .uui-h4.--no-top-margin, -.uui-text .uui-h4:first-child { +.uui-h4.--no-top-margin, +.uui-h4:first-child { margin-top: 0; } .uui-text h5, -.uui-text .uui-h5 { +.uui-h5 { font-size: var(--uui-type-h5-size); line-height: inherit; font-weight: 700; @@ -89,31 +101,37 @@ .uui-text h5.--no-top-margin, .uui-text h5:first-child, -.uui-text .uui-h5.--no-top-margin, -.uui-text .uui-h5:first-child { +.uui-h5.--no-top-margin, +.uui-h5:first-child { margin-top: 0; } +.uui-p, .uui-text p { margin-top: var(--uui-size-layout-1); margin-bottom: var(--uui-size-layout-1); } +.uui-p-lead, .uui-text p.uui-lead { font-size: var(--uui-size-6); } +.uui-a, .uui-text a { color: var(--uui-color-interactive); } -.uui-text a:link, +.uui-a:link, +.uui-a:active .uui-text a:link, .uui-text a:active { color: var(--uui-color-interactive); } +.uui-a:hover, .uui-text a:hover { color: var(--uui-color-interactive-emphasis); } +.uui-small, .uui-text small { display: inline-block; font-size: var(--uui-type-small-size); @@ -121,6 +139,7 @@ margin-bottom: var(--uui-size-layout-1); } +.uui-quoteblock, .uui-text blockquote { float: right; font-size: 15px; @@ -134,6 +153,7 @@ line-height: inherit; } +.uui-quoteblock:before, .uui-text blockquote:before { content: open-quote; margin-left: -0.4em; @@ -143,6 +163,7 @@ font-size: 2em; } +.uui-quoteblock:after, .uui-text blockquote:after { content: close-quote; margin-left: 0.04em; @@ -154,6 +175,7 @@ display: inline-block; } +.uui-ul, .uui-text ul { list-style-type: square; padding-left: var(--uui-size-layout-1); @@ -161,6 +183,7 @@ margin-bottom: var(--uui-size-layout-1); } +.uui-ol, .uui-text ol { padding-left: var(--uui-size-layout-1); margin-top: var(--uui-size-layout-1); diff --git a/packages/uui-ref-node/lib/uui-ref-node.element.ts b/packages/uui-ref-node/lib/uui-ref-node.element.ts index 2ae97da50..f8e12b8f5 100644 --- a/packages/uui-ref-node/lib/uui-ref-node.element.ts +++ b/packages/uui-ref-node/lib/uui-ref-node.element.ts @@ -67,8 +67,18 @@ export class UUIRefNodeElement extends UUIRefElement { @state() private _iconSlotHasContent = false; - protected fallbackIcon = - ''; + protected fallbackIcon = ` + + + `; connectedCallback() { super.connectedCallback(); @@ -141,17 +151,17 @@ export class UUIRefNodeElement extends UUIRefElement { public render() { return html` - ${this.#renderSomething()} + ${this.#renderOpenPart()}
- + `; } - #renderSomething() { + #renderOpenPart() { if (this.readonly) { return html`${this.#renderContent()}`; } else { @@ -164,7 +174,7 @@ export class UUIRefNodeElement extends UUIRefElement { css` :host { min-width: 250px; - padding: calc(var(--uui-size-2) + 1px); + padding: 1px; } #content { @@ -179,6 +189,10 @@ export class UUIRefNodeElement extends UUIRefElement { color: inherit; text-decoration: none; cursor: pointer; + align-self: stretch; + display: flex; + flex-grow: 1; + padding: calc(var(--uui-size-2)); } #icon { @@ -204,11 +218,16 @@ export class UUIRefNodeElement extends UUIRefElement { font-size: var(--uui-type-small-size); } + :host([selectable]) #open-part { + flex-grow: 0; + padding: 0; + margin: calc(var(--uui-size-2)); + } + :host(:not([disabled])) #open-part:hover #icon { color: var(--uui-color-interactive-emphasis); } :host(:not([disabled])) #open-part:hover #name { - font-weight: 700; text-decoration: underline; color: var(--uui-color-interactive-emphasis); } diff --git a/packages/uui-ref/lib/uui-ref.element.ts b/packages/uui-ref/lib/uui-ref.element.ts index 63fada255..3b4782ce1 100644 --- a/packages/uui-ref/lib/uui-ref.element.ts +++ b/packages/uui-ref/lib/uui-ref.element.ts @@ -77,9 +77,11 @@ export class UUIRefElement extends SelectOnlyMixin( transition: --uui-card-before-opacity 120ms; } - :host(:focus) { - /** TODO: implement focus outline. */ - outline-color: #6ab4f0; + :host([selectable]:focus-visible) { + outline-color: var(--uui-color-focus); + outline-width: var(--uui-card-border-width); + outline-style: solid; + outline-offset: var(--uui-card-border-width); } :host([error]) { @@ -179,6 +181,19 @@ export class UUIRefElement extends SelectOnlyMixin( text-align: left; color: var(--uui-color-text); } + a { + text-decoration: none; + color: inherit; + } + + button:focus, + a:focus { + outline-color: var(--uui-color-focus); + outline-width: var(--uui-card-border-width); + outline-style: solid; + outline-offset: var(--uui-card-border-width); + border-radius: var(--uui-border-radius); + } slot[name='actions'] { display: flex; @@ -186,11 +201,16 @@ export class UUIRefElement extends SelectOnlyMixin( --uui-button-height: calc(var(--uui-size-2) * 4); margin-right: var(--uui-size-2); } + #tag-container { + margin: calc(var(--uui-size-2)); + } #actions-container { + margin: calc(var(--uui-size-2)); opacity: 0; transition: opacity 120ms; } :host(:hover) #actions-container, + :host(:focus) #actions-container, :host(:focus-within) #actions-container { opacity: 1; } @@ -208,8 +228,6 @@ export class UUIRefElement extends SelectOnlyMixin( } slot[name='tag'] { - flex-grow: 1; - display: flex; justify-content: flex-end; align-items: center; diff --git a/packages/uui-symbol-file/lib/uui-symbol-file.element.ts b/packages/uui-symbol-file/lib/uui-symbol-file.element.ts index c949b300d..9db4512c1 100644 --- a/packages/uui-symbol-file/lib/uui-symbol-file.element.ts +++ b/packages/uui-symbol-file/lib/uui-symbol-file.element.ts @@ -1,6 +1,7 @@ import { LitElement, html, css } from 'lit'; import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; import { property } from 'lit/decorators.js'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; /** * @element uui-file-symbol @@ -16,20 +17,30 @@ export class UUISymbolFileElement extends LitElement { type = ''; render() { - return html` - + + + ${this.type - ? html`${this.type.toUpperCase()}` - : ''} `; + ? html`${this.type.toUpperCase()}` + : ''} + `; } static styles = [ + UUITextStyles, css` :host { position: relative; @@ -38,8 +49,8 @@ export class UUISymbolFileElement extends LitElement { #file-type { position: absolute; - bottom: 24%; - left: 25.5%; + bottom: 20%; + left: 12%; margin-left: calc(var(--uui-size-3) * -1); padding: 0px var(--uui-size-3); font-weight: 700; @@ -48,10 +59,12 @@ export class UUISymbolFileElement extends LitElement { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + border-radius: var(--uui-border-radius); } #icon { - fill: var(--uui-color-border-standalone); + width: 100%; + color: var(--uui-color-border-standalone); } `, ]; diff --git a/packages/uui-symbol-folder/lib/uui-symbol-folder.element.ts b/packages/uui-symbol-folder/lib/uui-symbol-folder.element.ts index c6b371b63..cd10cc8f2 100644 --- a/packages/uui-symbol-folder/lib/uui-symbol-folder.element.ts +++ b/packages/uui-symbol-folder/lib/uui-symbol-folder.element.ts @@ -10,12 +10,16 @@ export class UUISymbolFolderElement extends LitElement { render() { return html` - `; + d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" /> + `; } static styles = [ @@ -28,7 +32,8 @@ export class UUISymbolFolderElement extends LitElement { } #icon { - fill: var(--uui-color-border); + width: 100%; + color: var(--uui-color-border-standalone); } `, ];