A website inspired by Last.fm that will keep track of your listening statistics
lastfm music statistics
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add icon component with icons form heroicons

oscar345 6132eb3e 7a8b7c92

+70 -2
+4 -1
web/components/content/Icon.svelte
··· 1 1 <script lang="ts"> 2 2 type Props = { 3 3 name: string; 4 + class?: string; 4 5 }; 5 6 6 - let {}: Props = $props(); 7 + let { name, class: class_ }: Props = $props(); 7 8 </script> 9 + 10 + <span class={["icon", name, class_]}></span>
+48
web/lib/plugins/heroicons.plugin.js
··· 1 + import plugin from "tailwindcss/plugin"; 2 + import { readdirSync, readFileSync } from "fs"; 3 + import { join, basename, dirname } from "path"; 4 + import { fileURLToPath } from "url"; 5 + 6 + const __dirname = dirname(fileURLToPath(import.meta.url)); 7 + 8 + export default plugin(function ({ matchComponents, theme }) { 9 + let iconsDir = join(__dirname, "../../node_modules/heroicons"); 10 + let values = {}; 11 + let icons = [ 12 + ["", "/24/outline"], 13 + ["-solid", "/24/solid"], 14 + ["-mini", "/20/solid"], 15 + ["-micro", "/16/solid"], 16 + ]; 17 + icons.forEach(([suffix, dir]) => { 18 + readdirSync(join(iconsDir, dir)).forEach((file) => { 19 + let name = basename(file, ".svg") + suffix; 20 + // @ts-ignore 21 + values[name] = { name, fullPath: join(iconsDir, dir, file) }; 22 + }); 23 + }); 24 + matchComponents( 25 + { 26 + // @ts-ignore 27 + hero: ({ name, fullPath }) => { 28 + let content = readFileSync(fullPath) 29 + .toString() 30 + .replace(/\r?\n|\r/g, ""); 31 + content = encodeURIComponent(content); 32 + let size = theme("spacing.6"); 33 + if (name.endsWith("-mini")) { 34 + size = theme("spacing.5"); 35 + } else if (name.endsWith("-micro")) { 36 + size = theme("spacing.4"); 37 + } 38 + return { 39 + [`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`, 40 + "-webkit-mask": `var(--hero-${name})`, 41 + mask: `var(--hero-${name})`, 42 + }; 43 + }, 44 + }, 45 + // @ts-ignore 46 + { values }, 47 + ); 48 + });
+7 -1
web/package-lock.json
··· 4 4 "requires": true, 5 5 "packages": { 6 6 "": { 7 - "name": "web", 8 7 "dependencies": { 9 8 "@inertiajs/svelte": "2.3.8", 9 + "heroicons": "^2.2.0", 10 10 "svelte": "^5.46.3", 11 11 "tailwindcss": "^4.1.18" 12 12 }, ··· 1581 1581 "engines": { 1582 1582 "node": ">= 0.4" 1583 1583 } 1584 + }, 1585 + "node_modules/heroicons": { 1586 + "version": "2.2.0", 1587 + "resolved": "https://registry.npmjs.org/heroicons/-/heroicons-2.2.0.tgz", 1588 + "integrity": "sha512-yOwvztmNiBWqR946t+JdgZmyzEmnRMC2nxvHFC90bF1SUttwB6yJKYeme1JeEcBfobdOs827nCyiWBS2z/brog==", 1589 + "license": "MIT" 1584 1590 }, 1585 1591 "node_modules/is-extglob": { 1586 1592 "version": "2.1.1",
+1
web/package.json
··· 10 10 }, 11 11 "dependencies": { 12 12 "@inertiajs/svelte": "2.3.8", 13 + "heroicons": "^2.2.0", 13 14 "svelte": "^5.46.3", 14 15 "tailwindcss": "^4.1.18" 15 16 },
+10
web/styles/app.css
··· 5 5 @import "tailwindcss/utilities.css" layer(utilities); 6 6 7 7 @plugin "@tailwindcss/forms"; 8 + @plugin "../lib/plugins/heroicons.plugin.js"; 8 9 9 10 @import "./colors.css" layer(theme); 10 11 @import "./button.css" layer(components); ··· 98 99 --color-danger: var(--theme-color-danger); 99 100 --color-danger-contrast: var(--theme-color-danger-contrast); 100 101 } 102 + 103 + .icon { 104 + mask-repeat: no-repeat; 105 + background-color: currentColor; 106 + vertical-align: middle; 107 + display: inline-block; 108 + width: var(--spacing-4); 109 + height: var(--spacing-4); 110 + }