From 7fd8e666ea32e4c91c69f266664b3ebcdb1cb9a9 Mon Sep 17 00:00:00 2001 From: Victor Westerlund Date: Sat, 23 Nov 2024 08:45:41 +0100 Subject: [PATCH] wip: 2024-11-23T06:05:10+0100 (1732338310) --- public/about.php | 104 +++++++++++----- public/assets/css/pages/about.css | 199 ++++++++++++++++-------------- public/assets/js/pages/about.js | 4 +- 3 files changed, 181 insertions(+), 126 deletions(-) diff --git a/public/about.php b/public/about.php index f23e213..4791029 100644 --- a/public/about.php +++ b/public/about.php @@ -1,6 +1,7 @@ call(Endpoints::ABOUT_LANGUAGES->value)->get()->json(); - $languages_bytes_total = array_sum($languages); + $langs = new class extends API { + public readonly int $total_bytes; + + private readonly Response $resp; + private readonly array $languages; + + public function __construct() { + parent::__construct(); + + // Fetch languages from endpoint + $this->resp = $this->call(Endpoints::ABOUT_LANGUAGES->value)->get(); + + // We got a response from endpoint + if ($this->resp->ok) { + $this->languages = $this->resp->json(); + $this->total_bytes = array_sum($this->languages); + } + } + + // Return all languages as (string) language => (int) language_bytes + public function all(): array { + return $this->languages; + } + + // Return percent of total for all languages + public function get_percent(string $lang, int $mode = PHP_ROUND_HALF_UP): int { + return round(($this->languages[$lang] / $this->total_bytes) * 100, 0, $mode); + } + + // Return language bytes as percent of whole + public function get_percent_str(string $lang): string { + $percent = $this->get_percent($lang, PHP_ROUND_HALF_DOWN); + return ($percent > 1 ? $percent : "<1") . "%"; + } + + // Return languages bytes as a multiple-byte decimal unit + public function get_bytes_str(string $lang): string { + $bytes = $this->languages[$lang]; + + // Calculate factor for unit + $factor = floor((strlen($bytes) - 1) / 3); + // Divide by radix 10 + $format = $bytes / pow(1000, $factor); + + return round($format) . " " . BYTE_UNITS[$factor]; + } + }; ?>
- +

Victor Westerlund

I​'m a full-stack web developer from Sweden.

-

Instead of telling you what <programming/markup/command/query/whatever>-languages I use the most and over-guesstimating how much I use them, I thought I'd just show you instead with little chart which sums the number of bytes for each language for my public mirrors and sources on Forgejo contain and distributes them proportionally. The chart is updated automatically every day.

+

I used to list the <programming/markup/command/whatever>-languages here that I use the most and order them by guesstimating how much I use each one. But then I thought it would be better to just show you instead using this chart that automatically pulls the total bytes for each language from my public mirrors and sources on Forgejo.

- $bytes): ?> - - %
( bytes)
-

-
+ all() as $lang => $bytes): ?> + + get_percent_str($lang) ?>
( bytes)
+ +
- - -

50%

-

PHP

-

13 KB

- -
- -

50%

-

JavasScript

-

13 KB

- -
-
+ + + all() as $lang => $bytes): ?> + +

get_percent_str($lang) ?>

+

+

get_bytes_str($lang) ?>

+ +
+ + +
- $bytes): ?> - - %
( bytes)
-

