本文へ移動
cccskills
無料GitHub で公開

text-editing

Styled text display and rich text editing in SwiftUI using Text, AttributedString, and TextEditor with formatting controls. Use when implementing rich text editing or styled text display.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md8.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Styled Text Editing

Patterns for displaying styled text and building rich text editors in SwiftUI. Covers Text styling, AttributedString, TextEditor with selection-based formatting, and custom formatting definitions.

When This Skill Activates

Use this skill when the user:

  • Wants to display styled or formatted text
  • Needs rich text editing with bold/italic/underline controls
  • Asks about AttributedString or TextEditor
  • Wants text formatting toolbars
  • Asks about Markdown rendering in Text views
  • Needs custom text attributes or formatting constraints
  • Wants selection-based text formatting

Decision Tree

What text feature do you need?
|
+- Display styled read-only text
|  +- Simple styling (one style) -> Text Styling section below
|  +- Mixed styles in one string -> AttributedString section below
|  +- Markdown content -> Markdown section below
|
+- Edit plain text
|  +- TextEditor(text: $stringBinding)
|
+- Edit rich/styled text
|  +- Basic rich editor -> Rich Text Editing section below
|  +- With formatting toolbar -> Formatting Controls section below
|  +- With custom constraints -> Custom Formatting section below

API Availability

APIMinimum VersionNotes
Text with modifiersiOS 13.font(), .bold(), .italic()
TextEditor(text:)iOS 14Plain string binding
.foregroundStyle()iOS 15Preferred over .foregroundColor()
AttributedStringiOS 15Rich text model
.bold(condition)iOS 16Conditional bold/italic
.underline(pattern:)iOS 16Dash, dot patterns
TextEditor(text:selection:)iOS 18AttributedString + selection
AttributedTextSelectioniOS 18Selection-based formatting
text.transformAttributes(in:)iOS 18Modify attributes in selection
AttributedTextFormattingDefinitioniOS 18Custom formatting constraints
@Environment(\.fontResolutionContext)iOS 18Resolve font properties

Top 5 Mistakes

#MistakeFix
1Using .foregroundColor() on new projectsUse .foregroundStyle() — supports gradients and ShapeStyle
2.animation(.spring()) without value: on textDeprecated in iOS 15 — always pass value: parameter
3Expecting full Markdown in TextText only supports inline Markdown: bold, italic, [links]. No lists, tables, code blocks, images
4Creating new AttributedString instances on every body evaluationCache complex AttributedString objects in @State or computed properties outside body
5Using TextEditor(text: $string) for rich textUse TextEditor(text: $attributedString, selection: $selection) with AttributedString binding (iOS 18+)

Text Styling Quick Reference

// Font
Text("Hello").font(.headline)
Text("Custom").font(.system(size: 24, design: .rounded))

// Weight
Text("Bold").fontWeight(.bold)

// Color — prefer foregroundStyle over foregroundColor
Text("Styled").foregroundStyle(.red)
Text("Gradient").foregroundStyle(
    .linearGradient(colors: [.yellow, .blue], startPoint: .top, endPoint: .bottom)
)

// Decorations
Text("Bold").bold()
Text("Conditional").bold(someCondition)
Text("Underline").underline(true, pattern: .dash, color: .blue)
Text("Strike").strikethrough(true, pattern: .dot, color: .red)

// Layout
Text("Centered").multilineTextAlignment(.center)
Text("Spaced").lineSpacing(10)
Text("Truncated").lineLimit(2).truncationMode(.tail)

AttributedString

// Create and style ranges
var text = AttributedString("Red and Blue")
if let redRange = text.range(of: "Red") {
    text[redRange].foregroundColor = .red
    text[redRange].font = .headline
}
if let blueRange = text.range(of: "Blue") {
    text[blueRange].foregroundColor = .blue
    text[blueRange].underlineStyle = .single
}

// Display
Text(text)

Available Attributes

AttributeTypeExample
.fontFont.headline
.foregroundColorColor.red
.backgroundColorColor.yellow
.underlineStyleUnderlineStyle.single
.underlineColorColor.blue
.strikethroughStyleUnderlineStyle.single
.strikethroughColorColor.red
.inlinePresentationIntentInlinePresentationIntent.stronglyEmphasized (bold), .emphasized (italic)

Rich Text Editing (iOS 18+)

struct RichTextEditorView: View {
    @State private var text = AttributedString("Select text to format")
    @State private var selection = AttributedTextSelection()

    @Environment(\.fontResolutionContext) private var fontResolutionContext

    var body: some View {
        VStack {
            TextEditor(text: $text, selection: $selection)
                .frame(height: 200)

            HStack {
                Button(action: toggleBold) {
                    Image(systemName: "bold")
                }
                Button(action: toggleItalic) {
                    Image(systemName: "italic")
                }
                Button(action: toggleUnderline) {
                    Image(systemName: "underline")
                }
            }
        }
    }

    private func toggleBold() {
        text.transformAttributes(in: &selection) {
            let font = $0.font ?? .default
            let resolved = font.resolve(in: fontResolutionContext)
            $0.font = font.bold(!resolved.isBold)
        }
    }

