diff --git a/packages/preview/nametags/0.1.0/.gitignore b/packages/preview/nametags/0.1.0/.gitignore new file mode 100644 index 0000000000..938fec3a5b --- /dev/null +++ b/packages/preview/nametags/0.1.0/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +*.pdf diff --git a/packages/preview/nametags/0.1.0/LICENSE b/packages/preview/nametags/0.1.0/LICENSE new file mode 100644 index 0000000000..025f1491ba --- /dev/null +++ b/packages/preview/nametags/0.1.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Cameron Wimpy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/preview/nametags/0.1.0/README.md b/packages/preview/nametags/0.1.0/README.md new file mode 100644 index 0000000000..b0b7de2fe9 --- /dev/null +++ b/packages/preview/nametags/0.1.0/README.md @@ -0,0 +1,114 @@ +# nametags + +Conference nametag badges (4 × 3 in lanyard inserts) and table tents (tabloid landscape, folded to 11 × 4.25 in) — pure Typst, driven from any CSV or array. + +## Install + +From Typst Universe (after the package is published): + +```typst +#import "@preview/nametags:0.1.0": nametag, nametent +``` + +Or use a local checkout: + +```typst +#import "/path/to/nametags-package/lib.typ": nametag, nametent +``` + +## Quick start — badges + +`badges.typ`: + +```typst +#import "@preview/nametags:0.1.0": nametag + +#let rows = csv("attendees.csv").slice(1) // drop header row +#let left-logo = read("logo-left.png", encoding: none) // your logo +#let right-logo = read("logo-right.png", encoding: none) // your logo + +#for row in rows { + let (first, last, dept, inst) = row + nametag( + name: first + " " + last, + affiliation: inst, + subaffiliation: dept, + conference: "Annual Research Symposium", + year: "2026", + logo-left: left-logo, + logo-right: right-logo, + ) +} +``` + +`attendees.csv`: + +```csv +First,Last,Affil1,Affil2 +Jane,Doe,Department of Sociology,Example State University +John,Smith,School of Public Affairs,Riverside College +``` + +Then: + +```bash +typst compile badges.typ +``` + +You'll get one 4 × 3 in page per attendee. + +## Quick start — tents + +```typst +#import "@preview/nametags:0.1.0": nametent + +#let rows = csv("attendees.csv").slice(1) +#let left-logo = read("logo-left.png", encoding: none) // your logo +#let right-logo = read("logo-right.png", encoding: none) // your logo + +#for row in rows { + let (first, last, _, inst) = row + nametent( + name: first + " " + last, + affiliation: inst, + conference: "Annual Research Symposium", + year: "2026", + logo-left: left-logo, + logo-right: right-logo, + ) +} +``` + +Print on tabloid (11 × 17), trim or fold to 11 × 8.5, then fold along the horizontal center. The top half is rotated 180° so both sides read upright when standing on a table. + +## API + +### `nametag(name, affiliation, subaffiliation, conference, year, accent-color, logo-left, logo-right)` + +Renders a single 4 × 3 in badge as one page. + +| Parameter | Type | Default | Notes | +|----------:|------|---------|-------| +| `name` | str | `""` | Attendee's full name | +| `affiliation` | str | `""` | Primary line — typically institution | +| `subaffiliation` | str | `""` | Secondary line — typically department or title; omitted if empty | +| `conference` | str | `"Annual Research Symposium"` | Shown in the header bar, uppercased | +| `year` | str | `"2026"` | Right side of header bar | +| `accent-color` | color | `rgb("#0d3b66")` | Header-year accent and rule under name | +| `logo-left` | bytes \| none | `none` | Footer logo, left side. Pass `read("logo.png", encoding: none)` | +| `logo-right` | bytes \| none | `none` | Footer logo, right side | + +### `nametent(name, affiliation, conference, year, accent-color, logo-left, logo-right)` + +Renders a single tabloid landscape page that folds into a tent. Same parameter conventions as `nametag` but no `subaffiliation`. Name size is auto-selected (52 / 60 / 68 pt) by character count to keep names on one line. + +## Notes + +- **Logos are bytes, not paths.** Typst resolves `image()` paths relative to the file containing the call, so passing a path string into a packaged function won't find a file in your project. Loading the bytes once with `read()` and handing them in sidesteps this. +- **Example logos are placeholders.** `examples/logo-left.png` and `examples/logo-right.png` are simple wordmarks generated for the demo. Replace them with your own. +- **Fonts.** Both functions default to "Industry Inc Test Base" (headings) and "Oriya MN" (body), with Impact / Times New Roman as fallbacks. Edit the `heading-font` and `body-font` lists at the top of `nametag.typ` / `nametent.typ` to swap. +- **Quarto users.** A Quarto-driven version of this template lives at [`cwimpy/typst-templates/nametags`](https://github.com/cwimpy/typst-templates/tree/main/nametags), with an R chunk that reads the CSV and emits Typst calls. + +## License + +MIT diff --git a/packages/preview/nametags/0.1.0/examples/attendees.csv b/packages/preview/nametags/0.1.0/examples/attendees.csv new file mode 100644 index 0000000000..0bb9e8722d --- /dev/null +++ b/packages/preview/nametags/0.1.0/examples/attendees.csv @@ -0,0 +1,5 @@ +First,Last,Affil1,Affil2 +Jane,Doe,Department of Sociology,Example State University +John,Smith,School of Public Affairs,Riverside College +Alex,Rivera,Department of Political Science,Midwestern University +Sam,Chen,Institute for Policy Research,Coastal University diff --git a/packages/preview/nametags/0.1.0/examples/badges.typ b/packages/preview/nametags/0.1.0/examples/badges.typ new file mode 100644 index 0000000000..071b18b8e5 --- /dev/null +++ b/packages/preview/nametags/0.1.0/examples/badges.typ @@ -0,0 +1,26 @@ +// Render one 4x3 in badge per row of attendees.csv. +// +// From Typst Universe: +// #import "@preview/nametags:0.1.0": nametag +// From a local checkout: +#import "../lib.typ": nametag + +// CSV columns: First, Last, Affil1 (department), Affil2 (institution) +#let rows = csv("attendees.csv").slice(1) // drop header row + +// Load logos once as bytes; the package re-uses them on every page. +#let left-logo = read("logo-left.png", encoding: none) +#let right-logo = read("logo-right.png", encoding: none) + +#for row in rows { + let (first, last, affil1, affil2) = row + nametag( + name: first + " " + last, + affiliation: affil2, + subaffiliation: affil1, + conference: "Annual Research Symposium", + year: "2026", + logo-left: left-logo, + logo-right: right-logo, + ) +} diff --git a/packages/preview/nametags/0.1.0/examples/logo-left.png b/packages/preview/nametags/0.1.0/examples/logo-left.png new file mode 100644 index 0000000000..d9ea01a31a Binary files /dev/null and b/packages/preview/nametags/0.1.0/examples/logo-left.png differ diff --git a/packages/preview/nametags/0.1.0/examples/logo-right.png b/packages/preview/nametags/0.1.0/examples/logo-right.png new file mode 100644 index 0000000000..bbb123776c Binary files /dev/null and b/packages/preview/nametags/0.1.0/examples/logo-right.png differ diff --git a/packages/preview/nametags/0.1.0/examples/tents.typ b/packages/preview/nametags/0.1.0/examples/tents.typ new file mode 100644 index 0000000000..787ef50d3a --- /dev/null +++ b/packages/preview/nametags/0.1.0/examples/tents.typ @@ -0,0 +1,25 @@ +// Render one folded table tent per row of attendees.csv. +// Print on tabloid (11 x 17), trim to 11 x 8.5 if needed, fold along the +// horizontal center. +// +// From Typst Universe: +// #import "@preview/nametags:0.1.0": nametent +// From a local checkout: +#import "../lib.typ": nametent + +#let rows = csv("attendees.csv").slice(1) // drop header row + +#let left-logo = read("logo-left.png", encoding: none) +#let right-logo = read("logo-right.png", encoding: none) + +#for row in rows { + let (first, last, _, affil2) = row + nametent( + name: first + " " + last, + affiliation: affil2, + conference: "Annual Research Symposium", + year: "2026", + logo-left: left-logo, + logo-right: right-logo, + ) +} diff --git a/packages/preview/nametags/0.1.0/lib.typ b/packages/preview/nametags/0.1.0/lib.typ new file mode 100644 index 0000000000..0164a9d6e2 --- /dev/null +++ b/packages/preview/nametags/0.1.0/lib.typ @@ -0,0 +1,5 @@ +// nametags — Typst package entry point +// Re-exports the two layout functions. + +#import "nametag.typ": nametag +#import "nametent.typ": nametent diff --git a/packages/preview/nametags/0.1.0/nametag.typ b/packages/preview/nametags/0.1.0/nametag.typ new file mode 100644 index 0000000000..57514a4304 --- /dev/null +++ b/packages/preview/nametags/0.1.0/nametag.typ @@ -0,0 +1,123 @@ +// nametag.typ — single 4x3 in conference badge +// +// Each call sets the page to 4 x 3 in and renders one badge. Call once +// per attendee — Typst will start a new page for each. +// +// Logos are passed as bytes (e.g. `read("iri.png")`) so paths resolve +// relative to the *calling* file, not this package. + +#let nametag( + name: "", + affiliation: "", + subaffiliation: "", + conference: "Annual Research Symposium", + year: "2026", + accent-color: rgb("#0d3b66"), + logo-left: none, + logo-right: none, +) = { + // ---- Design tokens ---- + let ink = rgb("#000000") + let muted = rgb("#555555") + let faint = rgb("#777777") + let hairline = rgb("#e5e5e5") + + // Font fallbacks let this render on machines without the licensed + // fonts (CI, collaborators, Universe sandbox). + let heading-font = ("Industry Inc Test Base", "Industry Inc", "Industry", "Impact") + let body-font = ("Oriya MN", "Oriya Sangam MN", "Times New Roman") + + // ---- Page = the badge itself ---- + set page( + width: 4in, + height: 3in, + margin: 0pt, + fill: white, + ) + + // ---- Outer frame: a 3-row grid (header / body / footer) ---- + block( + width: 100%, + height: 100%, + stroke: 0.5pt + hairline, + radius: 6pt, + clip: true, + { + grid( + columns: 1, + rows: (auto, 1fr, auto), + + // ---- Header bar ---- + block( + width: 100%, + fill: ink, + inset: (x: 14pt, y: 9pt), + grid( + columns: (1fr, auto), + align: (left + horizon, right + horizon), + text( + font: heading-font, + size: 10pt, + fill: white, + tracking: 0.6pt, + upper(conference), + ), + text( + font: heading-font, + size: 10pt, + fill: accent-color, + year, + ), + ), + ), + + // ---- Body (fills remaining vertical space) ---- + block( + width: 100%, + height: 100%, + inset: (x: 18pt, y: 14pt), + align(center + horizon)[ + #text( + font: body-font, + weight: "bold", + size: 26pt, + fill: ink, + )[#name] + #v(4pt) + #box(width: 56pt, height: 4pt, fill: accent-color) + #v(14pt) + #text(font: body-font, size: 13pt, fill: rgb("#333333"))[#affiliation] + #if subaffiliation != "" [ + #v(3pt) + #block( + width: 90%, + text( + font: body-font, + size: 11pt, + fill: faint, + )[#subaffiliation], + ) + ] + ], + ), + + // ---- Footer with logos ---- + block( + width: 100%, + stroke: (top: 0.5pt + hairline), + inset: (x: 14pt, y: 6pt), + grid( + columns: (1fr, 1fr), + align: (left + horizon, right + horizon), + if logo-left != none { + image(logo-left, height: 24pt, fit: "contain") + } else { [] }, + if logo-right != none { + image(logo-right, height: 24pt, fit: "contain") + } else { [] }, + ), + ), + ) + }, + ) +} diff --git a/packages/preview/nametags/0.1.0/nametent.typ b/packages/preview/nametags/0.1.0/nametent.typ new file mode 100644 index 0000000000..bb76b93919 --- /dev/null +++ b/packages/preview/nametags/0.1.0/nametent.typ @@ -0,0 +1,124 @@ +// nametent.typ — folded table tent +// +// Tabloid landscape (11 x 8.5) folded along the horizontal center +// becomes an 11 x 4.25 tent. The top half is rotated 180° so both +// sides read upright after folding. +// +// Logos are passed as bytes (e.g. `read("iri.png")`) so paths resolve +// relative to the *calling* file, not this package. + +#let nametent( + name: "", + affiliation: "", + conference: "Annual Research Symposium", + year: "2026", + accent-color: rgb("#0d3b66"), + logo-left: none, + logo-right: none, +) = { + // ---- Design tokens ---- + let ink = rgb("#000000") + let hairline = rgb("#e5e5e5") + let heading-font = ("Industry Inc Test Base", "Industry Inc", "Industry", "Impact") + let body-font = ("Oriya MN", "Oriya Sangam MN", "Times New Roman") + + // Pick a name size that keeps the longest name on one line. + let name-size = if name.len() > 16 { + 52pt + } else if name.len() > 12 { + 60pt + } else { + 68pt + } + + // ---- Reusable single-panel layout (one half of the folded sheet) ---- + let panel = block( + width: 11in, + height: 4.25in, + fill: white, + grid( + columns: 1, + rows: (auto, 1fr), + row-gutter: 0pt, + + // Header bar + block( + width: 100%, + fill: ink, + inset: (x: 28pt, y: 9pt), + grid( + columns: (1fr, auto), + align: (left + horizon, right + horizon), + text( + font: heading-font, + size: 11pt, + fill: white, + tracking: 0.7pt, + upper(conference), + ), + text( + font: heading-font, + size: 11pt, + fill: accent-color, + year, + ), + ), + ), + + // Body — three columns: left logo | name | right logo + block( + width: 100%, + height: 100%, + inset: (x: 32pt, y: 18pt), + grid( + columns: (1.4in, 1fr, 1.4in), + column-gutter: 20pt, + align: (left + horizon, center + horizon, right + horizon), + + if logo-left != none { + image(logo-left, width: 1.4in, fit: "contain") + } else { [] }, + + align(center + horizon)[ + #text( + font: body-font, + weight: "bold", + size: name-size, + fill: ink, + )[#name] + #v(10pt) + #box(width: 96pt, height: 5pt, fill: accent-color) + #if affiliation != "" [ + #v(12pt) + #text( + font: body-font, + size: 22pt, + fill: rgb("#333333"), + )[#affiliation] + ] + ], + + if logo-right != none { + image(logo-right, width: 1.4in, fit: "contain") + } else { [] }, + ), + ), + ), + ) + + // ---- Page setup: tabloid landscape (folds to 11 x 4.25) ---- + set page( + width: 11in, + height: 8.5in, + margin: 0pt, + fill: white, + ) + + grid( + columns: 1, + rows: (4.25in, 4.25in), + row-gutter: 0pt, + rotate(180deg, reflow: true, panel), + panel, + ) +} diff --git a/packages/preview/nametags/0.1.0/typst.toml b/packages/preview/nametags/0.1.0/typst.toml new file mode 100644 index 0000000000..eb3ee1168f --- /dev/null +++ b/packages/preview/nametags/0.1.0/typst.toml @@ -0,0 +1,11 @@ +[package] +name = "nametags" +version = "0.1.0" +entrypoint = "lib.typ" +compiler = "0.12.0" +authors = ["Cameron Wimpy"] +license = "MIT" +description = "Conference nametag badges (4x3 in lanyard) and table tents (folded tabloid), driven from a CSV or any iterable." +repository = "https://github.com/cwimpy/typst-templates/tree/main/nametags-package" +keywords = ["nametag", "badge", "conference", "tent"] +categories = ["office"]