Iconography
GospeLib uses a custom icon set built on top of lucide-react-native as its base icon library. Lucide provides general-purpose UI icons (search, settings, navigation), while GospeLib adds bespoke scripture-specific icons that don't exist in any general library. All icons — Lucide-sourced and bespoke — share the same visual language after customization: humanist, warm, and consistent with the app's paper-and-ink aesthetic.
Icon System Properties
| Property | Value |
|---|---|
| Style | Stroke-based (default) / Filled (active/selected states) |
| Stroke weight | 1.5px at 24px base size, scales proportionally |
| Base size | 24×24px |
| Corner radius | 1px — slightly humanist, never mechanically sharp |
| Scaling | Proportional to user's text size setting |
State Behavior
| State | Treatment |
|---|---|
| Default | Line/stroke style |
| Active / Selected | Filled style — clear affordance for state change |
| Disabled | 40% opacity |
Lucide Base Library
GospeLib uses lucide-react-native as the foundation for general-purpose icons.
| Property | Detail |
|---|---|
| Package | lucide-react-native |
| License | ISC (open-source, permissive) |
| Icon count | 1 500+ and growing |
| Design | Consistent stroke-based, 24×24 grid |
| Tree-shakeable | Yes — only imported icons are bundled |
| Platform | Cross-platform via React Native (web, iOS, Android) |
| Maintenance | Active community, regular releases |
What comes from Lucide
General UI icons: navigation (chevrons, arrows, menus), actions (copy, share, download, trash), status indicators (check, alert, info), media controls (play, pause), and editor tools (bold, italic, list).
What remains fully custom
All scripture-specific bespoke icons listed in the Bespoke Icon Gallery section below — these concepts don't exist in any general icon library.
Customizing Lucide Icons for GospeLib
Lucide icons ship with sensible defaults, but they must be customized to match GospeLib's visual language. This section documents every alteration and shows how to implement them via a wrapper component.
Stroke Weight
Lucide defaults to 2px stroke. GospeLib uses 1.5px at the 24px base size — configured via the strokeWidth prop.
The thinner stroke gives a more refined, scholarly feel that aligns with the paper-and-ink aesthetic. It also reduces visual weight so icons recede behind content rather than competing with scripture text.
Corner Radius
Lucide defaults to sharp corners. GospeLib applies a subtle 1px corner radius to all icon paths for a humanist, warm feel.
This is not a Lucide prop. Achieve it by setting strokeLinejoin="round" and strokeLinecap="round" on the wrapper component — these SVG attributes round the joins and endpoints of every stroke path.
Size Tokens
Lucide uses a size prop (number). GospeLib wraps this to respect the design-system sizing tokens and scale proportionally with the user's text size setting:
| GospeLib Token | Pixel Value | Lucide size |
|---|---|---|
sm | 16 | 16 |
md (default) | 24 | 24 |
lg | 32 | 32 |
Color
Icons inherit color from the current text color by default (currentColor). The wrapper preserves this default and additionally allows corpus-specific color overrides from the color system.
Active / Selected States
Lucide only ships stroke variants. For filled active states, GospeLib must provide filled versions:
- A
filledprop on the wrapper appliesfill="currentColor"and reducesstrokeWidthto 0.5px so the fill dominates. - For the most common navigation icons (reader, explore, study), maintain a parallel set of filled SVGs.
Disabled State
40% opacity applied at the wrapper level — never per-icon. This keeps disabled treatment consistent and overridable from one place.
Wrapper Component Pattern
This is an illustrative sketch — not production code. The real component lives in @gospelib/ui.
import type { FC } from 'react';
import { type LucideIcon } from 'lucide-react-native';
interface IconProps {
/** A Lucide icon component, e.g. `Search` from lucide-react-native */
icon: LucideIcon;
/** GospeLib size token */
size?: 'sm' | 'md' | 'lg';
/** Render the filled active variant */
filled?: boolean;
/** Dim to 40 % opacity */
disabled?: boolean;
/** Override color — defaults to currentColor */
color?: string;
}
const SIZE_MAP = { sm: 16, md: 24, lg: 32 } as const;
export const GlIcon: FC<IconProps> = ({
icon: LucideComponent,
size = 'md',
filled = false,
disabled = false,
color = 'currentColor',
}) => (
<LucideComponent
size={SIZE_MAP[size]}
color={color}
strokeWidth={filled ? 0.5 : 1.5}
fill={filled ? color : 'none'}
strokeLinejoin="round"
strokeLinecap="round"
opacity={disabled ? 0.4 : 1}
/>
);
Using Icons in GospeLib
Lucide Icons — No SVG Modification Needed
GospeLib uses lucide-react-native, which provides every Lucide icon as a React Native component. All GospeLib customizations — stroke width, fill, size, line caps — are applied at runtime via props on the GlIcon wrapper (see Wrapper Component Pattern above). No SVG files are downloaded, modified, or stored for Lucide icons.
Lucide components accept strokeWidth, fill, strokeLinecap, strokeLinejoin, and size as props. GlIcon passes the exact values from the design spec (strokeWidth={1.5}, strokeLinecap="round", etc.) automatically. There is nothing to manually prepare.
To use a Lucide icon, import the component and pass it to GlIcon:
import { Search } from 'lucide-react-native';
import { GlIcon } from '@gospelib/ui';
<GlIcon icon={Search} size="md" />
<GlIcon icon={Search} size="md" filled />
Bespoke Icon Authoring Conventions
Icons that don't exist in Lucide — the scripture-specific icons and 3 custom navigation icons (reader, explore, study) — require hand-authored SVGs. These must visually match Lucide icons as rendered through GlIcon.
SVG attribute spec
| Attribute | Stroke variant | Filled variant |
|---|---|---|
viewBox | 0 0 24 24 | 0 0 24 24 |
width / height | 24 | 24 |
stroke | currentColor | currentColor |
stroke-width | 1.5 | 0.5 |
fill | none | currentColor |
stroke-linecap | round | round |
stroke-linejoin | round | round |
File naming and location
| Variant | Filename | Path |
|---|---|---|
| Stroke (default) | <icon-name>.svg | packages/ui/src/icons/<icon-name>.svg |
| Filled (active) | <icon-name>-filled.svg | packages/ui/src/icons/<icon-name>-filled.svg |
Names are kebab-case. Examples: corpus-ot.svg, corpus-ot-filled.svg.
Additional rules
- Minify to a single line — no newlines or leading/trailing whitespace.
- Do not add
class,id, ordata-*attributes. - Do not add
fillorstrokeattributes to child elements — inherit from root. - Author at the 24×24 base size only. Size variants (
sm=16,md=24,lg=32) are rendered at runtime viaGlIcon'ssizeprop.
Bespoke Icon Validation Checklist
This checklist applies to bespoke icons only. Lucide icons need no validation — they are used as components.
| # | Check | Pass |
|---|---|---|
| 1 | Root <svg> attributes match the spec table above exactly | ☐ |
| 2 | No fill, stroke, class, or id attributes on child elements | ☐ |
| 3 | File is a single minified line | ☐ |
| 4 | Filename is kebab-case, with -filled suffix for filled variants | ☐ |
| 5 | File is in packages/ui/src/icons/ | ☐ |
| 6 | Visually compared against Lucide icons at 16px, 24px, and 32px | ☐ |
| 7 | Renders correctly with color: #3D5A7A (Navy 500) and color: #1F3046 (Navy 700) | ☐ |
Bespoke Icon Gallery
This gallery shows 15 design variations for each bespoke icon. These are concepts for design review — the team will select one variation per icon for production use.
Scripture Icons
corpus-ot — Old Testament Scroll
Open scroll with stylized shin (ש) letterform.
corpus-nt — New Testament Alpha-Omega
Greek alpha-omega arc.
corpus-bom — Book of Mormon Plates
Plates with stylized reformed Egyptian mark.
corpus-dc — Doctrine & Covenants
Radiant circle (Urim and Thummim inspiration).
corpus-pogp — Pearl of Great Price
Stars/pearl cluster.
interlinear — Interlinear Text
Stacked text lines with emerging Hebrew letter.
witness — Manuscript Witness
Manuscript page with variant marking.
graph-node — Knowledge Graph
Node-and-edge constellation symbol.
strong-number — Strong's Number
H/G superscript with circular badge.
word-journey — Word Journey
Path between two open books.
temple-link — Temple Link
Simple stylized spire (geometric, non-denominational).
Navigation Icons
reader — Reader
Open book.
explore — Explore
Radial lines from center (constellation).
study — Study
Pencil + bookmark combined.
Icon + Label Rule
Icons are never shown without a label in primary navigation.
In dense tool panels and action rings, icons may appear without labels when the context is self-evident and space is constrained — but a long-press or hover always surfaces the label as a tooltip.
Sizing
Icons scale proportionally with the user's text size setting. At the base 24px size:
| Size | Dimension | Usage |
|---|---|---|
| Small | 16×16px | Inline badges, metadata |
| Standard | 24×24px | Navigation, tool strips |
| Large | 32×32px | Feature icons, empty states |
Touch target remains minimum 44×44px regardless of icon visual size — see Accessibility.
Related Pages
- Colors — corpus identity colors used in corpus icons
- Navigation & Layout — icon placement in tab bar and side rail
- Accessibility — icon scaling and touch target requirements
- Design Tokens —
layout.touchTargetMin: 44