Bear: Escritura Centrada en Tipografía

Cómo el diseño tipografía primero de Bear ganó Apple Design Awards: etiquetas anidadas, sistema de temas, modo enfoque y Markdown en línea. Con patrones de implementación Swift.

5 min de lectura 978 palabras
Bear: Escritura Centrada en Tipografía screenshot

Bear: Escritura con tipografía como prioridad

«Con Bear sentirás que estás usando un ordenador Apple de nuevo. Sin spinners, sin pantallas de carga skeleton, sin mensajes toast. Solo animaciones fluidas y contenido siempre listo para la acción.»

Bear es una clase magistral en diseño libre de distracciones. Cada decisión, desde la tipografía hasta el sistema de etiquetas, está al servicio de escritores que quieren pensar, no gestionar.


Puntos clave

  1. Cero estados de carga - El contenido siempre está listo; la sincronización ocurre de forma invisible en segundo plano
  2. Las etiquetas reemplazan a las carpetas - Los #tags en línea mientras escribes superan a la gestión de carpetas posterior, y las notas pueden existir en múltiples lugares
  3. Los controles tipográficos respetan al lector - Los controles de fuente, tamaño, interlineado y ancho permiten a los usuarios optimizar para su vista
  4. Tematiza todo a la vez - Más de 28 temas curados superan a los selectores de color fragmentados
  5. Modo enfoque como vía de escape - Cuando lo libre de distracciones necesita ir más lejos, un solo gesto elimina todo

Por qué Bear importa

Bear ganó el Apple Design Award 2017 y múltiples premios Editor's Choice al demostrar que las apps de notas pueden ser potentes y hermosas a la vez.

Logros clave: - Hizo Markdown accesible para no desarrolladores - Inventó las etiquetas anidadas como alternativa flexible a las carpetas - Creó más de 28 temas para diferentes contextos de escritura - Diseñó temas específicos para OLED (Dieci) con negro verdadero - Cero estados de carga: el contenido siempre está listo


Filosofía de diseño central

El principio anti-fricción

Bear elimina cada obstáculo entre el pensamiento y el texto:

PATRONES DE FRICCIÓN (Otras apps)     ENFOQUE DE BEAR
───────────────────────────────────────────────────────────────────
Diálogos de carpeta antes de crear    Solo empieza a escribir
Barras de formato bloqueando la vista Markdown en línea, invisible
Spinners de sincronización            Sincronización en segundo plano, sin indicadores
Ajustes dispersos en menús            Tipografía siempre al alcance
Selectores de color para resaltar     Los temas cambian todo a la vez

Idea clave: Cada elemento de la interfaz es una interrupción potencial. Elimina tantos como sea posible.


Biblioteca de patrones

1. Etiquetas anidadas infinitas

El sistema de etiquetas de Bear reemplaza las jerarquías rígidas de carpetas con una organización flexible e integrada en el texto.

Carpetas tradicionales vs etiquetas de Bear:

ENFOQUE DE CARPETAS                   ENFOQUE DE ETIQUETAS DE BEAR
───────────────────────────────────────────────────────────────────
📁 Work                               La nota contiene: #work/meetings
├── 📁 Meetings                       La nota contiene: #work/meetings/q1
│   ├── 📁 Q1
│   │   └── standup-2025-01.md       Una nota puede tener MÚLTIPLES etiquetas:
│   └── 📁 Q2                         #work/meetings #action-items #q1
└── 📁 Projects

Ubicación única                       Múltiples ubicaciones (virtuales)
Mover = operación de archivo          Etiquetar = solo escríbelo
Visible en el explorador de archivos  Visible en la barra lateral + cuerpo de la nota

Sintaxis de etiquetas:

Etiqueta simple:     #ideas
Etiqueta anidada:    #work/meetings/2025
Anidamiento profundo:#journal/2025/01/17

Resultado en la barra lateral:
├─ 📁 work
│   └─ 📁 meetings
│       └─ 📄 2025
├─ 📁 journal
│   └─ 📁 2025
│       └─ 📁 01
│           └─ 📄 17