-
+ all() as $lang => $bytes): ?> + + get_percent_str($lang) ?>
( bytes)
+ +
diff --git a/public/assets/css/pages/about.css b/public/assets/css/pages/about.css index 622fb33..42f855a 100644 --- a/public/assets/css/pages/about.css +++ b/public/assets/css/pages/about.css @@ -65,20 +65,24 @@ section.languages stacked-bar-chart { width: 100%; display: flex; border-radius: 100px; - height: calc(var(--padding) * 1.5); + height: var(--padding); background-color: rgba(255, 255, 255, 0); } -section.languages stacked-bar-chart:hover segment { +section.languages stacked-bar-chart:last-of-type { + flex-direction: row-reverse; +} + +section.languages stacked-bar-chart:hover chart-segment { opacity: .5; } -section.languages stacked-bar-chart segment { +section.languages stacked-bar-chart chart-segment { --border-corner-radius: 100px; transition: 150ms opacity; width: var(--size, 0%); - min-width: 5%; + min-width: 3%; height: 100%; color: white; position: relative; @@ -89,29 +93,43 @@ section.languages stacked-bar-chart segment { border-radius: 2px; } -section.languages stacked-bar-chart segment:hover { - opacity: 1; +section.languages stacked-bar-chart a:nth-child(odd) chart-segment { + background-color: rgba(255, 255, 255, .3); } -section.languages stacked-bar-chart a:first-child segment { +/* ### Round corners */ + +section.languages stacked-bar-chart a:first-child chart-segment { border-top-right-radius: var(--padding); border-bottom-right-radius: var(--padding); border-top-left-radius: var(--border-corner-radius); border-bottom-left-radius: var(--border-corner-radius); } -section.languages stacked-bar-chart a:last-child segment { +section.languages stacked-bar-chart a:last-child chart-segment { border-top-left-radius: var(--padding); border-bottom-left-radius: var(--padding); border-top-right-radius: var(--border-corner-radius); border-bottom-right-radius: var(--border-corner-radius); } -section.languages stacked-bar-chart a:nth-child(odd) segment { - background-color: rgba(255, 255, 255, .3); +section.languages stacked-bar-chart:last-of-type a:first-child chart-segment { + border-top-left-radius: var(--padding); + border-bottom-left-radius: var(--padding); + border-top-right-radius: var(--border-corner-radius); + border-bottom-right-radius: var(--border-corner-radius); } -section.languages stacked-bar-chart segment p { +section.languages stacked-bar-chart:last-of-type a:last-child chart-segment { + border-top-right-radius: var(--padding); + border-bottom-right-radius: var(--padding); + border-top-left-radius: var(--border-corner-radius); + border-bottom-left-radius: var(--border-corner-radius); +} + +/* ### Texts */ + +section.languages stacked-bar-chart chart-segment p { text-align: center; color: inherit; overflow: hidden; @@ -121,50 +139,60 @@ section.languages stacked-bar-chart segment p { padding: 0 3px; } -section.languages stacked-bar-chart segment[style="--size:0%;"] p span { +section.languages stacked-bar-chart chart-segment[style="--size:0%;"] p span { display: none; } -section.languages stacked-bar-chart segment[style="--size:0%;"] p::before { +section.languages stacked-bar-chart chart-segment[style="--size:0%;"] p::before { content: "<1%"; opacity: .5; } -section.languages stacked-bar-chart a segment[data-lang="Go"] { background-color: var(--color-go); } -section.languages stacked-bar-chart a segment[data-lang="PHP"] { background-color: var(--color-php); } -section.languages stacked-bar-chart a segment[data-lang="CSS"] { background-color: var(--color-css); } -section.languages stacked-bar-chart a segment[data-lang="HTML"] { background-color: var(--color-html); } -section.languages stacked-bar-chart a segment[data-lang="Python"] { background-color: var(--color-python); } -section.languages stacked-bar-chart a segment[data-lang="TypeScript"] { background-color: var(--color-typescript); } -section.languages stacked-bar-chart a segment[data-lang="Shell"] { background-color: var(--color-shell); color: black; } -section.languages stacked-bar-chart a segment[data-lang="JavaScript"] { background-color: var(--color-javascript); color: black; } - -/* ### Hoverpop */ - -section.languages stacked-bar-chart segment [data-hover] { +section.languages stacked-bar-chart chart-segment [data-hover] { display: none; - position: absolute; - top: 0; - left: 0; - text-align: center; - transform: translate(0, 0); - background-color: inherit; - padding: 5px 10px; - white-space: nowrap; - pointer-events: none; - border-radius: 6px; - -webkit-backdrop-filter: brightness(.2) blur(20px); - backdrop-filter: brightness(.2) blur(20px); } -section.languages stacked-bar-chart segment [data-hover].hovering { - display: initial; -} +/* ### Colors */ + +section.languages stacked-bar-chart a chart-segment[data-lang="Go"] { background-color: var(--color-go); } +section.languages stacked-bar-chart a chart-segment[data-lang="PHP"] { background-color: var(--color-php); } +section.languages stacked-bar-chart a chart-segment[data-lang="CSS"] { background-color: var(--color-css); } +section.languages stacked-bar-chart a chart-segment[data-lang="HTML"] { background-color: var(--color-html); } +section.languages stacked-bar-chart a chart-segment[data-lang="Python"] { background-color: var(--color-python); } +section.languages stacked-bar-chart a chart-segment[data-lang="TypeScript"] { background-color: var(--color-typescript); } +section.languages stacked-bar-chart a chart-segment[data-lang="Shell"] { background-color: var(--color-shell); color: black; } +section.languages stacked-bar-chart a chart-segment[data-lang="JavaScript"] { background-color: var(--color-javascript); color: black; } /* ### Legend */ -section.languages languages { - display: none; +section.languages languages-list { + gap: calc(var(--padding) / 2); + display: grid; + grid-template-columns: repeat(3, 1fr); + margin: var(--padding) 0; +} + +section.languages languages-list language-item { + gap: 10px; + display: flex; + border-radius: 8px; + align-items: center; + fill: var(--color-php); + padding: calc(var(--padding) / 1.5); + border: solid 1px rgba(255, 255, 255, .1); + background: linear-gradient(139deg, rgba(0, 0, 0, 0) 0%, rgba(79, 93, 144, .2) 100%); +} + +section.languages languages-list language-item p.lang { + font-size: 1.3em; + font-weight: 900; + color: var(--color-php); +} + +section.languages languages-list language-item svg { + width: 2em; + margin-left: auto; + transform: rotate(-90deg); } /* # Interests */ @@ -209,60 +237,45 @@ div.interests p { } } +/* Feature queries */ + +@media (hover: hover) { + section.languages stacked-bar-chart chart-segment:hover { + opacity: 1; + } + + section.languages stacked-bar-chart chart-segment [data-hover] { + display: none; + position: absolute; + top: 0; + left: 0; + text-align: center; + transform: translate(0, 0); + background-color: inherit; + padding: 5px 10px; + white-space: nowrap; + pointer-events: none; + border-radius: 6px; + z-index: 2000; + -webkit-backdrop-filter: brightness(.2) blur(20px); + backdrop-filter: brightness(.2) blur(20px); + } + + section.languages stacked-bar-chart chart-segment [data-hover].hovering { + display: initial; + } +} + /* Size queries */ -@media (max-width: 700px) { - section.languages { - gap: var(--padding); - display: flex; - flex-direction: column; +@media (max-width: 900px) { + section.languages languages-list { + grid-template-columns: repeat(2, 1fr); } +} - section.languages stacked-bar-chart { - height: 10px; - pointer-events: none; - } - - section.languages stacked-bar-chart:last-of-type { - flex-direction: row-reverse; - } - - section.languages stacked-bar-chart segment { - min-width: 1%; - } - - section.languages stacked-bar-chart segment p { - display: none; - } - - /* ### Languages */ - - section.languages languages { - gap: calc(var(--padding) / 2); - display: flex; - flex-direction: column; - } - - section.languages languages language { - gap: 10px; - display: flex; - border-radius: 8px; - align-items: center; - fill: var(--color-php); - padding: calc(var(--padding) / 1.5); - border: solid 1px rgba(255, 255, 255, .1); - background: linear-gradient(139deg, rgba(0, 0, 0, 0) 0%, rgba(79, 93, 144, .2) 100%); - } - - section.languages languages language p.lang { - font-size: 1.3em; - font-weight: 900; - color: var(--color-php); - } - - section.languages languages language svg { - width: 2em; - margin-left: auto; - transform: rotate(-90deg); +@media (max-width: 650px) { + section.languages languages-list { + grid-template-columns: 1fr; } } \ No newline at end of file diff --git a/public/assets/js/pages/about.js b/public/assets/js/pages/about.js index df27e69..0562f27 100644 --- a/public/assets/js/pages/about.js +++ b/public/assets/js/pages/about.js @@ -69,6 +69,4 @@ const implodeInterests = () => { } // Languages stacking bar chart hoverpop -{ - new Hoverpop(document.querySelectorAll("stacked-bar-chart segment")); -} \ No newline at end of file +new Hoverpop(document.querySelectorAll("stacked-bar-chart chart-segment")); \ No newline at end of file