UBER-573,-574: updated button styles, fixed ListView (#3484)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2023-07-07 08:33:55 +03:00 committed by GitHub
parent e7b6522e80
commit a29a6b1416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 133 additions and 141 deletions

View File

@ -342,7 +342,7 @@ export function createModel (builder: Builder): void {
size: 'small', size: 'small',
kind: 'list' kind: 'list'
}, },
displayProps: { optional: true } displayProps: { compression: true }
}, },
{ key: 'modifiedOn', displayProps: { key: 'modified', fixed: 'right', dividerBefore: true } }, { key: 'modifiedOn', displayProps: { key: 'modified', fixed: 'right', dividerBefore: true } },
{ {

View File

@ -723,7 +723,7 @@ export function createModel (builder: Builder): void {
size: 'small', size: 'small',
kind: 'list' kind: 'list'
}, },
displayProps: { optional: true } displayProps: { compression: true }
}, },
{ key: 'modifiedOn', displayProps: { key: 'modified', fixed: 'right', dividerBefore: true } }, { key: 'modifiedOn', displayProps: { key: 'modified', fixed: 'right', dividerBefore: true } },
{ {

View File

@ -486,7 +486,7 @@ export function createModel (builder: Builder): void {
{ {
key: 'labels', key: 'labels',
presenter: tags.component.LabelsPresenter, presenter: tags.component.LabelsPresenter,
displayProps: { optional: true }, displayProps: { compression: true },
props: { kind: 'list', full: false } props: { kind: 'list', full: false }
}, },
{ {
@ -501,8 +501,7 @@ export function createModel (builder: Builder): void {
displayProps: { displayProps: {
key: 'milestone', key: 'milestone',
excludeByKey: 'milestone', excludeByKey: 'milestone',
compression: true, compression: true
optional: true
} }
}, },
{ {
@ -517,15 +516,14 @@ export function createModel (builder: Builder): void {
displayProps: { displayProps: {
key: 'component', key: 'component',
excludeByKey: 'component', excludeByKey: 'component',
compression: true, compression: true
optional: true
} }
}, },
{ {
key: '', key: '',
label: tracker.string.DueDate, label: tracker.string.DueDate,
presenter: tracker.component.DueDatePresenter, presenter: tracker.component.DueDatePresenter,
displayProps: { key: 'dueDate', optional: true }, displayProps: { key: 'dueDate', compression: true },
props: { kind: 'list' } props: { kind: 'list' }
}, },
{ {
@ -533,7 +531,7 @@ export function createModel (builder: Builder): void {
label: tracker.string.Estimation, label: tracker.string.Estimation,
presenter: tracker.component.EstimationEditor, presenter: tracker.component.EstimationEditor,
props: { kind: 'list', size: 'small' }, props: { kind: 'list', size: 'small' },
displayProps: { key: 'estimation', fixed: 'left', dividerBefore: true } displayProps: { key: 'estimation', fixed: 'left', dividerBefore: true, optional: true }
}, },
{ {
key: 'modifiedOn', key: 'modifiedOn',
@ -633,21 +631,21 @@ export function createModel (builder: Builder): void {
}, },
displayProps: { displayProps: {
excludeByKey: 'milestone', excludeByKey: 'milestone',
compression: true, compression: true
optional: true
} }
}, },
{ {
key: '', key: '',
label: tracker.string.DueDate, label: tracker.string.DueDate,
presenter: tracker.component.DueDatePresenter, presenter: tracker.component.DueDatePresenter,
displayProps: { key: 'dueDate', optional: true }, displayProps: { key: 'dueDate', compression: true },
props: { kind: 'list', size: 'small' } props: { kind: 'list', size: 'small' }
}, },
{ {
key: '', key: '',
label: tracker.string.Estimation, label: tracker.string.Estimation,
presenter: tracker.component.EstimationEditor, presenter: tracker.component.EstimationEditor,
displayProps: { optional: true },
props: { kind: 'list', size: 'small' } props: { kind: 'list', size: 'small' }
}, },
{ {
@ -703,7 +701,7 @@ export function createModel (builder: Builder): void {
size: 'small', size: 'small',
shouldShowPlaceholder: false shouldShowPlaceholder: false
}, },
displayProps: { key: 'component', compression: true, optional: true } displayProps: { key: 'component', compression: true }
}, },
{ {
key: '', key: '',
@ -714,7 +712,7 @@ export function createModel (builder: Builder): void {
size: 'small', size: 'small',
shouldShowPlaceholder: false shouldShowPlaceholder: false
}, },
displayProps: { key: 'milestone', compression: true, optional: true } displayProps: { key: 'milestone', compression: true }
}, },
{ {
key: '', key: '',
@ -724,7 +722,7 @@ export function createModel (builder: Builder): void {
kind: 'list', kind: 'list',
size: 'small' size: 'small'
}, },
displayProps: { key: 'estimation', optional: true } displayProps: { key: 'estimation', compression: true }
}, },
{ key: '', displayProps: { grow: true } }, { key: '', displayProps: { grow: true } },
{ {

View File

@ -50,7 +50,7 @@
} }
&:focus { &:focus {
color: var(--theme-caption-color); color: var(--theme-caption-color);
box-shadow: 0 0 0 2px var(--accented-button-focused-border); box-shadow: 0 0 0 2px var(--accented-button-outline);
} }
&.selected { &.selected {
background-color: var(--theme-button-pressed); background-color: var(--theme-button-pressed);

View File

@ -16,27 +16,27 @@
/* Common Colors */ /* Common Colors */
* { * {
--accented-button-color: #fff; --accented-button-color: #fff;
--accented-button-content-color: rgba(255, 255, 255, .8);
--accented-button-border: rgba(255, 255, 255, .09); --accented-button-border: rgba(255, 255, 255, .09);
--accented-button-focused-border: #fff;
--accented-button-outline: #5190EC; --accented-button-outline: #5190EC;
--accented-button-transparent: rgba(43, 81, 144, 0.2); --accented-button-transparent: rgba(43, 81, 144, 0.2);
--accented-button-default: #2B5190; --accented-button-default: #2B5190;
--accented-button-hovered: #325FA9; --accented-button-hovered: #325FA9;
--accented-button-pressed: #284B86; --accented-button-pressed: #284B86;
--accented-button-focused: #284B86; --accented-button-focused: #2B5190;
--brand-button-default: #4169E1; --brand-button-default: #4169E1;
--brand-button-hovered: #587BE5; --brand-button-hovered: #587BE5;
--brand-button-pressed: #2C58DE; --brand-button-pressed: #2C58DE;
--brand-button-focused: #2C58DE; --brand-button-focused: #4169E1;
--positive-button-default: #26A869; --positive-button-default: #26A869;
--positive-button-hovered: #2BBB75; --positive-button-hovered: #2BBB75;
--positive-button-pressed: #21915B; --positive-button-pressed: #21915B;
--positive-button-focused: #21915B; --positive-button-focused: #26A869;
--negative-button-default: #CA4242; --negative-button-default: #CA4242;
--negative-button-hovered: #D05858; --negative-button-hovered: #D05858;
--negative-button-pressed: #BF3636; --negative-button-pressed: #BF3636;
--negative-button-focused: #BF3636; --negative-button-focused: #CA4242;
--white-color: #fff; --white-color: #fff;
--duotone-color: rgba(126, 134, 158, .25); --duotone-color: rgba(126, 134, 158, .25);
@ -66,21 +66,21 @@
/* Dark Theme */ /* Dark Theme */
.theme-dark { .theme-dark {
--accented-button-disabled: #12213B; --accented-button-disabled: rgba(255, 255, 255, .12);
--accented-button-disabled-color: #5E88CF; --accented-button-disabled-color: rgba(255, 255, 255, .4);
--brand-button-disabled: #111F4B; --brand-button-disabled: rgba(255, 255, 255, .12);
--brand-button-disabled-color: #6585E7; --brand-button-disabled-color: rgba(255, 255, 255, .4);
--positive-button-disabled: #092518; --positive-button-disabled: rgba(38, 168, 105, .2);
--positive-button-disabled-color: #25A265; --positive-button-disabled-color: rgba(38, 168, 105, .6);
--negative-button-disabled: #330F0F; --negative-button-disabled: rgba(202, 66, 66, .2);
--negative-button-disabled-color: #D06262; --negative-button-disabled-color: rgba(202, 66, 66, .6);
--theme-button-default: rgba(255, 255, 255, .02); --theme-button-default: rgba(255, 255, 255, .02);
--theme-button-hovered: rgba(255, 255, 255, .04); --theme-button-hovered: rgba(255, 255, 255, .04);
--theme-button-pressed: rgba(255, 255, 255, .08); --theme-button-pressed: rgba(255, 255, 255, .08);
--theme-button-focused: rgba(255, 255, 255, .04); --theme-button-focused: rgba(255, 255, 255, .04);
--theme-button-focused-border: rgba(255, 255, 255, .09); --theme-button-focused-border: rgba(255, 255, 255, .09);
--theme-button-disabled: rgba(255, 255, 255, .08); --theme-button-disabled: transparent;
--theme-button-border: rgba(255, 255, 255, .09); --theme-button-border: rgba(255, 255, 255, .09);
--theme-button-contrast-color: #000; --theme-button-contrast-color: #000;
@ -260,14 +260,14 @@
/* Light Theme */ /* Light Theme */
.theme-light { .theme-light {
--accented-button-disabled: #E0E8F6; --accented-button-disabled: rgba(0, 0, 0, .12);
--accented-button-disabled-color: #284B86; --accented-button-disabled-color: rgba(0, 0, 0, .4);
--brand-button-disabled: #DCE3F9; --brand-button-disabled: rgba(0, 0, 0, .12);
--brand-button-disabled-color: #2C58DE; --brand-button-disabled-color: rgba(0, 0, 0, .4);
--positive-button-disabled: #DEF7EB; --positive-button-disabled: rgba(38, 168, 105, .2);
--positive-button-disabled-color: #1A7046; --positive-button-disabled-color: rgba(33, 145, 91, .6);
--negative-button-disabled: #F6E0E0; --negative-button-disabled: rgba(202, 66, 66, .2);
--negative-button-disabled-color: #962C2C; --negative-button-disabled-color: rgba(202, 66, 66, .6);
--theme-button-default: rgba(0, 0, 0, .02); --theme-button-default: rgba(0, 0, 0, .02);
--theme-button-hovered: rgba(0, 0, 0, .04); --theme-button-hovered: rgba(0, 0, 0, .04);

View File

@ -185,16 +185,24 @@
} }
&:not(.no-focus):focus { box-shadow: none; } &:not(.no-focus):focus { box-shadow: none; }
} }
&.accented, &.brand, &.positive, &.negative {
&:hover, &:active, &:focus {
color: var(--accented-button-color);
.btn-icon { color: var(--accented-button-color); }
}
}
&.regular, &.ghost {
&:hover, &:active, &:focus { color: var(--theme-caption-color); }
}
&.accented, &.accented,
&.brand, &.brand,
&.positive, &.positive,
&.negative { &.negative {
padding: 0 1.5rem; padding: 0 1.5rem;
color: var(--accented-button-color); color: var(--accented-button-content-color);
border-color: var(--accented-button-border); border-color: var(--accented-button-border);
.btn-icon { color: var(--accented-button-color); } .btn-icon { color: var(--accented-button-content-color); }
&:focus { border-color: var(--accented-button-focused-border); }
} }
&.accented { &.accented {
background-color: var(--accented-button-default); background-color: var(--accented-button-default);
@ -272,7 +280,7 @@
} }
&:disabled { &:disabled {
color: var(--theme-trans-color); color: var(--theme-darker-color);
border-color: transparent; border-color: transparent;
cursor: not-allowed; cursor: not-allowed;

View File

@ -686,7 +686,6 @@
border-color: transparent; border-color: transparent;
} }
&:focus { &:focus {
border-color: var(--accented-button-focused-border);
box-shadow: 0 0 0 3px var(--accented-button-outline); box-shadow: 0 0 0 3px var(--accented-button-outline);
& > .icon { color: var(--caption-color); } & > .icon { color: var(--caption-color); }
} }
@ -894,7 +893,7 @@
.fix-margin { margin-left: .875rem; } .fix-margin { margin-left: .875rem; }
.name { margin-left: .375rem; } .name { margin-left: .375rem; }
.optional-bar { .compression-bar {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
@ -913,7 +912,7 @@
width: max-content; width: max-content;
} }
& > *:not(:first-child) { margin-left: .25rem; } & > *:not(:first-child) { margin-left: .25rem; }
& > * > * { min-width: fit-content; } & > * > *:not(.only-icon) { min-width: fit-content; }
} }
} }
// Labels on the ListView // Labels on the ListView
@ -956,7 +955,7 @@
.kanban-container .card-container .card-labels .label { font-size: .8125rem !important; } .kanban-container .card-container .card-labels .label { font-size: .8125rem !important; }
/* ListView & Kanban */ /* ListView & Kanban */
.list-container .optional-bar .label-wrapper, .list-container .compression-bar .label-wrapper,
.kanban-container .card-container .card-labels .label-wrapper { .kanban-container .card-container .card-labels .label-wrapper {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -60,6 +60,7 @@
label === undefined && label === undefined &&
$$slots.content === undefined && $$slots.content === undefined &&
(icon !== undefined || iconRight !== undefined || $$slots.icon || $$slots.iconRight) (icon !== undefined || iconRight !== undefined || $$slots.icon || $$slots.iconRight)
$: primary = ['accented', 'brand', 'positive', 'negative'].some((p) => p === kind)
onMount(() => { onMount(() => {
if (focus && input) { if (focus && input) {
@ -129,7 +130,11 @@
</div> </div>
{/if} {/if}
{#if loading} {#if loading}
<div class="btn-icon pointer-events-none caption-color spinner" class:resetIconSize> <div
class="btn-icon pointer-events-none spinner"
class:resetIconSize
style:color={primary ? 'var(--accented-button-color)' : 'var(--theme-caption-color)'}
>
<Spinner size={iconSize === 'inline' ? 'inline' : 'small'} /> <Spinner size={iconSize === 'inline' ? 'inline' : 'small'} />
</div> </div>
{/if} {/if}

View File

@ -35,18 +35,6 @@
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<DocNavLink {object} {disabled} inline noUnderline shrink={0}> <DocNavLink {object} {disabled} inline noUnderline shrink={0}>
{#if kind === 'list'} {#if kind === 'list'}
{#if compactMode}
<div
use:tooltip={{
component: AttachmentPopup,
props: popupProps
}}
class="sm-tool-icon"
>
<div class="icon halfcontent"><IconAttachment {size} /></div>
{#if showCounter}{value ?? 0}{/if}
</div>
{:else}
<Button <Button
{kind} {kind}
{size} {size}
@ -56,11 +44,10 @@
}} }}
> >
<div slot="icon"><IconAttachment {size} /></div> <div slot="icon"><IconAttachment {size} /></div>
<div slot="content" style:margin-left={showCounter ? '.375rem' : '0'}> <div slot="content" style:margin-left={showCounter && !compactMode ? '.375rem' : '0'}>
{#if showCounter}{value ?? 0}{/if} {#if showCounter && !compactMode}{value ?? 0}{/if}
</div> </div>
</Button> </Button>
{/if}
{:else} {:else}
<div <div
use:tooltip={{ use:tooltip={{

View File

@ -32,18 +32,6 @@
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<DocNavLink {object} inline noUnderline={true} shrink={0}> <DocNavLink {object} inline noUnderline={true} shrink={0}>
{#if kind === 'list'} {#if kind === 'list'}
{#if compactMode}
<div
use:tooltip={{
component: CommentPopup,
props: { objectId: object._id, object, withInput }
}}
class="sm-tool-icon"
>
<div class="icon halfcontent"><IconThread {size} /></div>
{#if showCounter}{value ?? 0}{/if}
</div>
{:else}
<Button <Button
{kind} {kind}
{size} {size}
@ -53,11 +41,10 @@
}} }}
> >
<div slot="icon"><IconThread {size} /></div> <div slot="icon"><IconThread {size} /></div>
<div slot="content" style:margin-left={showCounter ? '.375rem' : '0'}> <div slot="content" style:margin-left={showCounter && !compactMode ? '.375rem' : '0'}>
{#if showCounter}{value ?? 0}{/if} {#if showCounter && !compactMode}{value ?? 0}{/if}
</div> </div>
</Button> </Button>
{/if}
{:else} {:else}
<div <div
use:tooltip={{ use:tooltip={{

View File

@ -574,7 +574,6 @@
transition: border-color 0.1s var(--timing-main), box-shadow 0.1s var(--timing-main); transition: border-color 0.1s var(--timing-main), box-shadow 0.1s var(--timing-main);
&:focus-within { &:focus-within {
border-color: var(--accented-button-focused-border);
box-shadow: 0 0 0 3px var(--accented-button-outline); box-shadow: 0 0 0 3px var(--accented-button-outline);
} }
} }

View File

@ -116,8 +116,7 @@
} }
&:focus { &:focus {
border: 1px solid var(--accented-button-focused-border); box-shadow: 0 0 0 2px var(--accented-button-outline);
box-shadow: 0 0 0 3px var(--accented-button-outline);
} }
} }

View File

@ -60,8 +60,7 @@
color: var(--caption-color); color: var(--caption-color);
} }
&:focus { &:focus {
border: 1px solid var(--accented-button-focused-border); box-shadow: 0 0 0 2px var(--accented-button-outline);
box-shadow: 0 0 0 3px var(--accented-button-outline);
.icon-container { .icon-container {
color: var(--caption-color); color: var(--caption-color);
} }
@ -70,7 +69,7 @@
&.selected { &.selected {
background-color: var(--menu-bg-select); background-color: var(--menu-bg-select);
.icon-container { .icon-container {
color: var(--caption-color); color: var(--theme-caption-color);
} }
} }
} }

View File

@ -54,16 +54,15 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
border-color: var(--accented-button-focused-border); box-shadow: 0 0 0 2px var(--accented-button-outline);
box-shadow: 0 0 0 3px var(--accented-button-outline);
} }
&.selected { &.selected {
border-color: var(--caption-color); border-color: var(--caption-color);
box-shadow: 0 0 0 3px var(--trans-content-20); box-shadow: 0 0 0 2px var(--trans-content-20);
&:hover { &:hover {
border-color: var(--system-error-color); border-color: var(--system-error-color);
box-shadow: 0 0 0 3px var(--trans-content-20); box-shadow: 0 0 0 2px var(--trans-content-20);
} }
} }
} }

View File

@ -109,7 +109,7 @@
}} }}
on:click={() => dispatch('collapse')} on:click={() => dispatch('collapse')}
> >
<div class="flex-row-center clear-mins flex-grow"> <div class="flex-row-center flex-grow" style:color={headerComponent ? headerTextColor : 'inherit'}>
{#if level === 0} {#if level === 0}
<div class="chevron"><IconCollapseArrow size={'small'} /></div> <div class="chevron"><IconCollapseArrow size={'small'} /></div>
{/if} {/if}
@ -118,7 +118,6 @@
<Label label={view.string.NoGrouping} /> <Label label={view.string.NoGrouping} />
</span> </span>
{:else if headerComponent} {:else if headerComponent}
<span class="clear-mins" style:color={headerTextColor}>
<svelte:component <svelte:component
this={headerComponent.presenter} this={headerComponent.presenter}
value={category} value={category}
@ -131,7 +130,6 @@
accentColor = evt.detail accentColor = evt.detail
}} }}
/> />
</span>
{/if} {/if}
{#if selected.length > 0} {#if selected.length > 0}

View File

@ -112,25 +112,24 @@
/> />
</div> </div>
</div> </div>
{#each model.filter((p) => !(p.displayProps?.optional === true || p.displayProps?.suffix === true)) as attributeModel, i} {#each model.filter((p) => !(p.displayProps?.optional === true || p.displayProps?.compression === true || p.displayProps?.suffix === true)) as attributeModel, i}
{@const displayProps = attributeModel.displayProps} {@const displayProps = attributeModel.displayProps}
{#if !groupByKey || displayProps?.excludeByKey !== groupByKey} {#if !groupByKey || displayProps?.excludeByKey !== groupByKey}
{#if displayProps?.grow} {#if displayProps?.grow}
{#if !compactMode}
{#each model.filter((p) => p.displayProps?.suffix === true) as attrModel} {#each model.filter((p) => p.displayProps?.suffix === true) as attrModel}
<ListPresenter <ListPresenter
{docObject} {docObject}
attributeModel={attrModel} attributeModel={attrModel}
{props} {props}
{compactMode}
value={getObjectValue(attrModel.key, docObject)} value={getObjectValue(attrModel.key, docObject)}
onChange={getOnChange(docObject, attrModel)} onChange={getOnChange(docObject, attrModel)}
/> />
{/each} {/each}
{/if}
<GrowPresenter /> <GrowPresenter />
{#if !compactMode} {#if !compactMode}
<div class="optional-bar"> <div class="compression-bar">
{#each model.filter((p) => p.displayProps?.optional === true) as attrModel} {#each model.filter((p) => p.displayProps?.compression === true) as attrModel}
<ListPresenter <ListPresenter
{docObject} {docObject}
attributeModel={attrModel} attributeModel={attrModel}
@ -140,16 +139,13 @@
/> />
{/each} {/each}
</div> </div>
{:else} {#each model.filter((p) => p.displayProps?.optional === true) as attrModel}
<GrowPresenter />
{#each model.filter((p) => p.displayProps?.suffix === true) as attrModel}
<ListPresenter <ListPresenter
{docObject} {docObject}
attributeModel={attrModel} attributeModel={attrModel}
{props} {props}
value={getObjectValue(attrModel.key, docObject)} value={getObjectValue(attrModel.key, docObject)}
onChange={getOnChange(docObject, attrModel)} onChange={getOnChange(docObject, attrModel)}
compactMode
/> />
{/each} {/each}
{/if} {/if}
@ -180,7 +176,8 @@
<IconCircles /> <IconCircles />
</div> </div>
<div class="scroll-box gap-2"> <div class="scroll-box gap-2">
{#each model.filter((m) => m.displayProps?.optional) as attributeModel, j} <div class="compression-bar">
{#each model.filter((m) => m.displayProps?.compression) as attributeModel, j}
{@const displayProps = attributeModel.displayProps} {@const displayProps = attributeModel.displayProps}
{@const value = getObjectValue(attributeModel.key, docObject)} {@const value = getObjectValue(attributeModel.key, docObject)}
{#if displayProps?.excludeByKey !== groupByKey && value !== undefined} {#if displayProps?.excludeByKey !== groupByKey && value !== undefined}
@ -195,6 +192,23 @@
{/if} {/if}
{/each} {/each}
</div> </div>
{#each model.filter((m) => m.displayProps?.optional) as attributeModel, j}
{#if j === 0}
<GrowPresenter />
{/if}
{@const displayProps = attributeModel.displayProps}
{@const value = getObjectValue(attributeModel.key, docObject)}
{#if displayProps?.excludeByKey !== groupByKey && value !== undefined}
<ListPresenter
{docObject}
{attributeModel}
{props}
value={getObjectValue(attributeModel.key, docObject)}
onChange={getOnChange(docObject, attributeModel)}
/>
{/if}
{/each}
</div>
</div> </div>
{/if} {/if}
</div> </div>