ds2-core/public/patterns/core/sticky-note/index.html

319 lines
13 KiB
HTML
Raw Normal View History

2024-07-11 21:05:34 -04:00
<html>
<head>
<title>Pattern</title>
</head>
<body data-prismjs-copy-timeout="1500">
<h2>What is it</h2>
2024-07-14 16:18:52 -04:00
<p>Sticky notes provide a way to attach information. They are a DS2 core pattern for making notes. </p>
2024-07-11 21:05:34 -04:00
<h2>When to use it</h2>
2024-07-14 16:18:52 -04:00
<p>Use a sticky when you want to make a note without adding it to the content. </p>
2024-07-11 21:05:34 -04:00
<h2>How to use it</h2>
<p>Uses absolute positioning. Passing an optional element to the init function will initialise tabs within that element. You can move the position using either <code class="language-html inline">float="&#91; right | left &#93;"</code> or <code class="language-html inline">offset="&#91; top | left &#93;"</code>. Offset will take negative values in any web measurement unit.
2024-07-28 15:30:51 -04:00
<sticky-note class="blue" offset="-10rem 1rem">This <strong>is</strong> a sample sticky. You can drag it out of the way if you need to see the content under it.</sticky-note>
<sticky-note float="right">You will notice when you hover over the sticky, it shows a dot in the colour of the sticky in the position where the sticky note refers to (assuming you haven't dragged it and scrolled that location off the screen).</sticky-note>
2024-07-11 21:05:34 -04:00
</p>
<p>If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements". </p>
2024-07-14 16:18:52 -04:00
<tabset id="sticky-note">
<pre class="language-html" tab="html">
<sticky-note class="blue" float="right">This <strong>is</strong> a sample sticky. You can drag it out of the way if you need to see the content under it.</sticky-note></pre>
<pre class="language-pug" tab="pug">sticky-note(float="right").blue This #[strong is] a sample sticky.
2024-07-14 16:18:52 -04:00
| You can drag it out of the way if you need to see the content under it.</pre>
<pre class="language-css" data-tab="css"> @import url("https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap");sticky-note-wrapper{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid transparent;border-radius:50%;display:inline-block;height:0.5rem;position:relative;width:0.5rem}sticky-note-wrapper *{-webkit-box-sizing:border-box;box-sizing:border-box}sticky-note-wrapper sticky-note{cursor:-webkit-grab;cursor:grab;display:-ms-grid;display:grid;float:left;font-size:1rem;height:13rem;left:0;place-items:stretch;position:absolute;top:0;width:13rem;z-index:100}sticky-note-wrapper sticky-note:active{cursor:-webkit-grabbing;cursor:grabbing;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}sticky-note-wrapper sticky-note.right{float:right}sticky-note-wrapper sticky-note>div{-ms-grid-row:1;grid-row:1;-ms-grid-column:1;grid-column:1}sticky-note-wrapper sticky-note>div:first-child{background-color:rgba(0,0,0,0.25);-webkit-box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);display:-ms-grid;display:grid;margin:2rem 1rem 0.25rem 0.36rem;width:calc(100% - 1rem)}sticky-note-wrapper sticky-note>div:nth-child(2){clip-path:url(#stickyClip);display:-ms-grid;display:grid;font-family:"Kalam",cursive;font-style:1rem;font-weight:300;line-height:1.25rem;padding:1rem;place-items:center;text-align:center}sticky-note-wrapper sticky-note>div:nth-child(2)>*{font-family:"Kalam",cursive!important;font-style:normal!important;font-weight:300!important}@media screen and (max-width:1024px){sticky-note-wrapper sticky-note>div:nth-child(2){max-width:13rem;min-width:13rem;width:1rem}}@media screen and (max-width:768px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:1.75rem;max-width:21rem;min-height:21rem}}@media screen and (max-width:640px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:2.5rem;max-width:26rem;min-height:26rem}}sticky-note-wrapper sticky-note>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#ffffdd),color-stop(2%,#ffffd3),color-stop(12%,#ffffd3),color-stop(75%,#ffffc9),to(#ffffba));background:linear-gradient(180deg,#ffffdd 0%,#ffffd3 2%,#ffffd3 12%,#ffffc9 75%,#ffffba 100%)}sticky-note-wrapper sticky-note.blue>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#9dddec),color-stop(2%,#94daea),color-stop(12%,#94daea),color-stop(75%,#8bd7e8),to(#7fd3e6));background:linear-gradient(180deg,#9dddec 0%,#94daea 2%,#94daea 12%,#8bd7e8 75%,#7fd3e6 100%)}sticky-note-wrapper sticky-note.pink>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#fa7c93),color-stop(2%,#fa728b),color-stop(12%,#fa728b),color-stop(75%,#fa6883),to(#f95977));background:linear-gradient(180deg,#fa7c93 0%,#fa728b 2%,#fa728b 12%,#fa6883 75%,#f95977 100%)}sticky-note-wrapper sticky-note.green>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(#c5fcc9),color-stop(2%,#bbfbc0),color-stop(12%,#bbfbc0),color-stop(75%,#b1fab7),to(#a3faaa));background:linear-gradient(180deg,#c5fcc9 0%,#bbfbc0 2%,#bbfbc0 12%,#b1fab7 75%,#a3faaa 100%)}sticky-note-wrapper:has(sticky-note:hover){background-color:#ffffd3;border:1px solid black}sticky-note-wrapper:has(sticky-note.yellow:hover){background-color:#ffffd3}sticky-note-wrapper:has(sticky-note.blue:hover){background-color:#94daea}sticky-note-wrapper:has(sticky-note.pink:hover){background-color:#fa728b}sticky-note-wrapper:has(sticky-note.green:hover){background-color:#bbfbc0}</pre>
2024-07-28 15:30:51 -04:00
<div tab="scss">
<pre class="language-sass">$sticky-colors: ( [sass map with your own defined colours] );
@import "scss/core/switch/_sticky-note";
@include sticky-note;
</pre>
2024-07-28 15:30:51 -04:00
<pre class="language-sass">//- DS2 core (c) 2024 Alexander McIlwraith
2024-07-11 21:05:34 -04:00
//- Licensed under CC BY-SA 4.0
@use 'sass:color';
@use "sass:map";
@use 'sass:list';
@import url('https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap');
$sticky-colors: (
"yellow": #ffffd3,
"blue": #94daea,
"pink": #fa728b,
"green": #bbfbc0 ) !default;
@mixin sticky-note {
sticky-note-wrapper {
box-sizing: border-box;
border: 1px solid transparent;
border-radius: 50%;
display: inline-block;
height: .5rem;
position: relative;
width: .5rem;
& * {
box-sizing: border-box;
}
sticky-note {
cursor: grab;
display: grid;
float: left;
font-size: 1rem;
height: 13rem;
left: 0;
place-items: stretch;
position: absolute;
top: 0;
width: 13rem;
z-index: 100;
&:active {
cursor: grabbing;
user-select: none;
}
@media screen and (max-width: 1024px) {
//width: 15rem;
// background-color: green;
}
@media screen and (max-width: 768px) {
//width: 20rem;
// background-color: blue;
}
@media screen and (max-width: 640px) {
//width: 30rem;
// background-color: yellow;
}
&.right {
float: right;
}
@content;
> div {
grid-row: 1;
grid-column: 1;
&:nth-child(1) {
background-color: rgba(0, 0, 0, 0.25);
box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
display: grid;
margin: 2rem 1rem .25rem .36rem;
width: calc(100% - 1rem);
}
&:nth-child(2) {
clip-path: url(#stickyClip);
display: grid;
font-family: "Kalam", cursive;
font-style: 1rem;
font-weight: 300;
line-height: 1.25rem;
padding: 1rem;
place-items: center;
text-align: center;
// not adding this because maybe we want the sticky note text to be able to be selected and copied.
// user-select: none;
> * {
font-family: "Kalam", cursive !important;
font-style: normal !important;
font-weight: 300 !important;
}
@media screen and (max-width: 1024px) {
max-width: 13rem;
min-width: 13rem;
width: 1rem;
}
@media screen and (max-width: 768px) {
font-size: 1.75rem;
max-width: 21rem;
min-height: 21rem;
}
@media screen and (max-width: 640px) {
font-size: 2.5rem;
max-width: 26rem;
min-height: 26rem;
}
}
}
// default colour
> div:nth-child(2) {
$sticky-color: nth(map.values($sticky-colors), 1);
background: linear-gradient(
180deg,
lighten($sticky-color, 2%) 0%,
$sticky-color 2%,
$sticky-color 12%,
darken($sticky-color, 2%) 75%,
darken($sticky-color, 5%) 100%
);
}
// all class colors
@each $class, $sticky-color in $sticky-colors {
&.#{$class} > div:nth-child(2) {
@if $class != nth(map.keys($sticky-colors), 1) {
background: linear-gradient(
180deg,
lighten($sticky-color, 2%) 0%,
$sticky-color 2%,
$sticky-color 12%,
darken($sticky-color, 2%) 75%,
darken($sticky-color, 5%) 100%
);
}
}
}
}
&:has(sticky-note:hover) {
background-color: #{nth(map.values($sticky-colors), 1)};
border: 1px solid black;
}
@each $class, $sticky-color in $sticky-colors {
&:has(sticky-note.#{$class}:hover) {
background-color: $sticky-color;
}
}
}
}</pre>
2024-07-28 15:30:51 -04:00
</div>
<div tab="js">
<pre class="language-js">import * as stickynote from ""./js/core/sticky-note/_sticky-note.js";
2024-07-28 15:30:51 -04:00
stickynote.init()
</pre>
<pre class="language-js">//- DS2 core (c) 2024 Alexander McIlwraith
2024-07-11 21:05:34 -04:00
//- Licensed under CC BY-SA 4.0
const font = {
size: 0
}
const pos = {
x: 0,
y: 0
}
function drag(sticky) {
sticky.onmousedown = event => {
// get the position within the sticky
pos.x = (event.clientX - sticky.offsetLeft);
pos.y = (event.clientY - sticky.offsetTop);
// on mouse move, move the sticky to the position, minus the offset, of the mouse
document.onmousemove = documentEvent => {
sticky.style.top = (documentEvent.clientY - pos.y) + 'px';
sticky.style.left = (documentEvent.clientX - pos.x) + 'px';
sticky.setAttribute("moved", "true");
}
// when done, remove mouse move and mouse up handlers.
document.onmouseup = () => {
document.onmouseup = null;
document.onmousemove = null;
}
}
}
function waitForElement(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
// If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
const checkBottom = (attach) => {
// check if top or bottom
if (attach.y < 0) {
attach.ys = "bottom";
attach.y = attach.y * -1;
}
}
const setStickyPostions = (s, attach) => {
// set
s.style[attach.ys] = `${attach.y}px`;
s.style[attach.xs] = `${attach.x}px`;
s.style.display = "grid";
}
const css = (el, attr) => {
let st = ""
Object.entries(attr).forEach(val => {
const [key, value] = val;
st += `${key}: ${value}; `;
})
el.setAttribute("style",st.trim());
}
const calculateStickyPosition = (s) => {
let float = s.getAttribute("float");
let p = s.parentNode.getBoundingClientRect()
switch (float) {
case "left":
css(s, {left: (p.left * -1) + "px"})
break;
case "right":
css(s, { left: (Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) - p.left - s.offsetWidth - (font.size * 2)) + "px" });
break;
}
let offset = s.getAttribute("offset");
if (offset !== null) {
offset = offset.trim().split(" ");
css(s, {top: offset[0], left: offset[1] })
}
}
2024-07-12 22:19:12 -04:00
export function init(p = document){
2024-07-11 21:05:34 -04:00
font.size = parseFloat(getComputedStyle(document.documentElement).fontSize.replace("px",""));
2024-07-12 22:19:12 -04:00
p.querySelectorAll("sticky-note").forEach((s) => {
if (s.querySelectorAll("svg").length == 0) {
let wrapper = document.createElement("sticky-note-wrapper");
s.parentNode.insertBefore(wrapper, s);
wrapper.appendChild(s);
s.setAttribute("content", s.innerHTML.replace(/"/g, "\""));
s.innerHTML = `<div><svg width='0' height='0'><defs><clipPath id='stickyClip' clipPathUnits='objectBoundingBox'><path d='M 0 0 Q 0 0.69, 0.03 0.96 0.03 0.96, 1 0.96 Q 0.96 0.69, 0.96 0 0.96 0, 0 0' stroke-linejoin='round' stroke-linecap='square' /></clipPath></defs></svg></div><div><div>${s.innerHTML}</div></div>`;
}
calculateStickyPosition(s);
drag(s);
s.ondblclick = (e) => {
if (e.ctrlKey) {
calculateStickyPosition(s);
} else {
// add one click select
}
}
2024-07-11 21:05:34 -04:00
})
2024-07-12 22:19:12 -04:00
2024-07-11 21:05:34 -04:00
window.onresize = () => {
font.size = parseFloat(getComputedStyle(document.documentElement).fontSize.replace("px",""));
2024-07-12 22:19:12 -04:00
let stickies = p.querySelectorAll("sticky-note");
2024-07-11 21:05:34 -04:00
stickies.forEach((s) => {
calculateStickyPosition(s);
});
}
}</pre>
2024-07-28 15:30:51 -04:00
</div>
2024-07-14 16:18:52 -04:00
</tabset>
2024-07-11 21:05:34 -04:00
</body>
</html>