Last active
January 12, 2025 16:08
-
-
Save brifiction/bd43a433209c4fb585146021b31169b2 to your computer and use it in GitHub Desktop.
Medium-like Highlighting Tools Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="app"> | |
<highlightable | |
@share="onShare" | |
@highlight="onHighlight" | |
> | |
<p> | |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet at debitis deserunt, optio rem eaque obcaecati non possimus nisi assumenda architecto exercitationem dolore quo praesentium, deleniti reiciendis sed ab nihil! | |
</p> | |
</highlightable> | |
<p> | |
<strong>This paragraph can't be highlighted.</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore ipsam repellat, fugiat aut ex incidunt ut quisquam quasi consequatur ducimus quo in, cum soluta eos dolores tempore unde voluptate modi. | |
</p> | |
</div> | |
<script type="text/x-template" id="highlightable"> | |
<div> | |
<div | |
v-show="showTools" | |
class="tools" | |
:style="{ | |
left: `${x}px`, | |
top: `${y}px` | |
}" | |
@mousedown.prevent="" | |
> | |
<span | |
class="item" | |
@mousedown.prevent="handleAction('share')" | |
> | |
<svg style="width:24px;height:24px" viewBox="0 0 24 24"> | |
<path fill="#000000" d="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" /> | |
</svg> | |
</span> | |
<span | |
class="item" | |
@mousedown.prevent="handleAction('highlight')" | |
> | |
<svg style="width:24px;height:24px" viewBox="0 0 24 24"> | |
<path fill="#000000" d="M18.5,1.15C17.97,1.15 17.46,1.34 17.07,1.73L11.26,7.55L16.91,13.2L22.73,7.39C23.5,6.61 23.5,5.35 22.73,4.56L19.89,1.73C19.5,1.34 19,1.15 18.5,1.15M10.3,8.5L4.34,14.46C3.56,15.24 3.56,16.5 4.36,17.31C3.14,18.54 1.9,19.77 0.67,21H6.33L7.19,20.14C7.97,20.9 9.22,20.89 10,20.12L15.95,14.16" /> | |
</svg> | |
</span> | |
</div> | |
<slot/> | |
</div> | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Vue.component('highlightable', { | |
template: '#highlightable', | |
data () { | |
return { | |
x: 0, | |
y: 0, | |
showTools: false, | |
selectedText: '' | |
} | |
}, | |
computed: { | |
highlightableEl () { | |
return this.$slots.default[0].elm | |
} | |
}, | |
mounted () { | |
window.addEventListener('mouseup', this.onMouseup) | |
}, | |
beforeDestroy () { | |
window.removeEventListener('mouseup', this.onMouseup) | |
}, | |
methods: { | |
onMouseup () { | |
const selection = window.getSelection() | |
const startNode = selection.getRangeAt(0).startContainer.parentNode | |
const endNode = selection.getRangeAt(0).endContainer.parentNode | |
if (!startNode.isSameNode(this.highlightableEl) || !startNode.isSameNode(endNode)) { | |
this.showTools = false | |
return | |
} | |
const { x, y, width } = selection.getRangeAt(0).getBoundingClientRect() | |
if (!width) { | |
this.showTools = false | |
return | |
} | |
this.x = x + (width / 2) | |
this.y = y + window.scrollY - 10 | |
this.showTools = true | |
this.selectedText = selection.toString() | |
}, | |
handleAction (action) { | |
this.$emit(action, this.selectedText) | |
} | |
} | |
}) | |
new Vue({ | |
el: '#app', | |
methods: { | |
onShare (text) { | |
console.log('share:', text) | |
}, | |
onHighlight (text) { | |
console.log('highlight:', text) | |
} | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#app | |
width: 90% | |
max-width: 800px | |
padding: 5px | |
margin: 30px auto | |
font-family Verdana | |
color: #333 | |
width: 100% | |
p | |
line-height 1.5 | |
.tools | |
height: 30px | |
padding: 5px 10px | |
background #333 | |
border-radius 3px | |
position: absolute | |
top: 0 | |
left: 0 | |
transform: translate(-50%, -100%) | |
transition: 0.2s all | |
display: flex | |
justify-content: center | |
align-items: center | |
.tools:after | |
content: '' | |
position: absolute | |
left: 50% | |
bottom: -5px | |
transform: translateX(-50%) | |
width: 0 | |
height: 0 | |
border-left: 6px solid transparent | |
border-right: 6px solid transparent | |
border-top: 6px solid #333 | |
.item | |
color: #FFF | |
cursor: pointer | |
.item path | |
fill: #FFF | |
.item:hover path | |
fill: #1199ff | |
.item:hover | |
color: #1199ff | |
.item + .item | |
margin-left: 10px |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment