diff --git a/examples/jsm/inspector/tabs/Timeline.js b/examples/jsm/inspector/tabs/Timeline.js index b90608a0c200da..e110f5491c7134 100644 --- a/examples/jsm/inspector/tabs/Timeline.js +++ b/examples/jsm/inspector/tabs/Timeline.js @@ -224,6 +224,7 @@ class Timeline extends Tab { this.graphSlider.style.margin = '0 10px'; this.graphSlider.style.position = 'relative'; this.graphSlider.style.cursor = 'crosshair'; + this.graphSlider.style.touchAction = 'none'; graphContainer.appendChild( this.graphSlider ); @@ -277,7 +278,7 @@ class Timeline extends Tab { this.graphSlider.tabIndex = 0; this.graphSlider.style.outline = 'none'; - // Mouse interactivity on the graph + // Pointer interactivity on the graph let isDragging = false; const updatePlayheadFromEvent = ( e ) => { @@ -326,7 +327,7 @@ class Timeline extends Tab { }; - this.graphSlider.addEventListener( 'mousedown', ( e ) => { + this.graphSlider.addEventListener( 'pointerdown', ( e ) => { if ( this.isRecording ) return; @@ -337,7 +338,7 @@ class Timeline extends Tab { } ); - this.graphSlider.addEventListener( 'mouseenter', () => { + this.graphSlider.addEventListener( 'pointerenter', () => { if ( this.frames.length > 0 && ! this.isRecording ) { @@ -347,13 +348,13 @@ class Timeline extends Tab { } ); - this.graphSlider.addEventListener( 'mouseleave', () => { + this.graphSlider.addEventListener( 'pointerleave', () => { this.hoverIndicator.style.display = 'none'; } ); - this.graphSlider.addEventListener( 'mousemove', ( e ) => { + this.graphSlider.addEventListener( 'pointermove', ( e ) => { if ( this.frames.length === 0 || this.isRecording ) return; @@ -437,7 +438,7 @@ class Timeline extends Tab { } ); - window.addEventListener( 'mousemove', ( e ) => { + window.addEventListener( 'pointermove', ( e ) => { if ( isDragging ) { @@ -472,7 +473,7 @@ class Timeline extends Tab { } ); - window.addEventListener( 'mouseup', () => { + window.addEventListener( 'pointerup', () => { isDragging = false; this.isManualScrubbing = false; diff --git a/examples/jsm/inspector/ui/Style.js b/examples/jsm/inspector/ui/Style.js index 6171b6cc73d89e..813eec7cb618f7 100644 --- a/examples/jsm/inspector/ui/Style.js +++ b/examples/jsm/inspector/ui/Style.js @@ -22,12 +22,14 @@ export class Style { --font-mono: 'Courier New', Courier, monospace; } + .profiler-panel, .profiler-toggle, .detached-tab-panel, .profiler-panel *, .profiler-toggle *, .detached-tab-panel * { text-transform: initial; line-height: normal; box-sizing: border-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-tap-highlight-color: transparent; } .profiler-toggle { @@ -238,6 +240,8 @@ export class Style { font-family: var(--font-family); font-size: 11px; width: 350px; + max-width: calc(100vw - 30px); + min-width: 170px; max-height: calc(100vh - 100px); overflow-y: auto; overflow-x: hidden; @@ -339,6 +343,19 @@ export class Style { padding: 4px; } + @media screen and (max-width: 340px) { + + .mini-panel-content .parameters { + min-width: 0 !important; + } + + .mini-panel-content .list-container.parameters .list-item-row, + .mini-panel-content .list-container.parameters .list-header { + grid-template-columns: minmax(0, .5fr) minmax(0, 1fr) !important; + } + + } + .mini-panel-content .list-container.parameters { padding: 2px 6px 0px 6px !important; } @@ -386,11 +403,18 @@ export class Style { position: relative; } - .info-icon:hover { + .info-icon.active { background-color: var(--color-accent); color: white; } + @media (hover: hover) { + .info-icon:hover { + background-color: var(--color-accent); + color: white; + } + } + .info-tooltip { position: fixed; transform: translate(-50%, -100%); @@ -403,7 +427,6 @@ export class Style { width: max-content; max-width: 250px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); - pointer-events: none; opacity: 0; visibility: hidden; transition: opacity 0.2s, visibility 0.2s; @@ -802,6 +825,7 @@ export class Style { .profiler-panel.position-right.no-tabs .profiler-tabs, .profiler-panel.position-left.no-tabs .profiler-tabs { display: none; + padding-left: 2px; } .profiler-panel.position-right.no-tabs .panel-resizer, @@ -896,6 +920,7 @@ export class Style { display: flex; cursor: grab; position: relative; + margin-left: 2px; } .profiler-tabs:active { @@ -944,14 +969,16 @@ export class Style { } .tab-btn.active::before { - content: '⋮⋮'; + content: ''; position: absolute; left: 2px; - top: calc(50% - .1rem); + top: 50%; transform: translateY(-50%); - color: var(--profiler-border); - font-size: 18px; - letter-spacing: -2px; + width: 8px; + height: 14px; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='8' height='14' viewBox='0 0 8 14' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='2' cy='3' r='1' fill='%234a4a5a'/%3E%3Ccircle cx='2' cy='7' r='1' fill='%234a4a5a'/%3E%3Ccircle cx='2' cy='11' r='1' fill='%234a4a5a'/%3E%3Ccircle cx='6' cy='3' r='1' fill='%234a4a5a'/%3E%3Ccircle cx='6' cy='7' r='1' fill='%234a4a5a'/%3E%3Ccircle cx='6' cy='11' r='1' fill='%234a4a5a'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: center; opacity: 0.6; } @@ -1500,6 +1527,30 @@ export class Style { margin-left: 2px; } + @media screen and (max-width: 340px) { + + .mini-panel-content .list-item-cell:first-child { + display: flex; + align-items: center; + min-width: 0; + overflow: hidden; + width: 100%; + } + + .mini-panel-content .list-item-cell:first-child .value { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1 1 0%; + min-width: 0; + } + + .mini-panel-content .list-item-cell:first-child .info-icon { + flex-shrink: 0; + } + + } + .mini-panel-content .custom-checkbox .checkmark { width: 12px; height: 12px; diff --git a/examples/jsm/inspector/ui/Values.js b/examples/jsm/inspector/ui/Values.js index ed0f5313d4e90d..f79a13b5315043 100644 --- a/examples/jsm/inspector/ui/Values.js +++ b/examples/jsm/inspector/ui/Values.js @@ -102,7 +102,9 @@ class ValueNumber extends Value { let isDragging = false; let startY, startValue; - this.input.addEventListener( 'mousedown', ( e ) => { + this.input.style.touchAction = 'none'; + + this.input.addEventListener( 'pointerdown', ( e ) => { isDragging = true; startY = e.clientY; @@ -111,7 +113,7 @@ class ValueNumber extends Value { } ); - document.addEventListener( 'mousemove', ( e ) => { + document.addEventListener( 'pointermove', ( e ) => { if ( isDragging ) { @@ -144,7 +146,7 @@ class ValueNumber extends Value { } ); - document.addEventListener( 'mouseup', () => { + document.addEventListener( 'pointerup', () => { if ( isDragging ) { diff --git a/examples/jsm/inspector/ui/utils.js b/examples/jsm/inspector/ui/utils.js index 7a21139e74351c..9a6eac22093cee 100644 --- a/examples/jsm/inspector/ui/utils.js +++ b/examples/jsm/inspector/ui/utils.js @@ -123,20 +123,54 @@ export function info( parentNode, text ) { }; - infoIcon.addEventListener( 'mouseenter', showTooltip ); - infoIcon.addEventListener( 'mouseleave', hideTooltip ); + let isClickedOpen = false; + + const onDocumentPointerDown = ( e ) => { + + if ( ! infoIcon.contains( e.target ) ) { + + isClickedOpen = false; + infoIcon.classList.remove( 'active' ); + hideTooltip(); + document.removeEventListener( 'pointerdown', onDocumentPointerDown ); + + } + + }; + + infoIcon.addEventListener( 'pointerenter', () => { + + showTooltip(); + + } ); + + infoIcon.addEventListener( 'pointerleave', () => { + + if ( ! isClickedOpen ) { + + hideTooltip(); + + } + + } ); + infoIcon.addEventListener( 'click', ( e ) => { e.stopPropagation(); - const container = infoIcon.closest( '.three-inspector' ) || document.body; - const tooltip = container.querySelector( '.three-inspector-info-tooltip' ); - if ( tooltip && tooltip.style.visibility === 'visible' ) { - hideTooltip(); + isClickedOpen = ! isClickedOpen; - } else { + if ( isClickedOpen ) { + infoIcon.classList.add( 'active' ); showTooltip(); + document.addEventListener( 'pointerdown', onDocumentPointerDown ); + + } else { + + infoIcon.classList.remove( 'active' ); + hideTooltip(); + document.removeEventListener( 'pointerdown', onDocumentPointerDown ); }