Skip to content

Instantly share code, notes, and snippets.

@mrdotb
Created June 9, 2024 09:01
Show Gist options
  • Save mrdotb/8b78fde7dc3c8e191d1c8a4b90e21b0f to your computer and use it in GitHub Desktop.
Save mrdotb/8b78fde7dc3c8e191d1c8a4b90e21b0f to your computer and use it in GitHub Desktop.
Add lucide components to phoenix
def icon(%{name: "hero-" <> _} = assigns) do
~H"""
<span class={[@name, @class]} />
"""
end
# Add the pattern match fn for lucide
def icon(%{name: "lucide-" <> _} = assigns) do
~H"""
<span class={[@name, @class]} />
"""
end
# Add the lucide repository to mix
{:lucide,
github: "lucide-icons/lucide",
tag: "0.390.0",
sparse: "icons",
app: false,
compile: false,
depth: 1},
const { heroComponent, lucideComponent } = require('./tailwind.icon-components')
// ...
// in plugins add
// heroComponent,
// lucideComponent,
const fs = require('fs')
const path = require('path')
const plugin = require('tailwindcss/plugin')
exports.lucideComponent = plugin(({ matchComponents, theme }) => {
let iconsDir = path.join(__dirname, '../deps/lucide/icons')
const values = fs.readdirSync(iconsDir).reduce((iconsAcc, file) => {
if (file.endsWith('.svg')) {
const name = path.basename(file, '.svg')
iconsAcc[name] = { name, fullPath: path.join(iconsDir, file) }
return iconsAcc
} else {
return iconsAcc
}
}, {})
matchComponents(
{
lucide: ({ name, fullPath }) => {
const content = fs
.readFileSync(fullPath)
.toString()
.replace(/\r?\n|\r/g, '')
// Remove width and height attributes we only need viewBox
.replace('width="24"', '')
.replace('height="24"', '')
let size = theme('spacing.6')
if (name.endsWith('-mini')) {
size = theme('spacing.5')
} else if (name.endsWith('-micro')) {
size = theme('spacing.4')
}
return {
[`--lucide-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
'-webkit-mask': `var(--lucide-${name})`,
mask: `var(--lucide-${name})`,
'background-color': 'currentColor',
'vertical-align': 'middle',
display: 'inline-block',
width: size,
height: size,
}
},
},
{ values },
)
})
// Embeds Hero Icons (https://heroicons.com) into your app.css bundle
// See your `CoreComponents.icon/1` for more information.
exports.heroComponent = plugin(({ matchComponents, theme }) => {
let iconsDir = path.join(__dirname, '../deps/heroicons/optimized')
const icons = [
['', '/24/outline'],
['-solid', '/24/solid'],
['-mini', '/20/solid'],
['-micro', '/16/solid'],
]
const values = icons.reduce(
(acc, [suffix, dir]) =>
fs.readdirSync(path.join(iconsDir, dir)).reduce((iconsAcc, file) => {
const name = path.basename(file, '.svg') + suffix
iconsAcc[name] = { name, fullPath: path.join(iconsDir, dir, file) }
return iconsAcc
}, acc),
{},
)
matchComponents(
{
hero: ({ name, fullPath }) => {
const content = fs
.readFileSync(fullPath)
.toString()
.replace(/\r?\n|\r/g, '')
let size = theme('spacing.6')
if (name.endsWith('-mini')) {
size = theme('spacing.5')
} else if (name.endsWith('-micro')) {
size = theme('spacing.4')
}
return {
[`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
'-webkit-mask': `var(--hero-${name})`,
mask: `var(--hero-${name})`,
'background-color': 'currentColor',
'vertical-align': 'middle',
display: 'inline-block',
width: size,
height: size,
}
},
},
{ values },
)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment