Add bulk action drag UI
This commit is contained in:
parent
dda715be1b
commit
3b8ce3bd6d
5 changed files with 656 additions and 12 deletions
|
@ -1,13 +1,372 @@
|
|||
class App.TicketOverview extends App.Controller
|
||||
className: 'overviews'
|
||||
activeFocus: 'nav'
|
||||
mouse:
|
||||
x: null
|
||||
y: null
|
||||
|
||||
elements:
|
||||
'.js-batch-overlay': 'batchOverlay'
|
||||
'.js-batch-overlay-backdrop': 'batchOverlayBackdrop'
|
||||
'.js-batch-cancel': 'batchCancel'
|
||||
'.js-batch-macro-circle': 'batchMacroCircle'
|
||||
'.js-batch-assign-circle': 'batchAssignCircle'
|
||||
'.js-batch-assign': 'batchAssign'
|
||||
'.js-batch-macro': 'batchMacro'
|
||||
|
||||
events:
|
||||
'mousedown .item': 'startDragItem'
|
||||
'mouseenter .js-batch-overlay-entry': 'highlightBatchEntry'
|
||||
'mouseleave .js-batch-overlay-entry': 'unhighlightBatchEntry'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
|
||||
startDragItem: (event) ->
|
||||
@grabbedItem = $(event.currentTarget)
|
||||
offset = @grabbedItem.offset()
|
||||
@batchDragger = $(App.view('ticket_overview/batch_dragger')())
|
||||
@grabbedItemClone = @grabbedItem.clone()
|
||||
@grabbedItemClone.data('offset', @grabbedItem.offset())
|
||||
@grabbedItemClone.addClass('batch-dragger-item js-main-item')
|
||||
@batchDragger.append @grabbedItemClone
|
||||
|
||||
@batchDragger.data
|
||||
startX: event.pageX
|
||||
startY: event.pageY
|
||||
dx: Math.min(event.pageX - offset.left, 180)
|
||||
dy: event.pageY - offset.top
|
||||
moved: false
|
||||
|
||||
$(document).on 'mousemove.item', @dragItem
|
||||
$(document).one 'mouseup.item', @endDragItem
|
||||
# TODO: fire @cancelDrag on ESC
|
||||
|
||||
dragItem: (event) =>
|
||||
event.preventDefault()
|
||||
pos = @batchDragger.data()
|
||||
threshold = 3
|
||||
x = event.pageX - pos.dx
|
||||
y = event.pageY - pos.dy
|
||||
dir = if event.pageY > pos.startY then 1 else -1
|
||||
|
||||
if !pos.moved
|
||||
if Math.abs(event.pageX - pos.startX) > threshold or Math.abs(event.pageY - pos.startY) > threshold
|
||||
@batchDragger.data 'moved', true
|
||||
# check grabbed items batch checkbox to make sure its checked
|
||||
# (could be grabbed without checking the checkbox it)
|
||||
@grabbedItemWasntChecked = !@grabbedItem.find('[name="bulk"]').prop('checked')
|
||||
@grabbedItem.find('[name="bulk"]').prop('checked', true)
|
||||
@grabbedItemClone.find('[name="bulk"]').prop('checked', true)
|
||||
|
||||
additionalItems = @el.find('[name="bulk"]:checked').parents('.item').not(@grabbedItem)
|
||||
additionalItemsClones = additionalItems.clone()
|
||||
@draggedItems = @grabbedItemClone.add(additionalItemsClones)
|
||||
# store offsets for later use
|
||||
additionalItemsClones.each (i, item) -> $(@).data('offset', additionalItems.eq(i).offset())
|
||||
@batchDragger.prepend additionalItemsClones.addClass('batch-dragger-item').get().reverse()
|
||||
if(additionalItemsClones.length)
|
||||
@batchDragger.find('.js-batch-dragger-count').text(@draggedItems.length)
|
||||
|
||||
$('#app').append @batchDragger
|
||||
|
||||
@draggedItems.each (i, item) =>
|
||||
dx = $(item).data('offset').left - $(item).offset().left - x
|
||||
dy = $(item).data('offset').top - $(item).offset().top - y
|
||||
$.Velocity.hook item, 'translateX', "#{dx}px"
|
||||
$.Velocity.hook item, 'translateY', "#{dy}px"
|
||||
|
||||
@moveDraggedItems(-dir)
|
||||
|
||||
@mouseY = event.pageY
|
||||
@showBatchOverlay()
|
||||
else
|
||||
return
|
||||
|
||||
$.Velocity.hook @batchDragger, 'translateX', "#{x}px"
|
||||
$.Velocity.hook @batchDragger, 'translateY', "#{y}px"
|
||||
|
||||
endDragItem: (event) =>
|
||||
$(document).off 'mousemove.item'
|
||||
$(document).off 'mouseup.item'
|
||||
pos = @batchDragger.data()
|
||||
|
||||
if !@hoveredBatchEntry
|
||||
@cleanUpDrag()
|
||||
return
|
||||
|
||||
$.Velocity.hook @batchDragger, 'transformOriginX', "#{pos.dx}px"
|
||||
$.Velocity.hook @batchDragger, 'transformOriginY', "#{pos.dy}px"
|
||||
@hoveredBatchEntry.velocity
|
||||
properties:
|
||||
scale: 1.1
|
||||
options:
|
||||
duration: 200
|
||||
complete: =>
|
||||
@hoveredBatchEntry.velocity "reverse",
|
||||
duration: 200
|
||||
complete: =>
|
||||
# clean scale
|
||||
@hoveredBatchEntry.removeAttr('style')
|
||||
@cleanUpDrag(true)
|
||||
@performBatchAction @hoveredBatchEntry.attr('data-action')
|
||||
@hoveredBatchEntry = null
|
||||
@batchDragger.velocity
|
||||
properties:
|
||||
scale: 0
|
||||
options:
|
||||
duration: 200
|
||||
|
||||
cancelDrag: ->
|
||||
$(document).off 'mousemove.item'
|
||||
$(document).off 'mouseup.item'
|
||||
@cleanUpDrag()
|
||||
|
||||
cleanUpDrag: (success) ->
|
||||
@hideBatchOverlay()
|
||||
$('.batch-dragger').remove()
|
||||
|
||||
if @grabbedItemWasntChecked
|
||||
@grabbedItem.find('[name="bulk"]').prop('checked', false)
|
||||
|
||||
if success
|
||||
# uncheck all checked items
|
||||
@el.find('[name="bulk"]:checked').prop('checked', false)
|
||||
@el.find('[name="bulk_all"]').prop('checked', false)
|
||||
|
||||
moveDraggedItems: (dir) ->
|
||||
@draggedItems.velocity
|
||||
properties:
|
||||
translateX: 0
|
||||
translateY: (i) => dir * i * @batchDragger.height()/2
|
||||
options:
|
||||
easing: 'ease-in-out'
|
||||
duration: 300
|
||||
|
||||
@batchDragger.find('.js-batch-dragger-count').velocity
|
||||
properties:
|
||||
translateY: if dir < 0 then 0 else -@batchDragger.height()+8
|
||||
options:
|
||||
easing: 'ease-in-out'
|
||||
duration: 300
|
||||
|
||||
performBatchAction: (action) ->
|
||||
console.log "perform action #{action} on checked items"
|
||||
|
||||
showBatchOverlay: ->
|
||||
@batchOverlay.show()
|
||||
@batchOverlayBackdrop.velocity { opacity: [1, 0] }, { duration: 500 }
|
||||
@batchOverlayShown = true
|
||||
$(document).on 'mousemove.batchoverlay', @controlBatchOverlay
|
||||
|
||||
hideBatchOverlay: ->
|
||||
$(document).off 'mousemove.batchoverlay'
|
||||
@batchOverlayShown = false
|
||||
@batchOverlayBackdrop.velocity { opacity: [0, 1] }, { duration: 300, queue: false }
|
||||
@hideBatchCircles =>
|
||||
@batchOverlay.hide()
|
||||
|
||||
if @batchAssignShown
|
||||
@hideBatchAssign()
|
||||
|
||||
if @batchMacroShown
|
||||
@hideBatchMacro()
|
||||
|
||||
controlBatchOverlay: (event) =>
|
||||
# store to detect if the mouse is hovering a drag-action entry
|
||||
# after an animation ended -> @highlightBatchEntryAtMousePosition
|
||||
@mouse.x = event.pageX
|
||||
@mouse.y = event.pageY
|
||||
|
||||
if event.pageY <= window.innerHeight/5*2
|
||||
mouseInArea = 'top'
|
||||
else if event.pageY > window.innerHeight/5*2 && event.pageY <= window.innerHeight/5*3
|
||||
mouseInArea = 'middle'
|
||||
else
|
||||
mouseInArea = 'bottom'
|
||||
|
||||
switch mouseInArea
|
||||
when 'top'
|
||||
if !@batchMacroShown
|
||||
@hideBatchCircles()
|
||||
@showBatchMacro()
|
||||
@moveDraggedItems(1)
|
||||
|
||||
when 'middle'
|
||||
if @batchAssignShown
|
||||
@hideBatchAssign()
|
||||
|
||||
if @batchMacroShown
|
||||
@hideBatchMacro()
|
||||
|
||||
if !@batchCirclesShown
|
||||
@showBatchCircles()
|
||||
|
||||
when 'bottom'
|
||||
if !@batchAssignShown
|
||||
@hideBatchCircles()
|
||||
@showBatchAssign()
|
||||
@moveDraggedItems(-1)
|
||||
|
||||
showBatchCircles: ->
|
||||
@batchCirclesShown = true
|
||||
|
||||
@batchMacroCircle.velocity
|
||||
properties:
|
||||
translateY: [0, '-150%']
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
easing: [1,-.55,.2,1.37]
|
||||
duration: 500
|
||||
visibility: 'visible'
|
||||
delay: 200
|
||||
|
||||
@batchAssignCircle.velocity
|
||||
properties:
|
||||
translateY: [0, '150%']
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
easing: [1,-.55,.2,1.37]
|
||||
duration: 500
|
||||
visibility: 'visible'
|
||||
delay: 200
|
||||
|
||||
hideBatchCircles: (callback) ->
|
||||
@batchMacroCircle.velocity
|
||||
properties:
|
||||
translateY: ['-150%', 0]
|
||||
opacity: [0, 1]
|
||||
options:
|
||||
duration: 300
|
||||
visibility: 'hidden'
|
||||
queue: false
|
||||
|
||||
@batchAssignCircle.velocity
|
||||
properties:
|
||||
translateY: ['150%', 0]
|
||||
opacity: [0, 1]
|
||||
options:
|
||||
duration: 300
|
||||
complete: callback
|
||||
visibility: 'hidden'
|
||||
queue: false
|
||||
|
||||
@batchCirclesShown = false
|
||||
|
||||
showBatchAssign: ->
|
||||
return if !@batchOverlayShown # user might have dropped the item already
|
||||
@batchAssignShown = true
|
||||
|
||||
@batchAssign.velocity
|
||||
properties:
|
||||
translateY: [0, '100%']
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
easing: [1,-.55,.2,1.37]
|
||||
duration: 500
|
||||
visibility: 'visible'
|
||||
complete: @highlightBatchEntryAtMousePosition
|
||||
delay: if @batchCirclesShown then 0 else 200
|
||||
|
||||
@batchCancel.css
|
||||
top: 0
|
||||
bottom: 'auto'
|
||||
|
||||
@batchCancel.velocity
|
||||
properties:
|
||||
translateY: [0, '100%']
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
easing: [1,-.55,.2,1.37]
|
||||
duration: 500
|
||||
visibility: 'visible'
|
||||
delay: if @batchCirclesShown then 0 else 200
|
||||
|
||||
hideBatchAssign: ->
|
||||
@batchAssign.velocity
|
||||
properties:
|
||||
translateY: ['100%', 0]
|
||||
opacity: [0, 1]
|
||||
options:
|
||||
duration: 300
|
||||
visibility: 'hidden'
|
||||
queue: false
|
||||
|
||||
@batchCancel.velocity
|
||||
properties:
|
||||
translateY: ['100%', 0]
|
||||
opacity: [0, 1]
|
||||
options:
|
||||
duration: 300
|
||||
visibility: 'hidden'
|
||||
queue: false
|
||||
|
||||
@batchAssignShown = false
|
||||
|
||||
showBatchMacro: ->
|
||||
return if !@batchOverlayShown # user might have dropped the item already
|
||||
@batchMacroShown = true
|
||||
|
||||
@batchMacro.velocity
|
||||
properties:
|
||||
translateY: [0, '-100%']
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
easing: [1,-.55,.2,1.37]
|
||||
duration: 500
|
||||
visibility: 'visible'
|
||||
complete: @highlightBatchEntryAtMousePosition
|
||||
delay: if @batchCirclesShown then 0 else 200
|
||||
|
||||
@batchCancel.css
|
||||
top: 'auto'
|
||||
bottom: 0
|
||||
@batchCancel.velocity
|
||||
properties:
|
||||
translateY: [0, '-100%']
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
easing: [1,-.55,.2,1.37]
|
||||
duration: 500
|
||||
visibility: 'visible'
|
||||
delay: if @batchCirclesShown then 0 else 200
|
||||
|
||||
hideBatchMacro: ->
|
||||
@batchMacro.velocity
|
||||
properties:
|
||||
translateY: ['-100%', 0]
|
||||
opacity: [0, 1]
|
||||
options:
|
||||
duration: 300
|
||||
visibility: 'hidden'
|
||||
queue: false
|
||||
|
||||
@batchCancel.velocity
|
||||
properties:
|
||||
translateY: ['-100%', 0]
|
||||
opacity: [0, 1]
|
||||
options:
|
||||
duration: 300
|
||||
visibility: 'hidden'
|
||||
queue: false
|
||||
|
||||
@batchMacroShown = false
|
||||
|
||||
highlightBatchEntryAtMousePosition: =>
|
||||
entryAtPoint = $(document.elementFromPoint(@mouse.x, @mouse.y)).closest('.js-batch-overlay-entry')
|
||||
if(entryAtPoint.length)
|
||||
@hoveredBatchEntry = entryAtPoint.addClass('is-hovered')
|
||||
|
||||
highlightBatchEntry: (event) ->
|
||||
@hoveredBatchEntry = $(event.currentTarget).addClass('is-hovered')
|
||||
|
||||
unhighlightBatchEntry: (event) ->
|
||||
@hoveredBatchEntry = null
|
||||
$(event.currentTarget).removeClass('is-hovered')
|
||||
|
||||
render: ->
|
||||
elLocal = $(App.view('ticket_overview')())
|
||||
elLocal = $(App.view('ticket_overview/index')())
|
||||
|
||||
@navBarControllerVertical = new Navbar
|
||||
el: elLocal.find('.overview-header')
|
||||
|
@ -397,10 +756,10 @@ class Table extends App.Controller
|
|||
)
|
||||
table = $(table)
|
||||
table.delegate('[name="bulk_all"]', 'click', (e) ->
|
||||
if $(e.target).attr('checked')
|
||||
$(e.target).closest('table').find('[name="bulk"]').attr('checked', true)
|
||||
if $(e.currentTarget).prop('checked')
|
||||
$(e.currentTarget).closest('table').find('[name="bulk"]').prop('checked', true)
|
||||
else
|
||||
$(e.target).closest('table').find('[name="bulk"]').attr('checked', false)
|
||||
$(e.currentTarget).closest('table').find('[name="bulk"]').prop('checked', false)
|
||||
)
|
||||
@$('.table-overview').append(table)
|
||||
else
|
||||
|
@ -440,6 +799,25 @@ class Table extends App.Controller
|
|||
@bulkForm.hide()
|
||||
else
|
||||
@bulkForm.show()
|
||||
|
||||
if @lastChecked && e.shiftKey
|
||||
# check items in a row
|
||||
currentItem = $(e.currentTarget).parents('.item')
|
||||
lastCheckedItem = @lastChecked.parents('.item')
|
||||
items = currentItem.parent().children()
|
||||
|
||||
if currentItem.index() > lastCheckedItem.index()
|
||||
# current item is below last checked item
|
||||
startId = lastCheckedItem.index()
|
||||
endId = currentItem.index()
|
||||
else
|
||||
# current item is above last checked item
|
||||
startId = currentItem.index()
|
||||
endId = lastCheckedItem.index()
|
||||
|
||||
items.slice(startId+1, endId).find('[name="bulk"]').prop('checked', (-> !@checked))
|
||||
|
||||
@lastChecked = $(e.currentTarget)
|
||||
callbackIconHeader = (headers) ->
|
||||
attribute =
|
||||
name: 'icon'
|
||||
|
@ -523,8 +901,8 @@ class Table extends App.Controller
|
|||
|
||||
# deselect bulk_all if one item is uncheck observ
|
||||
@$('.table-overview').delegate('[name="bulk"]', 'click', (e) ->
|
||||
if !$(e.target).attr('checked')
|
||||
$(e.target).parents().find('[name="bulk_all"]').attr('checked', false)
|
||||
if !$(e.target).prop('checked')
|
||||
$(e.target).parents().find('[name="bulk_all"]').prop('checked', false)
|
||||
)
|
||||
|
||||
getSelected: ->
|
||||
|
@ -540,7 +918,7 @@ class Table extends App.Controller
|
|||
ticketId = $(element).val()
|
||||
for ticketIdSelected in ticketIDs
|
||||
if ticketIdSelected is ticketId
|
||||
$(element).attr('checked', true)
|
||||
$(element).prop('checked', true)
|
||||
)
|
||||
|
||||
viewmode: (e) =>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<div class="sidebar"></div>
|
||||
<div class="main flex">
|
||||
<div class="overview-header"></div>
|
||||
<div class="overview-table"></div>
|
||||
</div>
|
|
@ -0,0 +1,3 @@
|
|||
<div class="batch-dragger zIndex-10">
|
||||
<div class="batch-dragger-counter js-batch-dragger-count"></div>
|
||||
</div>
|
|
@ -0,0 +1,50 @@
|
|||
<div class="sidebar"></div>
|
||||
<div class="main flex">
|
||||
<div class="overview-header"></div>
|
||||
<div class="overview-table"></div>
|
||||
</div>
|
||||
<div class="batch-overlay js-batch-overlay">
|
||||
<div class="batch-overlay-backdrop js-batch-overlay-backdrop"></div>
|
||||
<div class="batch-overlay-cancel js-batch-cancel">
|
||||
<%- @T('drag here to cancel') %>
|
||||
</div>
|
||||
<div class="batch-overlay-circle batch-overlay-circle--top js-batch-macro-circle">
|
||||
<div class="batch-overlay-circle-label"><%- @T('run macro') %></div>
|
||||
<%- @Icon('arrow-up') %>
|
||||
</div>
|
||||
<div class="batch-overlay-circle batch-overlay-circle--bottom js-batch-assign-circle">
|
||||
<%- @Icon('arrow-down') %>
|
||||
<div class="batch-overlay-circle-label"><%- @T('assign tickets') %></div>
|
||||
</div>
|
||||
<div class="batch-overlay-assign batch-overlay-box js-batch-assign">
|
||||
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="assign">
|
||||
<span class="avatar size-80 avatar--unique" style="background-position: -100px -150px;">HH</span>
|
||||
<div class="batch-overlay-assign-entry-name">Hans Huber</div>
|
||||
</div>
|
||||
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="assign">
|
||||
<span class="avatar avatar--organization size-80 avatar--unique" style="background-position: -200px -60px;">
|
||||
<%- @Icon('organization') %>
|
||||
</span>
|
||||
<div class="batch-overlay-assign-entry-name">Zammad</div>
|
||||
<div class="batch-overlay-assign-entry-detail">3 Personen</div>
|
||||
</div>
|
||||
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="assign">
|
||||
<span class="avatar size-80 avatar--unique" style="background-position: -30px -10px;">FD</span>
|
||||
<div class="batch-overlay-assign-entry-name">Felicity Dickens</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="batch-overlay-macro batch-overlay-box js-batch-macro">
|
||||
<div class="batch-overlay-macro-entry js-batch-overlay-entry" data-action="macro">
|
||||
<div class="batch-overlay-macro-entry-name">Close</div>
|
||||
</div>
|
||||
<div class="batch-overlay-macro-entry js-batch-overlay-entry" data-action="macro">
|
||||
<div class="batch-overlay-macro-entry-name">Close & Tag as Spam</div>
|
||||
</div>
|
||||
<div class="batch-overlay-macro-entry js-batch-overlay-entry" data-action="macro">
|
||||
<div class="batch-overlay-macro-entry-name">Close & Reply we're on Holidays</div>
|
||||
</div>
|
||||
<div class="batch-overlay-macro-entry js-batch-overlay-entry" data-action="macro">
|
||||
<div class="batch-overlay-macro-entry-name">Escalate to 2nd level</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -3580,6 +3580,23 @@ footer {
|
|||
}
|
||||
}
|
||||
|
||||
&--organization {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.icon-organization {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
&.size-80 {
|
||||
.icon-organization {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-logo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -8321,6 +8338,207 @@ output {
|
|||
margin: 20px 0 32px;
|
||||
}
|
||||
|
||||
.batch-overlay {
|
||||
@extend .fit;
|
||||
z-index: 1;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
letter-spacing: 0.07em;
|
||||
font-size: 0.95em;
|
||||
line-height: 1.3;
|
||||
display: none;
|
||||
will-change: display;
|
||||
cursor: grabbing;
|
||||
overflow: hidden;
|
||||
|
||||
&-backdrop {
|
||||
@extend .fit;
|
||||
background: hsla(231,20%,8%,.8);
|
||||
opacity: 0;
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
&-circle {
|
||||
margin: 35px auto;
|
||||
background: hsl(207,7%,29%);
|
||||
border-radius: 100%;
|
||||
border: 4px solid white;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
padding: 20px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
will-change: transform, opacity;
|
||||
visibility: hidden;
|
||||
|
||||
&--top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&--bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: currentColor;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-label {
|
||||
width: 50%;
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-cancel {
|
||||
background: hsla(0,0%,100%,.21);
|
||||
background-clip: padding-box;
|
||||
border: 2px dashed hsla(0,0%,100%,.3);
|
||||
border-radius: 8px;
|
||||
padding: 28px;
|
||||
margin: 50px 200px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
visibility: hidden;
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
&-box {
|
||||
background: hsl(232,9%,17%);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
padding: 37px 25px;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
will-change: opacity, transition;
|
||||
}
|
||||
|
||||
&-assign {
|
||||
padding-bottom: 87px; // 37px + 50px
|
||||
bottom: -50px; // extra space for bounce animation
|
||||
|
||||
&-entry {
|
||||
padding: 13px;
|
||||
|
||||
&.is-hovered {
|
||||
.avatar {
|
||||
border-color: $highlight-color;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border: 4px solid hsl(231,5%,30%);
|
||||
margin-bottom: 10px;
|
||||
box-sizing: content-box;
|
||||
transition: transform 120ms;
|
||||
}
|
||||
|
||||
&-detail {
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-macro {
|
||||
padding-top: 87px; // 37px + 50px
|
||||
top: -50px; // extra space for bounce animation
|
||||
|
||||
&-entry {
|
||||
margin: 13px;
|
||||
border: 4px solid hsl(231,5%,30%);
|
||||
background: hsl(233,9%,24%);
|
||||
border-radius: 100%;
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
padding: 13px 13px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.9em;
|
||||
|
||||
&.is-hovered {
|
||||
border-color: $highlight-color;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.batch-dragger {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
pointer-events: none;
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
will-change: transform;
|
||||
|
||||
&-item {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: hsl(200,100%,91%);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 11px 0 9px 11px;
|
||||
box-shadow: 0 0 10px hsla(0,0%,0%,.28);
|
||||
will-change: transform;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
td {
|
||||
display: block;
|
||||
padding: 0 12px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:nth-child(3) {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
&:nth-child(n+4) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-counter {
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
bottom: -8px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 99px;
|
||||
z-index: 1;
|
||||
color: white;
|
||||
background: $highlight-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 0 10px hsla(0,0%,0%,.28);
|
||||
will-change: transform;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
----------------
|
||||
|
|
Loading…
Reference in a new issue