[IMP] web: improve ImageField style

This commit improves the style of the image widget
to use more approriate icons for edition/deletion.
Before this commit, a rectangle was covering the
entire image to highlight those buttons. Now, only
those are visible and highlighted on desktop when
hovered, while being always visible on mobile.

This will improve the visibility of this field
with views being always-edit.

task #2860958

closes odoo/odoo#97208

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
luvi
2022-08-04 13:54:24 +02:00
parent 6b41d20815
commit 9c4590f6fb
5 changed files with 45 additions and 73 deletions
@@ -1,9 +1,10 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { isMobileOS } from "@web/core/browser/feature_detection";
import { _lt } from "@web/core/l10n/translation";
import { useService } from "@web/core/utils/hooks";
import { url } from "@web/core/utils/urls";
import { _lt } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { FileUploader } from "../file_handler";
import { standardFieldProps } from "../standard_field_props";
@@ -24,6 +25,7 @@ function isBinarySize(value) {
export class ImageField extends Component {
setup() {
this.notification = useService("notification");
this.isMobile = isMobileOS();
this.state = useState({
isValid: true,
});
@@ -1,48 +1,26 @@
.o_field_image {
display: inline-block;
position: relative;
.o_form_image_controls {
@include o-position-absolute(0, 0);
width: 100%;
color: white;
background-color: $o-brand-primary;
opacity: 0;
button {
transition: opacity ease 400ms;
min-width: 35px;
button.fa {
border: none;
background-color: transparent;
outline: 0 !important;
}
.fa {
padding: 4px;
margin: 5px;
cursor: pointer;
}
width: 26px;
height: 26px;
opacity: 0;
background: $white;
}
@include media-breakpoint-down(sm, $o-extra-grid-breakpoints) {
.o_form_image_controls {
position: initial;
opacity: 1;
.fa {
width: 50%;
padding: 6px;
margin: 0px;
text-align: center;
&.o_select_file_button{
background: $o-brand-primary;
}
&.o_clear_file_button{
background: map-get($theme-colors, 'danger');
}
}
}
&:hover button {
@include o-hover-opacity(0.6, 0.9);
}
&:hover .o_form_image_controls {
opacity: 0.8;
.o_mobile_controls {
button {
@include o-hover-opacity(0.6, 0.9);
width: 30px;
height: 30px;
padding: 6px !important;
}
}
&.o_field_invalid img {
@@ -2,37 +2,34 @@
<templates xml:space="preserve">
<t t-name="web.ImageField" owl="1">
<t t-if="!props.readonly">
<div class="position-relative" aria-atomic="true" t-att-style="sizeStyle">
<div class="o_form_image_controls">
<FileUploader
acceptedFileExtensions="props.acceptedFileExtensions"
onUploaded.bind="onFileUploaded"
type="'image'"
>
<t t-set-slot="toggler">
<button
class="fa fa-pencil fa-lg float-start o_select_file_button"
data-tooltip="Edit"
aria-label="Edit"
/>
</t>
<div t-attf-class="position-absolute w-100 bottom-0 {{isMobile ? 'o_mobile_controls' : ''}}" aria-atomic="true" t-att-style="sizeStyle">
<t t-if="!props.readonly">
<FileUploader
acceptedFileExtensions="props.acceptedFileExtensions"
onUploaded.bind="onFileUploaded"
type="'image'"
>
<t t-set-slot="toggler">
<button
t-if="props.value and state.isValid"
class="fa fa-trash-o fa-lg float-end o_clear_file_button"
data-tooltip="Clear"
aria-label="Clear"
t-on-click="onFileRemove"
class="position-absolute bottom-0 start-0 border-0 rounded-circle m-1 p-1 fa fa-pencil fa-lg o_select_file_button"
data-tooltip="Edit"
aria-label="Edit"
/>
</FileUploader>
</div>
</div>
</t>
</t>
<button
t-if="props.value and state.isValid"
class="position-absolute bottom-0 end-0 border-0 rounded-circle m-1 p-1 fa fa-trash-o fa-lg o_clear_file_button"
data-tooltip="Clear"
aria-label="Clear"
t-on-click="onFileRemove"
/>
</FileUploader>
</t>
</div>
<img
class="img img-fluid"
alt="Binary file"
t-att-src="getUrl(props.previewImage or props.name)"
t-att-border="props.readonly ? 0 : 1"
t-att-name="props.name"
t-att-height="props.height"
t-att-width="props.width"
@@ -125,12 +125,12 @@ QUnit.module("Fields", (hooks) => {
assert.containsOnce(
target,
".o_form_image_controls .o_select_file_button",
".o_field_image .o_select_file_button",
"the image can be edited"
);
assert.containsOnce(
target,
".o_form_image_controls .o_clear_file_button",
".o_field_image .o_clear_file_button",
"the image can be deleted"
);
assert.strictEqual(
@@ -203,12 +203,12 @@ QUnit.module("Fields", (hooks) => {
assert.containsOnce(
target,
".o_form_image_controls .o_select_file_button",
".o_field_image .o_select_file_button",
"the image can be edited"
);
assert.containsNone(
target,
".o_form_image_controls .o_clear_file_button",
".o_field_image .o_clear_file_button",
"the image cannot be deleted as it has not been uploaded"
);
}
@@ -52,11 +52,6 @@
height: 200px;
width: auto;
}
.o_form_image_controls {
@include o-hover-opacity(0.7, 1);
padding: 2%;
}
}
}
.o_video_container {