Idea clave: Las etiquetas se escriben en línea, no se seleccionan desde menús. El acto de escribir crea la organización.


2. Sistema de control tipográfico

Bear ofrece controles tipográficos granulares que otras apps de notas ocultan:

┌─ Ajustes de tipografía ────────────────────────────────────────────┐
│                                                                    │
│  Fuente                                                            │
│  [Avenir Next ▼]        ← Fuentes del sistema + fuentes personalizadas │
│                                                                    │
│  Tamaño                                                            │
│  [─────●────────]  16pt                                           │
│                                                                    │
│  Interlineado                                                      │
│  [────────●─────]  1.6                                            │
│                                                                    │
│  Ancho de línea                                                    │
│  [──●───────────]  Estrecho  ← Ancho óptimo de lectura            │
│                                                                    │
│  Espaciado entre párrafos                                          │
│  [─────●────────]  Medio                                          │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Enfoque de implementación en Swift:

struct TypographySettings: Codable {
    var fontName: String = "Avenir Next"
    var fontSize: CGFloat = 16
    var lineHeightMultiple: CGFloat = 1.6
    var lineWidth: LineWidth = .comfortable
    var paragraphSpacing: CGFloat = 12

    enum LineWidth: String, Codable {
        case narrow = "narrow"      // ~60 characters
        case comfortable = "medium" // ~75 characters
        case wide = "wide"          // Full width
    }
}

// Applied to editor
func applyTypography(_ settings: TypographySettings, to textView: UITextView) {
    let style = NSMutableParagraphStyle()
    style.lineHeightMultiple = settings.lineHeightMultiple
    style.paragraphSpacing = settings.paragraphSpacing

    let attributes: [NSAttributedString.Key: Any] = [
        .font: UIFont(name: settings.fontName, size: settings.fontSize)!,
        .paragraphStyle: style
    ]

    textView.typingAttributes = attributes
}

3. Sistema de temas

Los temas de Bear afectan todo a la vez—nada de selección de colores fragmentada.

Estructura del tema:

struct BearTheme {
    // Background layers
    let sidebarBackground: Color
    let noteListBackground: Color
    let editorBackground: Color

    // Text hierarchy
    let textPrimary: Color
    let textSecondary: Color
    let textMuted: Color

    // Semantic highlights
    let tagColor: Color
    let linkColor: Color
    let codeBackground: Color
    let headingColor: Color

    // Selection and focus
    let selectionColor: Color
    let cursorColor: Color
}

// Example: Red Graphite (default light theme)
let redGraphite = BearTheme(
    sidebarBackground: Color(hex: "#F7F7F7"),
    noteListBackground: Color(hex: "#FFFFFF"),
    editorBackground: Color(hex: "#FFFFFF"),
    textPrimary: Color(hex: "#333333"),
    textSecondary: Color(hex: "#888888"),
    textMuted: Color(hex: "#BBBBBB"),
    tagColor: Color(hex: "#D14C3E"),      // The signature red
    linkColor: Color(hex: "#B44B41"),
    codeBackground: Color(hex: "#F5F5F5"),
    headingColor: Color(hex: "#333333"),
    selectionColor: Color(hex: "#FFE4E1"),
    cursorColor: Color(hex: "#D14C3E")
)

// Example: Dieci (OLED-optimized)
let dieci = BearTheme(
    sidebarBackground: Color(hex: "#000000"),  // True black
    noteListBackground: Color(hex: "#000000"), // True black
    editorBackground: Color(hex: "#000000"),   // True black
    textPrimary: Color(hex: "#FFFFFF"),
    textSecondary: Color(hex: "#888888"),
    textMuted: Color(hex: "#555555"),
    tagColor: Color(hex: "#FF9500"),
    linkColor: Color(hex: "#FF9500"),
    codeBackground: Color(hex: "#1C1C1C"),
    headingColor: Color(hex: "#FFFFFF"),
    selectionColor: Color(hex: "#3A3A3C"),
    cursorColor: Color(hex: "#FF9500")
)

