files/simple.ex
File card
A single file card with a page icon, the file name, its type and size, and a line about where it came from.
# in the module that renders the template
use EHVisuals
<div class="h-96 rounded-xl border border-border">
<.files_simple animated />
</div>
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
name |
string | "Northwind-4471.pdf" |
Up to 28 characters. |
type |
string | "PDF" |
The badge on the page. Up to 5 characters. |
size |
string | "248 KB" |
|
note |
string | "Added by the intake agent · 09:12" |
The line under the type and size. Up to 44 characters. |
Frame props, shared by every composition
| Prop | Type | Default | What it does |
|---|---|---|---|
animated |
boolean | false |
Turns motion on. Without it the composition renders in its final, still state. |
trigger |
"mount" | "in-view" | "in-view-repeat" | "in-view" |
When the entrance plays: on page load, once when scrolled into view, or every time it comes back into view. |
hover |
boolean | false |
Enables the hover micro-interactions the composition supports. |
glow |
boolean | true |
The warm incandescent halo behind the composition. |
fade_out |
boolean | false |
Fades the bottom edge into the surface underneath. |
isometric |
boolean | false |
Tilts the composition into the isometric plane of the platform stack. |
theme |
"dark" | "light" | "dark" |
`dark` for the site canvas, `light` for the cream reversed surface. |
class |
string | nil |
Extra classes for the frame. |
rest |
global | — |
Any other HTML attribute, set on the frame. |
Source
Two files. Copy them into your app if you would rather own the code than depend on the library.
lib/eh_visuals/files/simple.ex
defmodule EHVisuals.Files.Simple do
@moduledoc """
One file as a card: a page icon with its type, the file name, the type and
size, and a line about where it came from.
"""
use EHVisuals.Composition,
name: "files/simple",
title: "File card",
description:
"A single file card with a page icon, the file name, its type and size, and a line about where it came from."
@bone_widths [26, 42, 42, 34, 42, 30]
attr(:name, :string, default: "Northwind-4471.pdf", doc: "Up to 28 characters.")
attr(:type, :string, default: "PDF", doc: "The badge on the page. Up to 5 characters.")
attr(:size, :string, default: "248 KB")
attr(:note, :string,
default: "Added by the intake agent · 09:12",
doc: "The line under the type and size. Up to 44 characters."
)
attr(:label, :string, default: "A file card for a PDF invoice with its name, type and size")
frame_attrs()
@spec files_simple(map()) :: Phoenix.LiveView.Rendered.t()
def files_simple(assigns) do
badge_w = Float.round(14 + String.length(assigns.type) * 5.6, 1)
assigns =
assigns
|> assign(:badge_w, badge_w)
|> assign(:badge_x, Float.round(188 - badge_w, 1))
|> assign(:bones, Enum.with_index(@bone_widths))
|> assign(:meta, "#{assigns.type} · #{assigns.size}")
~H"""
<.frame name="files/simple" label={@label} {frame_opts(assigns)}>
<svg viewBox="0 0 300 206">
<g class="ehv-h-lift">
<rect class="ehv-card ehv-a-rise" x="0.5" y="0.5" width="299" height="205" rx="12" />
<rect class="ehv-well ehv-a-fade ehv-i-1" x="12.5" y="12.5" width="275" height="110" rx="8" />
<g class="ehv-a-rise ehv-i-2">
<g class="ehv-files-simple__page">
<path class="ehv-card-2 ehv-round" d="M120.5 24.5 h44 l15 15 v70 h-59 z" />
<path class="ehv-line ehv-round" d="M164.5 24.5 v15 h15" />
<g :for={{width, index} <- @bones} class={"ehv-a-fade ehv-i-#{index + 3}"}>
<rect
class={[
if(index == 0, do: "ehv-fill-strong", else: "ehv-fill-soft"),
"ehv-a-grow-x",
"ehv-i-#{index + 3}"
]}
x="129"
y={46 + index * 9}
width={width}
height="4"
rx="2"
/>
</g>
<g class="ehv-a-pop ehv-i-8">
<rect class="ehv-fill-lime" x={@badge_x} y="88" width={@badge_w} height="17" rx="5" />
<text
class="ehv-mono ehv-t-on-lime"
x={@badge_x + @badge_w / 2}
y="99.5"
font-size="7.5"
text-anchor="middle"
>
{String.upcase(@type)}
</text>
</g>
</g>
</g>
<g class="ehv-a-fade ehv-i-6">
<text class="ehv-t-strong" x="20" y="150" font-size="14">{@name}</text>
<text class="ehv-mono ehv-t-2" x="20" y="167" font-size="8.5">
{String.upcase(@meta)}
</text>
<text class="ehv-t-3" x="20" y="188" font-size="11">{@note}</text>
</g>
<g class="ehv-a-pop ehv-i-9">
<circle class="ehv-line-soft" cx="266" cy="154" r="13" />
<path
class="ehv-line-ink ehv-round ehv-files-simple__arrow"
d="M266 147.5 v9.5 m-4 -4 l4 4 l4 -4"
/>
<path class="ehv-line-ink ehv-round" d="M260.5 160.5 h11" />
</g>
</g>
</svg>
</.frame>
"""
end
end
assets/css/files/simple.css
/* files/simple */
.ehv-files-simple { --ehv-max-w: 340px; }
/* On hover the page lifts off its well and the download arrow dips. */
.ehv-files-simple__page,
.ehv-files-simple__arrow { transform-box: fill-box; }
.ehv--hover :is(.ehv-files-simple__page, .ehv-files-simple__arrow) { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-files-simple__page { transform: translateY(-3px); }
.ehv--hover:hover .ehv-files-simple__arrow { transform: translateY(1.5px); }