V15: Link Picker Modal UX Flow (#17994)
* Link Picker: reworked modal UX flow * Tweaked "Target" description * Link Picker modal tweaks * Localized "Reset URL" confirm modal * Awaits validation on picker change * Added `data-mark` attributes --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
This commit is contained in:
@@ -502,9 +502,9 @@ export default {
|
||||
copiedItemOfItems: 'Copied %0% out of %1% items',
|
||||
},
|
||||
defaultdialogs: {
|
||||
nodeNameLinkPicker: 'Link title',
|
||||
nodeNameLinkPicker: 'Title',
|
||||
urlLinkPicker: 'Link',
|
||||
anchorLinkPicker: 'Anchor / querystring',
|
||||
anchorLinkPicker: 'Anchor or querystring',
|
||||
anchorInsert: 'Name',
|
||||
closeThisWindow: 'Close this window',
|
||||
confirmdelete: 'Are you sure you want to delete',
|
||||
@@ -563,14 +563,14 @@ export default {
|
||||
includeDescendants: 'Include descendants',
|
||||
theFriendliestCommunity: 'The friendliest community',
|
||||
linkToPage: 'Link to document',
|
||||
openInNewWindow: 'Opens the linked document in a new window or tab',
|
||||
openInNewWindow: 'Opens the link in a new window or tab',
|
||||
linkToMedia: 'Link to media',
|
||||
selectContentStartNode: 'Select content start node',
|
||||
selectMedia: 'Select media',
|
||||
selectMediaType: 'Select media type',
|
||||
selectIcon: 'Select icon',
|
||||
selectItem: 'Select item',
|
||||
selectLink: 'Select link',
|
||||
selectLink: 'Configure link',
|
||||
selectMacro: 'Select macro',
|
||||
selectContent: 'Select content',
|
||||
selectContentType: 'Select content type',
|
||||
@@ -671,7 +671,7 @@ export default {
|
||||
email: 'Enter your email',
|
||||
enterMessage: 'Enter a message...',
|
||||
usernameHint: 'Your username is usually your email',
|
||||
anchor: '#value or ?key=value',
|
||||
anchor: 'Enter an anchor or querystring, #value or ?key=value',
|
||||
enterAlias: 'Enter alias...',
|
||||
generatingAlias: 'Generating alias...',
|
||||
a11yCreateItem: 'Create item',
|
||||
|
||||
@@ -491,9 +491,9 @@ export default {
|
||||
copiedItemOfItems: 'Copied %0% out of %1% items',
|
||||
},
|
||||
defaultdialogs: {
|
||||
nodeNameLinkPicker: 'Link title',
|
||||
nodeNameLinkPicker: 'Title',
|
||||
urlLinkPicker: 'Link',
|
||||
anchorLinkPicker: 'Anchor / querystring',
|
||||
anchorLinkPicker: 'Anchor or querystring',
|
||||
anchorInsert: 'Name',
|
||||
closeThisWindow: 'Close this window',
|
||||
confirmdelete: 'Are you sure you want to delete',
|
||||
@@ -553,7 +553,7 @@ export default {
|
||||
includeDescendants: 'Include descendants',
|
||||
theFriendliestCommunity: 'The friendliest community',
|
||||
linkToPage: 'Link to document',
|
||||
openInNewWindow: 'Opens the linked document in a new window or tab',
|
||||
openInNewWindow: 'Opens the link in a new window or tab',
|
||||
linkToMedia: 'Link to media',
|
||||
selectContentStartNode: 'Select content start node',
|
||||
selectEvent: 'Select event',
|
||||
@@ -561,7 +561,7 @@ export default {
|
||||
selectMediaType: 'Select media type',
|
||||
selectIcon: 'Select icon',
|
||||
selectItem: 'Select item',
|
||||
selectLink: 'Select link',
|
||||
selectLink: 'Configure link',
|
||||
selectMacro: 'Select macro',
|
||||
selectContent: 'Select content',
|
||||
selectContentType: 'Select content type',
|
||||
@@ -663,7 +663,7 @@ export default {
|
||||
email: 'Enter your email',
|
||||
enterMessage: 'Enter a message...',
|
||||
usernameHint: 'Your username is usually your email',
|
||||
anchor: '#value or ?key=value',
|
||||
anchor: 'Enter an anchor or querystring, #value or ?key=value',
|
||||
enterAlias: 'Enter alias...',
|
||||
generatingAlias: 'Generating alias...',
|
||||
a11yCreateItem: 'Create item',
|
||||
@@ -671,6 +671,7 @@ export default {
|
||||
a11yName: 'Name',
|
||||
rteParagraph: 'Write something amazing...',
|
||||
rteHeading: "What's the title?",
|
||||
enterUrl: 'Enter a URL...',
|
||||
},
|
||||
editcontenttype: {
|
||||
createListView: 'Create custom list view',
|
||||
@@ -798,6 +799,7 @@ export default {
|
||||
dictionary: 'Dictionary',
|
||||
dimensions: 'Dimensions',
|
||||
discard: 'Discard',
|
||||
document: 'Document',
|
||||
down: 'Down',
|
||||
download: 'Download',
|
||||
edit: 'Edit',
|
||||
@@ -2671,4 +2673,13 @@ export default {
|
||||
toolbar_removeItem: 'Remove action',
|
||||
toolbar_emptyGroup: 'Empty',
|
||||
},
|
||||
linkPicker: {
|
||||
modalSource: 'Source',
|
||||
modalManual: 'Manual',
|
||||
modalAnchorValidationMessage:
|
||||
'Please enter an anchor or querystring, or select a published document or media item, or manually configure the URL.',
|
||||
resetUrlHeadline: 'Reset URL?',
|
||||
resetUrlMessage: 'Are you sure you want to reset this URL?',
|
||||
resetUrlLabel: 'Reset',
|
||||
},
|
||||
} as UmbLocalizationDictionary;
|
||||
|
||||
@@ -6,38 +6,67 @@ import type {
|
||||
} from './link-picker-modal.token.js';
|
||||
import { css, customElement, html, nothing, query, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { isUmbracoFolder, UmbMediaTypeStructureRepository } from '@umbraco-cms/backoffice/media-type';
|
||||
import { umbFocus } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { umbBindToValidation, UmbValidationContext } from '@umbraco-cms/backoffice/validation';
|
||||
import { umbConfirmModal, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbDocumentDetailRepository } from '@umbraco-cms/backoffice/document';
|
||||
import { UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document';
|
||||
import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media';
|
||||
import type { UUIBooleanInputEvent, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import type { UUIBooleanInputEvent, UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
|
||||
type UmbInputPickerEvent = CustomEvent & { target: { value?: string } };
|
||||
|
||||
@customElement('umb-link-picker-modal')
|
||||
export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPickerModalData, UmbLinkPickerModalValue> {
|
||||
#propertyLayoutOrientation: 'horizontal' | 'vertical' = 'vertical';
|
||||
|
||||
#validationContext = new UmbValidationContext(this);
|
||||
|
||||
@state()
|
||||
private _allowedMediaTypeUniques?: Array<string>;
|
||||
|
||||
@state()
|
||||
private _config: UmbLinkPickerConfig = {
|
||||
hideAnchor: false,
|
||||
hideTarget: false,
|
||||
};
|
||||
|
||||
@state()
|
||||
private _allowedMediaTypeUniques?: Array<string>;
|
||||
|
||||
@query('umb-input-document')
|
||||
private _documentPickerElement?: UmbInputDocumentElement;
|
||||
|
||||
@query('umb-input-media')
|
||||
private _mediaPickerElement?: UmbInputMediaElement;
|
||||
|
||||
override async firstUpdated() {
|
||||
@query('#link-anchor', true)
|
||||
private _linkAnchorInput?: UUIInputElement;
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
if (this.data?.config) {
|
||||
this._config = this.data.config;
|
||||
}
|
||||
|
||||
if (this.modalContext) {
|
||||
this.observe(this.modalContext.size, (size) => {
|
||||
if (size === 'large' || size === 'full') {
|
||||
this.#propertyLayoutOrientation = 'horizontal';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.#getMediaTypes();
|
||||
}
|
||||
|
||||
protected override firstUpdated() {
|
||||
this._linkAnchorInput?.addValidator(
|
||||
'valueMissing',
|
||||
() => this.localize.term('linkPicker_modalAnchorValidationMessage'),
|
||||
() => !this.value.link.url && !this.value.link.queryString,
|
||||
);
|
||||
}
|
||||
|
||||
async #getMediaTypes() {
|
||||
// Get all the media types, excluding the folders, so that files are selectable media items.
|
||||
const mediaTypeStructureRepository = new UmbMediaTypeStructureRepository(this);
|
||||
const { data: mediaTypes } = await mediaTypeStructureRepository.requestAllowedChildrenOf(null);
|
||||
@@ -61,7 +90,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
} else if (query) {
|
||||
this.#partialUpdateLink({ queryString: `#${query}` });
|
||||
} else {
|
||||
this.#partialUpdateLink({ queryString: query });
|
||||
this.#partialUpdateLink({ queryString: '' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,24 +129,29 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
const unique = event.target.value;
|
||||
|
||||
if (unique) {
|
||||
if (type === 'document') {
|
||||
const documentRepository = new UmbDocumentDetailRepository(this);
|
||||
const { data: documentData } = await documentRepository.requestByUnique(unique);
|
||||
if (documentData) {
|
||||
icon = documentData.documentType.icon;
|
||||
name = documentData.variants[0].name;
|
||||
url = documentData.urls[0].url;
|
||||
switch (type) {
|
||||
case 'document': {
|
||||
const documentRepository = new UmbDocumentDetailRepository(this);
|
||||
const { data: documentData } = await documentRepository.requestByUnique(unique);
|
||||
if (documentData) {
|
||||
icon = documentData.documentType.icon;
|
||||
name = documentData.variants[0].name;
|
||||
url = documentData.urls[0]?.url ?? '';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'media') {
|
||||
const mediaRepository = new UmbMediaDetailRepository(this);
|
||||
const { data: mediaData } = await mediaRepository.requestByUnique(unique);
|
||||
if (mediaData) {
|
||||
icon = mediaData.mediaType.icon;
|
||||
name = mediaData.variants[0].name;
|
||||
url = mediaData.urls[0].url;
|
||||
case 'media': {
|
||||
const mediaRepository = new UmbMediaDetailRepository(this);
|
||||
const { data: mediaData } = await mediaRepository.requestByUnique(unique);
|
||||
if (mediaData) {
|
||||
icon = mediaData.mediaType.icon;
|
||||
name = mediaData.variants[0].name;
|
||||
url = mediaData.urls[0].url;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +160,30 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
name: this.value.link.name || name,
|
||||
type: unique ? type : undefined,
|
||||
unique,
|
||||
url,
|
||||
url: url ?? this.value.link.url,
|
||||
};
|
||||
|
||||
this.#partialUpdateLink(link);
|
||||
|
||||
await this.#validationContext.validate();
|
||||
}
|
||||
|
||||
async #onResetUrl() {
|
||||
if (this.value.link.url) {
|
||||
await umbConfirmModal(this, {
|
||||
color: 'danger',
|
||||
headline: this.localize.term('linkPicker_resetUrlHeadline'),
|
||||
content: this.localize.term('linkPicker_resetUrlMessage'),
|
||||
confirmLabel: this.localize.term('linkPicker_resetUrlLabel'),
|
||||
});
|
||||
}
|
||||
|
||||
this.#partialUpdateLink({ type: null, url: null });
|
||||
}
|
||||
|
||||
async #onSubmit() {
|
||||
await this.#validationContext.validate();
|
||||
this.modalContext?.submit();
|
||||
}
|
||||
|
||||
#triggerDocumentPicker() {
|
||||
@@ -140,12 +194,16 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
this._mediaPickerElement?.shadowRoot?.querySelector('#btn-add')?.dispatchEvent(new Event('click'));
|
||||
}
|
||||
|
||||
#triggerExternalUrl() {
|
||||
this.#partialUpdateLink({ type: 'external' });
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<umb-body-layout headline=${this.localize.term('defaultdialogs_selectLink')}>
|
||||
<uui-box>
|
||||
${this.#renderLinkUrlInput()} ${this.#renderLinkTitleInput()} ${this.#renderLinkTargetInput()}
|
||||
${this.#renderInternals()}
|
||||
${this.#renderLinkType()} ${this.#renderLinkAnchorInput()} ${this.#renderLinkTitleInput()}
|
||||
${this.#renderLinkTargetInput()}
|
||||
</uui-box>
|
||||
<div slot="actions">
|
||||
<uui-button label=${this.localize.term('general_close')} @click=${this._rejectModal}></uui-button>
|
||||
@@ -153,56 +211,134 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
color="positive"
|
||||
look="primary"
|
||||
label=${this.localize.term('general_submit')}
|
||||
?disabled=${!this.value.link.url && !this.value.link.queryString}
|
||||
@click=${this._submitModal}></uui-button>
|
||||
?disabled=${!this.value.link.type}
|
||||
@click=${this.#onSubmit}></uui-button>
|
||||
</div>
|
||||
</umb-body-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderLinkUrlInput() {
|
||||
#renderLinkType() {
|
||||
return html`
|
||||
<umb-property-layout orientation="vertical">
|
||||
<div class="side-by-side" slot="editor">
|
||||
<umb-property-layout
|
||||
orientation="vertical"
|
||||
label=${this.localize.term('defaultdialogs_link')}
|
||||
style="padding:0;">
|
||||
<uui-input
|
||||
slot="editor"
|
||||
placeholder=${this.localize.term('general_url')}
|
||||
label=${this.localize.term('general_url')}
|
||||
.value=${this.value.link.url ?? ''}
|
||||
?disabled=${this.value.link.unique ? true : false}
|
||||
@change=${this.#onLinkUrlInput}
|
||||
${umbFocus()}>
|
||||
</uui-input>
|
||||
</umb-property-layout>
|
||||
${when(
|
||||
!this._config.hideAnchor,
|
||||
() => html`
|
||||
<umb-property-layout
|
||||
orientation="vertical"
|
||||
label=${this.localize.term('defaultdialogs_anchorLinkPicker')}
|
||||
style="padding:0;">
|
||||
<uui-input
|
||||
slot="editor"
|
||||
placeholder=${this.localize.term('placeholders_anchor')}
|
||||
label=${this.localize.term('placeholders_anchor')}
|
||||
@change=${this.#onLinkAnchorInput}
|
||||
.value=${this.value.link.queryString ?? ''}></uui-input>
|
||||
</umb-property-layout>
|
||||
`,
|
||||
)}
|
||||
<umb-property-layout
|
||||
orientation=${this.#propertyLayoutOrientation}
|
||||
label=${this.localize.term('linkPicker_modalSource')}
|
||||
mandatory>
|
||||
<div slot="editor">
|
||||
${this.#renderLinkTypeSelection()} ${this.#renderDocumentPicker()} ${this.#renderMediaPicker()}
|
||||
${this.#renderLinkUrlInput()} ${this.#renderLinkUrlInputReadOnly()}
|
||||
</div>
|
||||
</umb-property-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderLinkTypeSelection() {
|
||||
if (this.value.link.type) return nothing;
|
||||
return html`
|
||||
<uui-button-group>
|
||||
<uui-button
|
||||
data-mark="action:document"
|
||||
look="placeholder"
|
||||
label=${this.localize.term('general_document')}
|
||||
@click=${this.#triggerDocumentPicker}></uui-button>
|
||||
<uui-button
|
||||
data-mark="action:media"
|
||||
look="placeholder"
|
||||
label=${this.localize.term('general_media')}
|
||||
@click=${this.#triggerMediaPicker}></uui-button>
|
||||
<uui-button
|
||||
data-mark="action:external"
|
||||
look="placeholder"
|
||||
label=${this.localize.term('linkPicker_modalManual')}
|
||||
@click=${this.#triggerExternalUrl}></uui-button>
|
||||
</uui-button-group>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderDocumentPicker() {
|
||||
return html`
|
||||
<umb-input-document
|
||||
?hidden=${!this.value.link.unique || this.value.link.type !== 'document'}
|
||||
.max=${1}
|
||||
.showOpenButton=${true}
|
||||
.value=${this.value.link.unique && this.value.link.type === 'document' ? this.value.link.unique : ''}
|
||||
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'document')}>
|
||||
</umb-input-document>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderMediaPicker() {
|
||||
return html`
|
||||
<umb-input-media
|
||||
?hidden=${!this.value.link.unique || this.value.link.type !== 'media'}
|
||||
.allowedContentTypeIds=${this._allowedMediaTypeUniques}
|
||||
.max=${1}
|
||||
.value=${this.value.link.unique && this.value.link.type === 'media' ? this.value.link.unique : ''}
|
||||
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'media')}></umb-input-media>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderLinkUrlInput() {
|
||||
if (this.value.link.type !== 'external') return nothing;
|
||||
return html`
|
||||
<uui-input
|
||||
data-mark="input:url"
|
||||
label=${this.localize.term('placeholders_enterUrl')}
|
||||
placeholder=${this.localize.term('placeholders_enterUrl')}
|
||||
.value=${this.value.link.url ?? ''}
|
||||
?disabled=${!!this.value.link.unique}
|
||||
?required=${this._config.hideAnchor}
|
||||
@change=${this.#onLinkUrlInput}
|
||||
${umbBindToValidation(this)}>
|
||||
${when(
|
||||
!this.value.link.unique,
|
||||
() => html`
|
||||
<div slot="append">
|
||||
<uui-button
|
||||
slot="append"
|
||||
compact
|
||||
label=${this.localize.term('general_remove')}
|
||||
@click=${this.#onResetUrl}>
|
||||
<uui-icon name="remove"></uui-icon>
|
||||
</uui-button>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
</uui-input>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderLinkUrlInputReadOnly() {
|
||||
if (!this.value.link.unique || !this.value.link.url) return nothing;
|
||||
return html`<uui-input readonly value=${this.value.link.url}></uui-input>`;
|
||||
}
|
||||
|
||||
#renderLinkAnchorInput() {
|
||||
if (this._config.hideAnchor) return nothing;
|
||||
return html`
|
||||
<umb-property-layout
|
||||
orientation=${this.#propertyLayoutOrientation}
|
||||
label=${this.localize.term('defaultdialogs_anchorLinkPicker')}>
|
||||
<uui-input
|
||||
data-mark="input:anchor"
|
||||
slot="editor"
|
||||
id="link-anchor"
|
||||
label=${this.localize.term('placeholders_anchor')}
|
||||
placeholder=${this.localize.term('placeholders_anchor')}
|
||||
.value=${this.value.link.queryString ?? ''}
|
||||
@change=${this.#onLinkAnchorInput}
|
||||
${umbBindToValidation(this)}></uui-input>
|
||||
</umb-property-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderLinkTitleInput() {
|
||||
return html`
|
||||
<umb-property-layout orientation="vertical" label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}>
|
||||
<umb-property-layout
|
||||
orientation=${this.#propertyLayoutOrientation}
|
||||
label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}>
|
||||
<uui-input
|
||||
data-mark="input:title"
|
||||
slot="editor"
|
||||
label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}
|
||||
placeholder=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}
|
||||
@@ -216,7 +352,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
#renderLinkTargetInput() {
|
||||
if (this._config.hideTarget) return nothing;
|
||||
return html`
|
||||
<umb-property-layout orientation="vertical" label=${this.localize.term('content_target')}>
|
||||
<umb-property-layout orientation=${this.#propertyLayoutOrientation} label=${this.localize.term('content_target')}>
|
||||
<uui-toggle
|
||||
slot="editor"
|
||||
label=${this.localize.term('defaultdialogs_openInNewWindow')}
|
||||
@@ -228,43 +364,6 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
`;
|
||||
}
|
||||
|
||||
#renderInternals() {
|
||||
return html`
|
||||
<umb-property-layout orientation="vertical" label=${this.localize.term('defaultdialogs_linkinternal')}>
|
||||
<div slot="editor">
|
||||
${when(
|
||||
!this.value.link.unique,
|
||||
() => html`
|
||||
<uui-button-group>
|
||||
<uui-button
|
||||
look="placeholder"
|
||||
label=${this.localize.term('defaultdialogs_linkToPage')}
|
||||
@click=${this.#triggerDocumentPicker}></uui-button>
|
||||
<uui-button
|
||||
look="placeholder"
|
||||
label=${this.localize.term('defaultdialogs_linkToMedia')}
|
||||
@click=${this.#triggerMediaPicker}></uui-button>
|
||||
</uui-button-group>
|
||||
`,
|
||||
)}
|
||||
<umb-input-document
|
||||
?hidden=${!this.value.link.unique || this.value.link.type !== 'document'}
|
||||
.max=${1}
|
||||
.showOpenButton=${true}
|
||||
.value=${this.value.link.unique && this.value.link.type === 'document' ? this.value.link.unique : ''}
|
||||
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'document')}>
|
||||
</umb-input-document>
|
||||
<umb-input-media
|
||||
?hidden=${!this.value.link.unique || this.value.link.type !== 'media'}
|
||||
.allowedContentTypeIds=${this._allowedMediaTypeUniques}
|
||||
.max=${1}
|
||||
.value=${this.value.link.unique && this.value.link.type === 'media' ? this.value.link.unique : ''}
|
||||
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'media')}></umb-input-media>
|
||||
</div>
|
||||
</umb-property-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
css`
|
||||
uui-box {
|
||||
@@ -277,15 +376,9 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
||||
|
||||
uui-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.side-by-side {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--uui-size-space-5);
|
||||
|
||||
umb-property-layout {
|
||||
flex: 1 1 0px;
|
||||
&[readonly] {
|
||||
margin-top: var(--uui-size-space-2);
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
Reference in New Issue
Block a user