Categorias de temas: - Temas claros: Red Graphite, High Contrast, Solarized Light - Temas oscuros: Dark Graphite, Dracula, Nord - Temas OLED: Dieci, Charcoal (negro puro para ahorro de bateria) - Especiales: Shibuya Jazz, Everforest (ambientacion especifica)


4. Modo de concentracion

El modo de concentracion de Bear elimina todo excepto las palabras; incluso el cursor es sutil.

MODO NORMAL
┌────────┬────────────┬───────────────────────────────────────────┐
│        │            │                                           │
│Barra   │ Lista de   │  Editor                                   │
│lateral │ notas      │                                           │
│        │            │                                           │
│ #work  │  Meeting   │  # Meeting Notes                          │
│ #ideas │  Ideas     │                                           │
│ #books │  Draft     │  Today we discussed...                    │
│        │            │                                           │
└────────┴────────────┴───────────────────────────────────────────┘

MODO DE CONCENTRACION (atajo de teclado o gesto)
┌─────────────────────────────────────────────────────────────────┐
│                                                                 │
│                                                                 │
│                   # Meeting Notes                               │
│                                                                 │
│                   Today we discussed...                         │
│                                                                 │
│                                                                 │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Todo desaparece. Solo quedan las palabras.

Principios de implementacion: - Un solo gesto o atajo lo activa - La animacion es rapida (sin transiciones prolongadas) - El cursor parpadea sutilmente, sin reclamar atencion - Los margenes proporcionan espacio de respiro alrededor del texto


5. TagCons (iconos visuales de etiquetas)

Bear asigna automaticamente iconos a las etiquetas comunes, haciendo la barra lateral facilmente escaneable.

Barra lateral con TagCons:
├─ 💡 ideas
├─ 📚 books
├─ ✏️ writing
├─ 📝 journal
├─ 🏃 fitness
├─ 💼 work
│   ├─ 📅 meetings
│   └─ 📋 projects
└─ 🎯 goals

Logica de asignacion de iconos:

enum TagConCategory {
    static let mappings: [String: String] = [
        "ideas": "💡",
        "books": "📚",
        "reading": "📖",
        "writing": "✏️",
        "journal": "📝",
        "diary": "📓",
        "work": "💼",
        "meetings": "📅",
        "projects": "📋",
        "goals": "🎯",
        "fitness": "🏃",
        "health": "❤️",
        "recipes": "🍳",
        "travel": "✈️",
        "music": "🎵",
        "code": "💻",
    ]

    static func icon(for tag: String) -> String? {
        let normalized = tag.lowercased()
        return mappings[normalized]
    }
}

Idea clave: Los iconos se asignan automaticamente pero son personalizables. Los valores predeterminados inteligentes reducen la friccion de configuracion.


Sistema de diseno visual

Paleta de colores (tema Red Graphite)

extension Color {
    // Signature accent
    static let bearRed = Color(hex: "#D14C3E")

    // Backgrounds
    static let sidebarBg = Color(hex: "#F7F7F7")
    static let editorBg = Color(hex: "#FFFFFF")

    // Text
    static let textPrimary = Color(hex: "#333333")
    static let textSecondary = Color(hex: "#888888")

    // Code blocks
    static let codeBg = Color(hex: "#F5F5F5")
    static let codeText = Color(hex: "#333333")
}

Tipografía

struct BearTypography {
    // Editor fonts
    static let bodyFont = Font.custom("Avenir Next", size: 16)
    static let headingFont = Font.custom("Avenir Next", size: 24).weight(.semibold)
    static let monoFont = Font.custom("SF Mono", size: 14)

    // Line heights
    static let bodyLineHeight: CGFloat = 1.6
    static let headingLineHeight: CGFloat = 1.3

    // Optimal reading width
    static let maxLineWidth: CGFloat = 680  // ~75 characters
}

Filosofía de animación

Sin estados de carga

El principio clave de animación de Bear: el contenido siempre está listo.

// Anti-pattern: Loading spinner
struct LoadingNote: View {
    var body: some View {
        ProgressView()  // Bear NEVER does this
    }
}

