-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
394 additions
and
41 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
.venn { | ||
display: flex; | ||
flex-direction: column; | ||
gap: var(--spacing-s); | ||
position: relative; | ||
max-width: 90%; | ||
margin: auto; | ||
} | ||
|
||
.venn .venn-content { | ||
position: relative; | ||
} | ||
|
||
.venn .venn-content > div { | ||
box-sizing: border-box; | ||
padding: var(--image-border-radius-xxl); | ||
} | ||
|
||
.venn .venn-content .venn-content-left { | ||
background-color: #F4FADE; | ||
border: 2px solid var(--color-accent-lightgreen-content); | ||
border-bottom: 0; | ||
border-radius: 50vw 50vw 0 0; | ||
padding-top: 18vw; | ||
} | ||
|
||
.venn .venn-content .venn-content-right { | ||
background-color: var(--color-accent-purple-content); | ||
border: 2px solid var(--color-accent-purple-bg); | ||
border-top: 0; | ||
border-radius: 0 0 50vw 50vw; | ||
padding-bottom: 18vw; | ||
} | ||
|
||
.venn .venn-content .venn-content-intersection { | ||
border: 2px solid #3576ae; | ||
background-color: #def3fc; | ||
} | ||
|
||
.venn .venn-content h2 { | ||
margin-bottom: 0.5em; | ||
font-size: var(--type-heading-xl-size); | ||
line-height: var(--type-heading-xl-lh); | ||
text-align: center; | ||
} | ||
|
||
.venn .venn-content ul { | ||
--venn-progress: 50%; | ||
|
||
list-style-type: none; | ||
margin: 0; | ||
padding: 0; | ||
display: flex; | ||
flex-wrap: wrap; | ||
justify-content: center; | ||
gap: 0.5em; | ||
text-align: center; | ||
} | ||
|
||
.venn .venn-content li { | ||
border: 2px solid var(--color-white); | ||
border-radius: var(--image-border-radius-m); | ||
background-color: #fff6; | ||
font-size: var(--type-body-xs-size); | ||
line-height: 1.3; | ||
transition: transform 0.4s, opacity 0.2s; | ||
} | ||
|
||
.venn .venn-content li.below-range { | ||
transform: scale(0.95); | ||
opacity: 0.6; | ||
} | ||
|
||
.venn .venn-content li.in-range { | ||
background: linear-gradient(105deg, var(--color-accent-pink-bg), #f0b2f244 var(--venn-progress), #fff6 var(--venn-progress)); | ||
} | ||
|
||
.venn .venn-content li.exceeds-range { | ||
background-color: var(--color-accent-pink-bg); | ||
} | ||
|
||
.venn .venn-content li:hover { | ||
opacity: 1; | ||
} | ||
|
||
.venn .venn-content a { | ||
display: block; | ||
width: 100%; | ||
border-radius: var(--image-border-radius-s); | ||
padding: calc(0.5em - 4px) 1em; | ||
background-color: transparent; | ||
color: var(--color-black); | ||
font-style: normal; | ||
font-weight: 600; | ||
text-decoration: none; | ||
transition: background-color .2s; | ||
} | ||
|
||
.venn .venn-content a:hover { | ||
background-color: #fff8; | ||
} | ||
|
||
@media (width >= 900px) { | ||
.venn .venn-content { | ||
display: grid; | ||
grid-template-columns: repeat(2, 1fr); | ||
position: relative; | ||
} | ||
|
||
.venn .venn-content > div { | ||
border-radius: var(--image-border-radius-xxl); | ||
padding: var(--image-border-radius-xxl); | ||
} | ||
|
||
.venn .venn-content .venn-content-left { | ||
border: 2px solid var(--color-accent-lightgreen-content); | ||
border-right-width: 1px; | ||
border-radius: var(--image-border-radius-xxl) 0 0 var(--image-border-radius-xxl); | ||
padding-top: var(--image-border-radius-xxl); | ||
padding-right: calc(33% + var(--image-border-radius-xl)); | ||
} | ||
|
||
.venn .venn-content .venn-content-right { | ||
border: 2px solid var(--color-accent-purple-bg); | ||
border-left-width: 1px; | ||
border-radius: 0 var(--image-border-radius-xxl) var(--image-border-radius-xxl) 0; | ||
padding-bottom: var(--image-border-radius-xxl); | ||
padding-left: calc(33% + var(--image-border-radius-xl)); | ||
} | ||
|
||
.venn .venn-content .venn-content-intersection { | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate(-50%, -50%); | ||
width: calc(100% / 3); | ||
border-radius: var(--image-border-radius-xxl); | ||
} | ||
} | ||
|
||
/* slider */ | ||
.venn .venn-slider { | ||
box-sizing: border-box; | ||
font-weight: var(--type-detail-all-weight); | ||
} | ||
|
||
.venn .venn-slider input { | ||
appearance: none; | ||
position: relative; | ||
width: 100%; | ||
height: var(--circular-icon-tag-size); | ||
margin: 0; | ||
border-radius: var(--image-border-radius-xxl); | ||
background-color: var(--bg-color-grey); | ||
cursor: pointer; | ||
overflow: hidden; | ||
transition: outline 0.2s; | ||
} | ||
|
||
.venn .venn-slider input:hover, | ||
.venn .venn-slider input:focus { | ||
outline: 2px solid var(--color-accent-pink-content); | ||
} | ||
|
||
.venn .venn-slider input::-webkit-slider-thumb { | ||
appearance: none; | ||
width: var(--circular-icon-tag-size); | ||
height: var(--circular-icon-tag-size); | ||
border-radius: var(--image-border-radius-xxl) 0 0 var(--image-border-radius-xxl); | ||
background-color: var(--color-accent-pink-bg); | ||
cursor: ew-resize; | ||
box-shadow: -100vw 0 0 100vw var(--color-accent-pink-bg); | ||
} | ||
|
||
.venn .venn-slider label { | ||
display: block; | ||
text-align: center; | ||
margin-bottom: 0.5rem; | ||
} | ||
|
||
.venn .venn-slider .venn-ticks { | ||
display: flex; | ||
justify-content: space-between; | ||
font-size: var(--type-detail-l-size); | ||
line-height: var(--type-detail-l-lh); | ||
text-transform: var(--type-detail-m-transform); | ||
} | ||
|
||
@media (width >= 900px) { | ||
.venn .venn-slider { | ||
order: 1; | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { createTag } from '../../scripts/scripts.js'; | ||
|
||
/** | ||
* Updates the 'level' query parameter in the URL. | ||
* @param {number} value Value for the 'level' parameter. | ||
*/ | ||
function updateLevelParam(value) { | ||
const params = new URLSearchParams(window.location.search); | ||
params.set('level', value); | ||
const url = `${window.location.pathname}?${params.toString()}`; | ||
window.history.replaceState({ path: url }, '', url); | ||
} | ||
|
||
/** | ||
* Updates the venn content display based on the value of the range. | ||
* @param {HTMLInputElement} range Range input element. | ||
* @param {number} value Value of the range. | ||
* @param {NodeListOf<HTMLLIElement>} lis List of <li> elements to update. | ||
*/ | ||
function updateVennDisplay(value, lis) { | ||
lis.forEach((li) => { | ||
li.removeAttribute('style'); | ||
const min = parseInt(li.dataset.min, 10); | ||
const max = parseInt(li.dataset.max, 10); | ||
if (value < min) li.className = 'below-range'; | ||
else if (value >= min && value < max) { | ||
li.className = 'in-range'; | ||
// calculate the percentage position of 'value' within the range min - max | ||
li.style.setProperty('--venn-progress', `${((value - min + 1) / (max - min + 1)) * 100}%`); | ||
} else li.className = 'exceeds-range'; | ||
}); | ||
} | ||
|
||
export default async function decorate(block) { | ||
const content = block.firstElementChild; | ||
content.className = 'venn-content'; | ||
const segments = ['left', 'intersection', 'right']; | ||
[...content.children].forEach((segment, i) => { | ||
const layout = segments[i]; | ||
if (layout) segment.className = `venn-content-${layout}`; | ||
}); | ||
|
||
// establish skill level ranges | ||
let sliderMin = 0; | ||
let sliderMax = 0; | ||
const lis = block.querySelectorAll('li'); | ||
lis.forEach((wrapper) => { | ||
// identify skill from <a> tag | ||
const skill = wrapper.querySelector('a'); | ||
// separate skill level range from skill | ||
const levels = wrapper.textContent.replace(skill.textContent, '').trim(); | ||
wrapper.innerHTML = skill.outerHTML; | ||
if (levels) { | ||
// extract min and max from 'levels' string range | ||
const [min, max] = levels.replace('(', '').split(',').map((n) => parseInt(n, 10)); | ||
if (sliderMin === 0 || min < sliderMin) sliderMin = min; | ||
if (sliderMax === 0 || max > sliderMax) sliderMax = max; | ||
wrapper.dataset.min = min; | ||
wrapper.dataset.max = max; | ||
} | ||
}); | ||
|
||
// build skill slider | ||
const slider = createTag('div', { class: 'venn-slider' }); | ||
const range = createTag('input', { | ||
type: 'range', name: 'venn-slider', id: 'venn-slider', step: 1, | ||
}); | ||
// set range min and max based on skill level values | ||
range.min = sliderMin; | ||
range.max = sliderMax; | ||
range.addEventListener('input', () => { | ||
updateLevelParam(range.value); | ||
updateVennDisplay(parseInt(range.value, 10), lis); | ||
}); | ||
const label = createTag('label', { type: 'range', for: 'venn-slider' }); | ||
label.textContent = 'Skill Level'; | ||
const ticks = createTag('div', { class: 'venn-ticks' }); | ||
// TODO: remove hard-coded text | ||
ticks.innerHTML = `<span>Beginner</span> | ||
<span>Expert</span>`; | ||
slider.append(label, range, ticks); | ||
block.prepend(slider); | ||
|
||
// retrieve level query param | ||
const params = new URLSearchParams(window.location.search); | ||
const level = params.get('level') || sliderMin; | ||
range.value = level; | ||
updateVennDisplay(level, lis); | ||
} |
This file contains 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
Oops, something went wrong.