Skip to main content

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

PropertyValue
StyleStroke-based (default) / Filled (active/selected states)
Stroke weight1.5px at 24px base size, scales proportionally
Base size24×24px
Corner radius1px — slightly humanist, never mechanically sharp
ScalingProportional to user's text size setting

State Behavior

StateTreatment
DefaultLine/stroke style
Active / SelectedFilled style — clear affordance for state change
Disabled40% opacity

Lucide Base Library

GospeLib uses lucide-react-native as the foundation for general-purpose icons.

PropertyDetail
Packagelucide-react-native
LicenseISC (open-source, permissive)
Icon count1 500+ and growing
DesignConsistent stroke-based, 24×24 grid
Tree-shakeableYes — only imported icons are bundled
PlatformCross-platform via React Native (web, iOS, Android)
MaintenanceActive 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 TokenPixel ValueLucide size
sm1616
md (default)2424
lg3232

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 filled prop on the wrapper applies fill="currentColor" and reduces strokeWidth to 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

tip

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.

Why this works

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

AttributeStroke variantFilled variant
viewBox0 0 24 240 0 24 24
width / height2424
strokecurrentColorcurrentColor
stroke-width1.50.5
fillnonecurrentColor
stroke-linecaproundround
stroke-linejoinroundround

File naming and location

VariantFilenamePath
Stroke (default)<icon-name>.svgpackages/ui/src/icons/<icon-name>.svg
Filled (active)<icon-name>-filled.svgpackages/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, or data-* attributes.
  • Do not add fill or stroke attributes 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 via GlIcon's size prop.

Bespoke Icon Validation Checklist

caution

This checklist applies to bespoke icons only. Lucide icons need no validation — they are used as components.

#CheckPass
1Root <svg> attributes match the spec table above exactly
2No fill, stroke, class, or id attributes on child elements
3File is a single minified line
4Filename is kebab-case, with -filled suffix for filled variants
5File is in packages/ui/src/icons/
6Visually compared against Lucide icons at 16px, 24px, and 32px
7Renders correctly with color: #3D5A7A (Navy 500) and color: #1F3046 (Navy 700)

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-ot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

corpus-nt — New Testament Alpha-Omega

Greek alpha-omega arc.

corpus-nt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

corpus-bom — Book of Mormon Plates

Plates with stylized reformed Egyptian mark.

corpus-bom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

corpus-dc — Doctrine & Covenants

Radiant circle (Urim and Thummim inspiration).

corpus-dc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

corpus-pogp — Pearl of Great Price

Stars/pearl cluster.

corpus-pogp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

interlinear — Interlinear Text

Stacked text lines with emerging Hebrew letter.

interlinear
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

witness — Manuscript Witness

Manuscript page with variant marking.

witness
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

graph-node — Knowledge Graph

Node-and-edge constellation symbol.

graph-node
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

strong-number — Strong's Number

H/G superscript with circular badge.

strong-number
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

word-journey — Word Journey

Path between two open books.

word-journey
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

Simple stylized spire (geometric, non-denominational).

temple-link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

reader — Reader

Open book.

reader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

explore — Explore

Radial lines from center (constellation).

explore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

study — Study

Pencil + bookmark combined.

study
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
15 design variations — select one for production

Icon + Label Rule

important

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:

SizeDimensionUsage
Small16×16pxInline badges, metadata
Standard24×24pxNavigation, tool strips
Large32×32pxFeature icons, empty states

Touch target remains minimum 44×44px regardless of icon visual size — see Accessibility.