// Bear's approach: Optimistic, instant
struct NoteEditor: View {
    @State private var note: Note

    var body: some View {
        TextEditor(text: $note.content)
            .onAppear {
                // Content already available from local cache
                // Sync happens invisibly in background
            }
    }
}

Transiciones suaves de paneles

// Sidebar collapse/expand
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
    sidebarVisible.toggle()
}

// Focus mode transition
withAnimation(.easeInOut(duration: 0.2)) {
    focusMode = true
}

Experiencia Markdown

Vista previa en vivo (estilizado en línea)

Bear renderiza Markdown mientras escribes. No necesita vista dividida.

What you type:              What you see:
───────────────────────────────────────────────────────
# Heading                   Heading (large, bold)

**bold text**               bold text (styled, ** hidden)

- list item                 • list item (bullet rendered)

`code`                      code (monospace, highlighted)

[link](url)                 link (styled, URL hidden)

Concepto de implementación:

class MarkdownTextStorage: NSTextStorage {
    private var backingStore = NSMutableAttributedString()

    override func replaceCharacters(in range: NSRange, with str: String) {
        beginEditing()
        backingStore.replaceCharacters(in: range, with: str)
        edited(.editedCharacters, range: range, changeInLength: str.count - range.length)
        endEditing()
    }

    override func processEditing() {
        super.processEditing()
        applyMarkdownStyling()
    }

    private func applyMarkdownStyling() {
        // Apply styles based on Markdown patterns
        // Hide syntax characters (**, `, #, etc.)
        // Render inline while preserving plain text source
    }
}

Lecciones para nuestro trabajo

1. Cero estados de carga

Si el contenido existe localmente, muéstralo al instante. Sincroniza en segundo plano.

2. Etiquetas > Carpetas

El etiquetado en línea mientras escribes es más rápido que organizar carpetas después.

3. La tipografía es UX

Dar a los usuarios control sobre la fuente, el tamaño, la altura de línea y el ancho demuestra respeto por la lectura.

4. Tematizar todo a la vez

No hagas que los usuarios elijan 12 colores. Ofrece temas completos curados.

5. Modo enfoque como vía de escape

Cuando la experiencia libre de distracciones no es lo suficientemente libre, un solo gesto elimina todo.


Preguntas frecuentes

¿Cómo funcionan las etiquetas anidadas de Bear?

Escribe #parent/child/grandchild en cualquier parte de una nota. Bear crea automáticamente la jerarquía en la barra lateral. A diferencia de las carpetas, una nota puede tener múltiples etiquetas, ubicándola en múltiples “lugares” simultáneamente. Las etiquetas se crean al escribirlas, no navegando por menús.

¿Por qué Bear usa temas en lugar de ajustes de color individuales?

Los temas garantizan coherencia visual. Cuando los usuarios eligen colores individualmente, a menudo crean combinaciones con poco contraste o tonos que chocan entre sí. Los más de 28 temas curados de Bear garantizan esquemas de color legibles y estéticamente consistentes en todos los elementos de la interfaz.

¿Qué diferencia el Markdown de Bear de otros editores?

Bear renderiza Markdown en línea mientras escribes. Los caracteres de sintaxis (**, #, backticks) se ocultan después de escribirlos, mostrando solo el resultado con estilo. Ves la apariencia final mientras editas, sin necesidad de un panel de vista previa separado.

¿Cómo logra Bear cero estados de carga?

Bear almacena todo el contenido localmente y lo carga desde la caché instantáneamente. La sincronización con iCloud ocurre en segundo plano sin spinners ni indicadores de progreso. Si abres Bear sin conexión, todo funciona. La sincronización se completa silenciosamente cuando la conexión regresa.

¿Puedo exportar mis notas de Bear a otros formatos?

Bear exporta a Markdown, PDF, HTML, DOCX y texto plano. Las notas conservan su código fuente Markdown, así que tú eres dueño de tus datos. El sistema de etiquetas se exporta como frontmatter o estructura de archivos dependiendo del formato.