    private func toggleItalic() {
        text.transformAttributes(in: &selection) {
            let font = $0.font ?? .default
            let resolved = font.resolve(in: fontResolutionContext)
            $0.font = font.italic(!resolved.isItalic)
        }
    }

    private func toggleUnderline() {
        text.transformAttributes(in: &selection) {
            if $0.underlineStyle != nil {
                $0.underlineStyle = nil
            } else {
                $0.underlineStyle = .single
            }
        }
    }
}

Reading Selection Attributes

// Get current attributes at the selection/cursor
let attributes = selection.typingAttributes(in: text)
let currentColor = attributes.foregroundColor ?? .primary

Custom Formatting Definition (iOS 18+)

Constrain which formatting options are available in the editor:

struct MyTextFormatting: AttributedTextFormattingDefinition {
    typealias Scope = AttributeScopes.SwiftUIAttributes

    static let fontWeight = ValueConstraint(
        \.font,
        constraint: { font in
            guard let font = font else { return nil }
            let weight = font.resolve().weight
            return font.weight(weight == .bold ? .regular : .bold)
        }
    )
}

// Apply to TextEditor
TextEditor(text: $text, selection: $selection)
    .textFormattingDefinition(MyTextFormatting.self)

Markdown in Text

// Inline markdown support
Text("This is **bold** and *italic* text")
Text("Visit [Apple](https://www.apple.com)")
Text("Code: `inline code`")

Markdown Limitations

Text supports only inline Markdown:

  • ✅ Bold (**text**), italic (*text*), links, inline code
  • ❌ Line breaks, block formatting, lists, tables, code blocks, images, block quotes

Review Checklist

Text Display

  • Using .foregroundStyle() instead of deprecated .foregroundColor()
  • .lineLimit() paired with .help() tooltip or .textSelection(.enabled) for truncated text
  • Dynamic Type supported — using system font styles, not hardcoded sizes
  • Colors adapt to dark mode — using system colors or semantic styles

AttributedString

  • Complex AttributedString cached in @State, not recreated in body
  • Range lookups use safe if let range = text.range(of:) pattern
  • Appropriate attributes used (.inlinePresentationIntent for semantic bold/italic)

TextEditor

  • Rich text uses TextEditor(text: $attributedString, selection: $selection) (iOS 18+)
  • Formatting toolbar uses text.transformAttributes(in: &selection) pattern
  • Font resolution uses @Environment(\.fontResolutionContext) for toggle logic
  • Accessibility labels provided for formatting buttons

Localization

  • User-facing strings use LocalizedStringKey
  • Markdown in localized strings uses Text(LocalizedStringKey("**Bold** text"))

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Run a structured accessibility audit on an iOS/macOS app — automated XCUITest audits, Accessibility Inspector, manual VoiceOver/Dynamic Type passes, and App Store Accessibility Nutrition Label evaluation. Use before release, when preparing Nutrition Label declarations, or for EU Accessibility Act compliance.

日本語の概要は準備中です。原文の説明を表示しています。

rshankras/claude-code-apple-skills7902026年7月24日 更新

Generate accessibility infrastructure for VoiceOver, Dynamic Type, and accessibility features. Use when improving app accessibility, adding accessibility labels and hints, or auditing compliance.

日本語の概要は準備中です。原文の説明を表示しています。

rshankras/claude-code-apple-skills7902026年7月24日 更新

Generates an Apple-compliant account deletion flow with multi-step confirmation UI, optional data export, configurable grace period, Keychain cleanup, and server-side deletion request. Use when user needs account deletion, right-to-delete, or Apple App Review compliance for account removal.

日本語の概要は準備中です。原文の説明を表示しています。

rshankras/claude-code-apple-skills7902026年7月24日 更新

Privacy-preserving ad measurement with AdAttributionKit (SKAdNetwork's successor) — install and re-engagement attribution, conversion-value strategy under crowd anonymity, and end-to-end postback testing. Use when running paid acquisition beyond Apple Ads, measuring re-engagement campaigns, designing conversion values, or migrating from SKAdNetwork.

日本語の概要は準備中です。原文の説明を表示しています。

rshankras/claude-code-apple-skills7902026年7月24日 更新

alarmkit

無料

AlarmKit integration for scheduling alarms and timers with custom UI, Live Activities, and snooze support. Use when implementing alarm or timer features in iOS 26+ apps.

日本語の概要は準備中です。原文の説明を表示しています。

rshankras/claude-code-apple-skills7902026年7月24日 更新

Interpret app metrics and make data-driven decisions. Covers DAU/MAU, retention, LTV, ARPU, App Store Connect analytics, AARRR funnel analysis, cohort analysis, and diagnostic decision trees. Use when user wants to understand their metrics, diagnose problems, or build a data-driven growth plan.

日本語の概要は準備中です。原文の説明を表示しています。

rshankras/claude-code-apple-skills7902026年7月24日 更新

rshankras のスキルをすべて見る

このスキルの問題を報告する