diff --git a/src/extensions/file_based_loadorder/views/ItemRenderer.tsx b/src/extensions/file_based_loadorder/views/ItemRenderer.tsx index 5b1fd7057..509806b48 100644 --- a/src/extensions/file_based_loadorder/views/ItemRenderer.tsx +++ b/src/extensions/file_based_loadorder/views/ItemRenderer.tsx @@ -1,157 +1,154 @@ -import * as React from 'react'; -import { Checkbox, ListGroupItem } from 'react-bootstrap'; -import { withTranslation } from 'react-i18next'; -import { connect } from 'react-redux'; -import { ComponentEx } from '../../../util/ComponentEx'; - -import { IItemRendererProps, ILoadOrderEntry, LoadOrder } from '../types/types'; - -import { Icon, tooltip } from '../../../controls/api'; -import { IProfile, IState } from '../../../types/api'; - -import * as selectors from '../../../util/selectors'; -import { getSafe } from '../../../util/storeHelper'; - -import { setFBLoadOrderEntry } from '../actions/loadOrder'; - -interface IConnectedProps { - modState: any; - loadOrder: LoadOrder; - profile: IProfile; -} - -interface IActionProps { - onSetLoadOrderEntry: (profileId: string, entry: ILoadOrderEntry) => void; -} - -interface IBaseProps { - className?: string; - item: IItemRendererProps; -} - -type IProps = IBaseProps & IConnectedProps & IActionProps; - -class ItemRenderer extends ComponentEx { - public render() { - const item = this.props.item.loEntry; - const displayCheckboxes = this.props.item.displayCheckboxes; - return this.renderDraggable(item, displayCheckboxes); - } - - private renderValidationError(): JSX.Element { - const { invalidEntries, loEntry } = this.props.item; - const invalidEntry = (invalidEntries !== undefined) - ? invalidEntries.find(inv => inv.id.toLowerCase() === loEntry.id.toLowerCase()) - : undefined; - return (invalidEntry !== undefined) - ? ( - - ) : null; - } - - private renderExternalBanner(item: ILoadOrderEntry): JSX.Element { - const { t } = this.props; - return this.isExternal(item) ? ( -
- - {t('Not managed by Vortex')} -
- ) : null; - } - - private renderDraggable(item: ILoadOrderEntry, displayCheckboxes: boolean): JSX.Element { - const { loadOrder, className } = this.props; - const key = !!item.name ? `${item.name}` : `${item.id}`; - - const position = loadOrder.findIndex(entry => entry.id === item.id) + 1; - - let classes = ['load-order-entry']; - if (className !== undefined) { - classes = classes.concat(className.split(' ')); - } - - if (this.isExternal(item)) { - classes = classes.concat('external'); - } - - const checkBox = () => (displayCheckboxes) - ? ( - - ) - : null; - - const lock = () => (this.isLocked(item)) - ? ( - - ) : null; - - const dragHandleClasses = this.isLocked(item) - ? 'drag-handle-icon undraggable' : 'drag-handle-icon'; - - return ( - - -

{position}

- {this.renderValidationError()} -

{key}

- {this.renderExternalBanner(item)} - {checkBox()} - {lock()} -
- ); - } - - private isLocked(item: ILoadOrderEntry): boolean { - return [true, 'true', 'always'].includes(item.locked); - } - - private isExternal(item: ILoadOrderEntry): boolean { - return (item.modId !== undefined) ? false : true; - } - - private onStatusChange = (evt: any) => { - const { item, onSetLoadOrderEntry, profile } = this.props; - const entry = { - ...item.loEntry, - enabled: evt.target.checked, - }; - onSetLoadOrderEntry(profile.id, entry); - } -} - -const empty = {}; -function mapStateToProps(state: IState, ownProps: IProps): IConnectedProps { - const profile: IProfile = selectors.activeProfile(state); - return { - profile, - loadOrder: getSafe(state, ['persistent', 'loadOrder', profile.id], []), - modState: getSafe(profile, ['modState'], empty), - }; -} - -function mapDispatchToProps(dispatch: any): IActionProps { - return { - onSetLoadOrderEntry: (profileId, entry) => - dispatch(setFBLoadOrderEntry(profileId, entry)), - }; -} - -export default withTranslation(['common'])( - connect(mapStateToProps, mapDispatchToProps)( - ItemRenderer) as any) as React.ComponentClass<{ - className?: string, - item: IItemRendererProps, - }>; +import * as React from 'react'; +import { Checkbox, ListGroupItem } from 'react-bootstrap'; +import { withTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; +import { ComponentEx } from '../../../util/ComponentEx'; + +import { IItemRendererProps, ILoadOrderEntry, LoadOrder } from '../types/types'; + +import { Icon, tooltip } from '../../../controls/api'; +import { IProfile, IState } from '../../../types/api'; + +import * as selectors from '../../../util/selectors'; +import { getSafe } from '../../../util/storeHelper'; + +import { setFBLoadOrderEntry } from '../actions/loadOrder'; + +interface IConnectedProps { + modState: any; + loadOrder: LoadOrder; + profile: IProfile; +} + +interface IActionProps { + onSetLoadOrderEntry: (profileId: string, entry: ILoadOrderEntry) => void; +} + +interface IBaseProps { + className?: string; + item: IItemRendererProps; +} + +type IProps = IBaseProps & IConnectedProps & IActionProps; + +class ItemRenderer extends ComponentEx { + public render() { + const item = this.props.item.loEntry; + const displayCheckboxes = this.props.item.displayCheckboxes; + return this.renderDraggable(item, displayCheckboxes); + } + + private renderValidationError(): JSX.Element { + const { invalidEntries, loEntry } = this.props.item; + const invalidEntry = (invalidEntries !== undefined) + ? invalidEntries.find(inv => inv.id.toLowerCase() === loEntry.id.toLowerCase()) + : undefined; + return (invalidEntry !== undefined) + ? ( + + ) : null; + } + + private renderExternalBanner(item: ILoadOrderEntry): JSX.Element { + const { t } = this.props; + return this.isExternal(item) ? ( +
+ + {t('Not managed by Vortex')} +
+ ) : null; + } + + private renderDraggable(item: ILoadOrderEntry, displayCheckboxes: boolean): JSX.Element { + const { loadOrder, className } = this.props; + const key = !!item.name ? `${item.name}` : `${item.id}`; + + const position = loadOrder.findIndex(entry => entry.id === item.id) + 1; + + let classes = ['load-order-entry']; + if (className !== undefined) { + classes = classes.concat(className.split(' ')); + } + + if (this.isExternal(item)) { + classes = classes.concat('external'); + } + + const checkBox = () => (displayCheckboxes) + ? ( + + ) + : null; + + const lock = () => (this.isLocked(item)) + ? ( + + ) : null; + + return ( + + +

{position}

+ {this.renderValidationError()} +

{key}

+ {this.renderExternalBanner(item)} + {checkBox()} + {lock()} +
+ ); + } + + private isLocked(item: ILoadOrderEntry): boolean { + return [true, 'true', 'always'].includes(item.locked); + } + + private isExternal(item: ILoadOrderEntry): boolean { + return (item.modId !== undefined) ? false : true; + } + + private onStatusChange = (evt: any) => { + const { item, onSetLoadOrderEntry, profile } = this.props; + const entry = { + ...item.loEntry, + enabled: evt.target.checked, + }; + onSetLoadOrderEntry(profile.id, entry); + } +} + +const empty = {}; +function mapStateToProps(state: IState, ownProps: IProps): IConnectedProps { + const profile: IProfile = selectors.activeProfile(state); + return { + profile, + loadOrder: getSafe(state, ['persistent', 'loadOrder', profile.id], []), + modState: getSafe(profile, ['modState'], empty), + }; +} + +function mapDispatchToProps(dispatch: any): IActionProps { + return { + onSetLoadOrderEntry: (profileId, entry) => + dispatch(setFBLoadOrderEntry(profileId, entry)), + }; +} + +export default withTranslation(['common'])( + connect(mapStateToProps, mapDispatchToProps)( + ItemRenderer) as any) as React.ComponentClass<{ + className?: string, + item: IItemRendererProps, + }>; diff --git a/src/extensions/mod_load_order/views/DefaultItemRenderer.tsx b/src/extensions/mod_load_order/views/DefaultItemRenderer.tsx index a2dc8783b..d89d160a9 100644 --- a/src/extensions/mod_load_order/views/DefaultItemRenderer.tsx +++ b/src/extensions/mod_load_order/views/DefaultItemRenderer.tsx @@ -1,194 +1,191 @@ -import * as React from 'react'; -import { Checkbox, ListGroupItem } from 'react-bootstrap'; -import { withTranslation } from 'react-i18next'; -import { connect } from 'react-redux'; -import * as url from 'url'; -import { ComponentEx, translate } from '../../../util/ComponentEx'; - -import { IItemRendererOptions, ILoadOrder, ILoadOrderDisplayItem, - ILoadOrderEntry } from '../types/types'; - -import { Icon } from '../../../controls/api'; -import { IProfile, IState } from '../../../types/api'; - -import * as selectors from '../../../util/selectors'; -import { getSafe } from '../../../util/storeHelper'; - -import { setLoadOrderEntry } from '../actions/loadOrder'; - -interface IConnectedProps { - modState: any; - loadOrder: ILoadOrder; - profile: IProfile; - itemRendererOptions: IItemRendererOptions; -} - -interface IActionProps { - onSetLoadOrderEntry: (profileId: string, modId: string, entry: ILoadOrderEntry) => void; -} - -interface IBaseProps { - className?: string; - item: ILoadOrderDisplayItem; - onRef: (element: any) => any; - onContextMenu?: (evt: any) => any; -} - -type IProps = IBaseProps & IConnectedProps & IActionProps; - -class DefaultItemRenderer extends ComponentEx { - constructor(props: IProps) { - super(props); - this.initState({}); - } - - public render() { - const item = this.props.item; - return (!!item.locked) - ? this.renderLocked(item) - : this.renderDraggable(item); - } - - private renderModImg(): JSX.Element { - const { itemRendererOptions, item } = this.props; - let effectiveURL; - try { - effectiveURL = url.parse(item.imgUrl); - } catch (err) { - return null; - } - effectiveURL = (effectiveURL.protocol !== null) - ? item.imgUrl - : url.pathToFileURL(item.imgUrl).href; - return (itemRendererOptions.listViewType !== 'compact') - ? - : null; - } - - private renderExternalBanner(): JSX.Element { - const { t } = this.props; - return ( -
- {t('Not managed by Vortex')} - -
- ); - } - - private renderLocked(item: ILoadOrderDisplayItem): JSX.Element { - const { loadOrder, className } = this.props; - const position = (item.prefix !== undefined) - ? item.prefix - : loadOrder[item.id].pos + 1; - - const key = `${item.name}-${position}`; - - let classes = ['load-order-entry']; - if (className !== undefined) { - classes = classes.concat(className.split(' ')); - } - return ( - -

{position}

- {this.renderModImg()} -
-

{item.name}

- {(item.external === true) && this.renderExternalBanner()} -
- -
- ); - } - - private renderDraggable(item: ILoadOrderDisplayItem): JSX.Element { - const { loadOrder, className, itemRendererOptions } = this.props; - const position = (item.prefix !== undefined) - ? item.prefix - : loadOrder[item.id].pos + 1; - - const key = `${item.name}-${position}`; - - let classes = ['load-order-entry']; - if (className !== undefined) { - classes = classes.concat(className.split(' ')); - } - - const checkBox = () => (!!itemRendererOptions?.displayCheckboxes) - ? ( - - ) - : null; - - const dragHandleClasses = item.locked - ? 'drag-handle-icon undraggable' : 'drag-handle-icon'; - - return ( - - -

{position}

-
- {(!!item?.external) && this.renderExternalBanner()} - {this.renderModImg()} -
-

{item.name}

- {checkBox()} -
- ); - } - - private onStatusChange = (evt: any) => { - const { loadOrder, item, onSetLoadOrderEntry, profile } = this.props; - const entry = { - pos: loadOrder[item.id].pos, - enabled: evt.target.checked, - }; - - onSetLoadOrderEntry(profile.id, item.id, entry); - } - - private setRef = (ref: any): any => { - return this.props.onRef(ref); - } -} - -const empty = {}; -const defaultRendererOpts: IItemRendererOptions = { listViewType: 'full', displayCheckboxes: true }; -function mapStateToProps(state: IState, ownProps: IProps): IConnectedProps { - const profile: IProfile = selectors.activeProfile(state); - return { - profile, - loadOrder: getSafe(state, ['persistent', 'loadOrder', profile.id], empty), - modState: getSafe(profile, ['modState'], empty), - itemRendererOptions: getSafe(state, - ['settings', 'loadOrder', 'rendererOptions', profile.gameId], defaultRendererOpts), - }; -} - -function mapDispatchToProps(dispatch: any): IActionProps { - return { - onSetLoadOrderEntry: (profileId, modId, entry) => - dispatch(setLoadOrderEntry(profileId, modId, entry)), - }; -} - -export default withTranslation(['common'])( - connect(mapStateToProps, mapDispatchToProps)( - DefaultItemRenderer) as any) as React.ComponentClass<{ - className?: string, - item: ILoadOrderDisplayItem, - onRef: (ref: any) => any - onContextMenu?: (evt: any) => any }>; +import * as React from 'react'; +import { Checkbox, ListGroupItem } from 'react-bootstrap'; +import { withTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; +import * as url from 'url'; +import { ComponentEx, translate } from '../../../util/ComponentEx'; + +import { IItemRendererOptions, ILoadOrder, ILoadOrderDisplayItem, + ILoadOrderEntry } from '../types/types'; + +import { Icon } from '../../../controls/api'; +import { IProfile, IState } from '../../../types/api'; + +import * as selectors from '../../../util/selectors'; +import { getSafe } from '../../../util/storeHelper'; + +import { setLoadOrderEntry } from '../actions/loadOrder'; + +interface IConnectedProps { + modState: any; + loadOrder: ILoadOrder; + profile: IProfile; + itemRendererOptions: IItemRendererOptions; +} + +interface IActionProps { + onSetLoadOrderEntry: (profileId: string, modId: string, entry: ILoadOrderEntry) => void; +} + +interface IBaseProps { + className?: string; + item: ILoadOrderDisplayItem; + onRef: (element: any) => any; + onContextMenu?: (evt: any) => any; +} + +type IProps = IBaseProps & IConnectedProps & IActionProps; + +class DefaultItemRenderer extends ComponentEx { + constructor(props: IProps) { + super(props); + this.initState({}); + } + + public render() { + const item = this.props.item; + return (!!item.locked) + ? this.renderLocked(item) + : this.renderDraggable(item); + } + + private renderModImg(): JSX.Element { + const { itemRendererOptions, item } = this.props; + let effectiveURL; + try { + effectiveURL = url.parse(item.imgUrl); + } catch (err) { + return null; + } + effectiveURL = (effectiveURL.protocol !== null) + ? item.imgUrl + : url.pathToFileURL(item.imgUrl).href; + return (itemRendererOptions.listViewType !== 'compact') + ? + : null; + } + + private renderExternalBanner(): JSX.Element { + const { t } = this.props; + return ( +
+ {t('Not managed by Vortex')} + +
+ ); + } + + private renderLocked(item: ILoadOrderDisplayItem): JSX.Element { + const { loadOrder, className } = this.props; + const position = (item.prefix !== undefined) + ? item.prefix + : loadOrder[item.id].pos + 1; + + const key = `${item.name}-${position}`; + + let classes = ['load-order-entry']; + if (className !== undefined) { + classes = classes.concat(className.split(' ')); + } + return ( + +

{position}

+ {this.renderModImg()} +
+

{item.name}

+ {(item.external === true) && this.renderExternalBanner()} +
+ +
+ ); + } + + private renderDraggable(item: ILoadOrderDisplayItem): JSX.Element { + const { loadOrder, className, itemRendererOptions } = this.props; + const position = (item.prefix !== undefined) + ? item.prefix + : loadOrder[item.id].pos + 1; + + const key = `${item.name}-${position}`; + + let classes = ['load-order-entry']; + if (className !== undefined) { + classes = classes.concat(className.split(' ')); + } + + const checkBox = () => (!!itemRendererOptions?.displayCheckboxes) + ? ( + + ) + : null; + + return ( + + +

{position}

+
+ {(!!item?.external) && this.renderExternalBanner()} + {this.renderModImg()} +
+

{item.name}

+ {checkBox()} +
+ ); + } + + private onStatusChange = (evt: any) => { + const { loadOrder, item, onSetLoadOrderEntry, profile } = this.props; + const entry = { + pos: loadOrder[item.id].pos, + enabled: evt.target.checked, + }; + + onSetLoadOrderEntry(profile.id, item.id, entry); + } + + private setRef = (ref: any): any => { + return this.props.onRef(ref); + } +} + +const empty = {}; +const defaultRendererOpts: IItemRendererOptions = { listViewType: 'full', displayCheckboxes: true }; +function mapStateToProps(state: IState, ownProps: IProps): IConnectedProps { + const profile: IProfile = selectors.activeProfile(state); + return { + profile, + loadOrder: getSafe(state, ['persistent', 'loadOrder', profile.id], empty), + modState: getSafe(profile, ['modState'], empty), + itemRendererOptions: getSafe(state, + ['settings', 'loadOrder', 'rendererOptions', profile.gameId], defaultRendererOpts), + }; +} + +function mapDispatchToProps(dispatch: any): IActionProps { + return { + onSetLoadOrderEntry: (profileId, modId, entry) => + dispatch(setLoadOrderEntry(profileId, modId, entry)), + }; +} + +export default withTranslation(['common'])( + connect(mapStateToProps, mapDispatchToProps)( + DefaultItemRenderer) as any) as React.ComponentClass<{ + className?: string, + item: ILoadOrderDisplayItem, + onRef: (ref: any) => any + onContextMenu?: (evt: any) => any }>; diff --git a/src/stylesheets/vortex/page-mod-load-order.scss b/src/stylesheets/vortex/page-mod-load-order.scss index 6c5436a42..3e558a7b3 100644 --- a/src/stylesheets/vortex/page-mod-load-order.scss +++ b/src/stylesheets/vortex/page-mod-load-order.scss @@ -1,279 +1,282 @@ -#collections-load-order-list, -#page-file-based-loadorder, -#page-generic-loadorder { - - .layout-flex { - flex: 1 1 0; - position: relative; - overflow: auto; - } - - .layout-container { - gap: 8px; - } - - - .file-based-load-order-container { - gap: 8px; - } - - .file-based-load-order-list { - - .list-group { - display: flex; - align-items: stretch; - flex-direction: column; - gap: 4px; - margin: 0; - padding: 0 8px 0 0; // padding between scrollbar and list items - } - } - - .load-order-entry { - - display: flex; - flex-direction: row; - align-items: center; - background-color: $brand-bg; - gap: 8px; - - height: 100%; - overflow: auto; - - margin: 0; - border: 1px gray solid; - border-radius: 4px; - padding: 0 12px 0 12px; - - .drag-handle-icon { - fill: $brand-menu; - } - - .load-order-index { - //padding: 2px 2px; - // margin-right: 15px; - min-width: 24px; - } - - .load-order-name-container { - display: flex; - align-items: center; - gap: 8px; - } - - .load-order-name { - flex: 1 1 0; - } - - .locked-entry-logo { - margin: 0; - } - - .fblo-invalid-entry { - margin-right: 5px; - color: $brand-danger; - } - - .entry-checkbox { - //margin-right: 15px; - //margin-left: auto; - - // This shouldn't be necessary. But hey ho lets go. - &.disabled { - display: none; - } - - label { - padding: 0; - - input[type="checkbox"] { - margin-left: initial; - position: initial; - } - - } - } - - &.collection-tab { - padding: 0px 0px 0px 15px; - } - - &.dragging { - opacity: 0; - } - - &.locked { - background-color: $brand-primary; - } - - .drag-handle-icon.undraggable { - visibility: hidden; - //fill: red; - } - - &.external { - - .load-order-unmanaged-banner { - - text-align: center; - bottom: 0; - - display: flex; - background: transparent; - color: gray; - border-radius: 16px; - align-items: center; - //position: initial; - border: 1px $gray-light solid; - padding: 2px; - margin-right: 8px; - } - - .external-caution-logo { - margin-right: 5px; - margin-left: 5px; - } - - .external-text-area { - margin-right: 5px; - } - } - - >.layout-container { - align-items: center; - } - } - - #fb-lo-errorbox { - - background-color: $brand-bg; - width: 100%; - overflow: auto; - border: none; - - p { - padding: 4px 0 0 8px; - } - - &.valid { - p { - color: $brand-success; - } - } - - &.invalid { - p { - color: $brand-danger; - } - } - } - - - - #loadorderinfo { - - padding: 0 12px; - border: 0; - - display: block; - - height: 100%; - overflow: auto; - - > .layout-container { - gap: 8px; - display: flex; - flex-direction: column; - - > * { - padding: 12px; - border: 1px gray solid; - border-radius: 4px; - - > .layout-flex-inner { - display: flex; - flex-direction: column; - gap: 8px; - - // fblo component is adding a dirty p above what the extension can add - > p { - display: flex; - flex-direction: column; - gap: 8px; - margin: 0; - } - } - - p { - margin: 0; - } - - .alert { - display: flex; - flex-direction: column; - gap: 8px; - border-radius: 2px; - - } - - h1, h2, h3, h4, h5, h6 { - margin: 0; - } - - } - - // top box (information) - - > :first-child { - //background-color: #acff2f60; - flex: 1 1 0; // default - min-height: 200px; // don't think we need this as max-height on next child is 50% - } - - // bottom box (validation console) - - > :last-child { - //background-color: #892be26b; - flex: unset; // shrinks to whatever space is needed, preferably none - max-height: 50%; // don't ever take up more than 50% of height - - background-color: $brand-bg; - } - - - } - } - - #mod-info { - font-size: 1.2em; - } - - #mod-img { - width: 150px; - height: 90px; - margin: 5px 10px 5px 5px; - border: 1px solid $brand-secondary; - } -} - -#collection-edit-loadorder-edit-info-container { - border: 2px solid $brand-info; - box-sizing: border-box; - border-radius: 10px; - padding: 1em; - margin-bottom: 15px; - height: auto; - - .loadorder-edit-info-icon { - color: $brand-info; - size: 3em; - margin-right: 20px; - } - - .collection-edit-loadorder-edit-info { - letter-spacing: 0.25px; - a { - color: $link-color; - } - } +#collections-load-order-list, +#page-file-based-loadorder, +#page-generic-loadorder { + + .layout-flex { + flex: 1 1 0; + position: relative; + overflow: auto; + } + + .layout-container { + gap: 8px; + } + + + .file-based-load-order-container { + gap: 8px; + } + + .file-based-load-order-list { + + .list-group { + display: flex; + align-items: stretch; + flex-direction: column; + gap: 4px; + margin: 0; + padding: 0 8px 0 0; // padding between scrollbar and list items + } + } + + .load-order-entry { + + display: flex; + flex-direction: row; + align-items: center; + background-color: $brand-bg; + gap: 8px; + + height: 100%; + overflow: auto; + + margin: 0; + border: 1px gray solid; + border-radius: 4px; + padding: 0 12px 0 12px; + + h1:has(+ p) { + margin-bottom: 0; + } + + .drag-handle-icon { + fill: $brand-menu; + } + + .load-order-index { + //padding: 2px 2px; + // margin-right: 15px; + min-width: 24px; + } + + .load-order-name-container { + display: flex; + align-items: center; + gap: 8px; + } + + .load-order-name { + flex: 1 1 0; + } + + .locked-entry-logo { + margin: 0; + } + + .fblo-invalid-entry { + margin-right: 5px; + color: $brand-danger; + } + + .entry-checkbox { + //margin-right: 15px; + //margin-left: auto; + + // This shouldn't be necessary. But hey ho lets go. + &.disabled { + display: none; + } + + label { + padding: 0; + + input[type="checkbox"] { + margin-left: initial; + position: initial; + } + + } + } + + &.collection-tab { + padding: 0px 0px 0px 15px; + } + + &.dragging { + opacity: 0; + } + + &.locked { + background-color: $brand-primary; + } + + .drag-handle-icon:has(~.locked-entry-logo) { + visibility: hidden; + } + + &.external { + + .load-order-unmanaged-banner { + + text-align: center; + bottom: 0; + + display: flex; + background: transparent; + color: gray; + border-radius: 16px; + align-items: center; + //position: initial; + border: 1px $gray-light solid; + padding: 2px; + margin-right: 8px; + } + + .external-caution-logo { + margin-right: 5px; + margin-left: 5px; + } + + .external-text-area { + margin-right: 5px; + } + } + + >.layout-container { + align-items: center; + } + } + + #fb-lo-errorbox { + + background-color: $brand-bg; + width: 100%; + overflow: auto; + border: none; + + p { + padding: 4px 0 0 8px; + } + + &.valid { + p { + color: $brand-success; + } + } + + &.invalid { + p { + color: $brand-danger; + } + } + } + + + + #loadorderinfo { + + padding: 0 12px; + border: 0; + + display: block; + + height: 100%; + overflow: auto; + + > .layout-container { + gap: 8px; + display: flex; + flex-direction: column; + + > * { + padding: 12px; + border: 1px gray solid; + border-radius: 4px; + + > .layout-flex-inner { + display: flex; + flex-direction: column; + gap: 8px; + + // fblo component is adding a dirty p above what the extension can add + > p { + display: flex; + flex-direction: column; + gap: 8px; + margin: 0; + } + } + + p { + margin: 0; + } + + .alert { + display: flex; + flex-direction: column; + gap: 8px; + border-radius: 2px; + + } + + h1, h2, h3, h4, h5, h6 { + margin: 0; + } + + } + + // top box (information) + + > :first-child { + //background-color: #acff2f60; + flex: 1 1 0; // default + min-height: 200px; // don't think we need this as max-height on next child is 50% + } + + // bottom box (validation console) + + > :last-child { + //background-color: #892be26b; + flex: unset; // shrinks to whatever space is needed, preferably none + max-height: 50%; // don't ever take up more than 50% of height + + background-color: $brand-bg; + } + + + } + } + + #mod-info { + font-size: 1.2em; + } + + #mod-img { + width: 150px; + height: 90px; + margin: 5px 10px 5px 5px; + border: 1px solid $brand-secondary; + } +} + +#collection-edit-loadorder-edit-info-container { + border: 2px solid $brand-info; + box-sizing: border-box; + border-radius: 10px; + padding: 1em; + margin-bottom: 15px; + height: auto; + + .loadorder-edit-info-icon { + color: $brand-info; + size: 3em; + margin-right: 20px; + } + + .collection-edit-loadorder-edit-info { + letter-spacing: 0.25px; + a { + color: $link-color; + } + } } \ No newline at end of file