Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8016f73
feat(iOS): add custom style
kacperzolkiewski Jun 16, 2026
fb8cdc0
fix: copilot code review
kacperzolkiewski Jun 16, 2026
e4f4804
fix: reapplying attributes
kacperzolkiewski Jun 16, 2026
2c29d83
fix: use hex for colors
kacperzolkiewski Jun 17, 2026
c2c0613
feat: handle named colors in html parsing
kacperzolkiewski Jun 17, 2026
ce12b57
feat: add colors to toolbar
kacperzolkiewski Jun 17, 2026
18ca4bd
Merge branch 'main' into @kacperzolkiewski/feat-custom-style
kacperzolkiewski Jun 17, 2026
ec7521b
test: add e2e test for colors
kacperzolkiewski Jun 17, 2026
9c0c095
fix: handling rgb colors
kacperzolkiewski Jun 17, 2026
f34fbf0
Merge branch 'main' into @kacperzolkiewski/feat-custom-style
kacperzolkiewski Jun 19, 2026
cf3739e
fix: custom style parsing
kacperzolkiewski Jun 22, 2026
4ab7531
fix: align normalizer to properly handle span with colors
kacperzolkiewski Jun 22, 2026
0e37c0d
fix: handle opacity in custom style colors
kacperzolkiewski Jul 29, 2026
e29cdfa
fix: foreground color
kacperzolkiewski Jul 31, 2026
1c1933b
Merge branch '@kacperzolkiewski/custom-style' into @kacperzolkiewski/…
kacperzolkiewski Aug 7, 2026
1d2aa4a
fix: update podfile
kacperzolkiewski Aug 7, 2026
eeaa4ac
fix: applying custom style in renderer
kacperzolkiewski Aug 7, 2026
595ba1d
Merge branch '@kacperzolkiewski/feat-custom-style' of github.com:soft…
kacperzolkiewski Aug 7, 2026
dc48a57
test: update screenshots
kacperzolkiewski Aug 7, 2026
f1c7a1b
fix: update font screenshots
kacperzolkiewski Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .maestro/enrichedInput/flows/custom_style_colors_visual.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
appId: swmansion.enriched.example
---
# Validates custom colors on plain text, inline styles, and paragraph styles.
- launchApp

- tapOn:
id: 'toggle-screen-button'

- tapOn:
id: 'editor-input'

# Section 1: Plain text with colors

- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-FF0000'
- inputText: 'Red text'
- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-clear'
- inputText: ' '

- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-FFFF00'
- inputText: 'Yellow back'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-clear'
- inputText: ' '

- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-FF0000'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-FFFF00'
- inputText: 'Red+Yellow'
- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-clear'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-clear'
- inputText: ' '

# Section 2: Inline styles + color

- tapOn:
id: 'toolbar-bold'
- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-FF0000'
- inputText: 'Bold red'
- tapOn:
id: 'toolbar-bold'
- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-clear'
- inputText: ' '

- tapOn:
id: 'toolbar-italic'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-FFFF00'
- inputText: 'Italic yellow back'
- tapOn:
id: 'toolbar-italic'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-clear'
- inputText: ' '
- pressKey: Enter

# Section 3: Paragraph styles + color

- tapOn:
id: 'toolbar-heading-5'
- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-FF0000'
- inputText: 'H5 red'
- pressKey: Enter
- tapOn:
id: 'toolbar-text-color'
- tapOn:
id: 'color-swatch-clear'

- tapOn:
id: 'toolbar-quote'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-FFFF00'
- inputText: 'Quote yellow back'
- tapOn:
id: 'toolbar-bg-color'
- tapOn:
id: 'color-swatch-clear'

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'custom_style_colors'
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions .maestro/enrichedText/flows/custom_style_colors_visual.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
appId: swmansion.enriched.example
---
# Validates that custom style colors are displayed correctly
- launchApp

- tapOn:
id: 'toggle-screen-button'

- tapOn:
id: 'toggle-enriched-text-screen-button'

- runFlow:
file: '../subflows/set_enriched_text_value.yaml'
env:
VALUE: >
<html>
<p><span style="color: #FF5733;">Standard 6-digit Hex text</span></p>
<p><span style="background-color: #000000; color: #FFFFFF;">White text on black background</span></p>
<p><span style="background-color: #00FF0040;">25% transparent green background</span></p>
<p><span style="color: #0000FF80;">50% transparent blue text</span></p>
<p><span style="color: #F00;">Red 3-digit shorthand text</span></p>
<h6><span style="background-color: #0F0; color: #000;">Black text on green</span></h6>
</html>

- runFlow:
file: '../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'custom_style_colors_visual'
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,13 @@ class EnrichedTextInputViewManager :
view?.setTextAlignment(alignment)
}

override fun setStyle(
view: EnrichedTextInputView?,
styleJSON: String,
) {
// TODO: Implement
}
Comment thread
kacperzolkiewski marked this conversation as resolved.

override fun measure(
context: Context,
localData: ReadableMap?,
Expand Down
2 changes: 1 addition & 1 deletion apps/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2108,7 +2108,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
FBLazyVector: b3e7ad108f0d882e30445c5527d774e3fd432f3d
hermes-engine: 78997c9592858f3aeaacad4f0062cd700ba8dda2
hermes-engine: 03c4f027614fa33388949bb373cbf7a4892b8e5f
RCTDeprecation: 2a74a2c57675e64419bd89078efde81f7c1de90b
RCTRequired: 30451112e6fef4e6f31b4e7eee0845156e35e4b0
RCTSwiftUI: 5aaf0b07e747ba749dc6acc94d8bd41eea4b570f
Expand Down
92 changes: 92 additions & 0 deletions apps/example/src/components/ColorPickerRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { type FC } from 'react';
import { Pressable, ScrollView, StyleSheet, Text } from 'react-native';

interface Props {
colors: string[];
activeColor: string;
onSelectColor: (color: string) => void;
onClear: () => void;
}

export const ColorPickerRow: FC<Props> = ({
colors,
activeColor,
onSelectColor,
onClear,
}) => {
return (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={styles.container}
contentContainerStyle={styles.content}
>
<Pressable
testID="color-swatch-clear"
style={styles.clearButton}
onPress={onClear}
>
<Text style={styles.clearText}>✕</Text>
</Pressable>
{colors.map((color) => {
const isActive = color.toLowerCase() === activeColor?.toLowerCase();
const swatchId = `color-swatch-${color.replace('#', '').toUpperCase()}`;
return (
<Pressable
key={color}
testID={swatchId}
onPress={() => onSelectColor(color)}
style={[
styles.swatch,
{ backgroundColor: color },
isActive && styles.swatchActive,
color === '#FFFFFF' && styles.swatchBordered,
]}
/>
);
})}
</ScrollView>
);
};

const SWATCH_SIZE = 28;

const styles = StyleSheet.create({
container: {
width: '100%',
backgroundColor: 'rgba(0, 26, 114, 0.9)',
},
content: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 8,
paddingVertical: 8,
gap: 8,
},
clearButton: {
width: SWATCH_SIZE,
height: SWATCH_SIZE,
borderRadius: SWATCH_SIZE / 2,
backgroundColor: 'rgba(255,255,255,0.15)',
justifyContent: 'center',
alignItems: 'center',
},
clearText: {
color: 'white',
fontSize: 14,
lineHeight: 16,
},
swatch: {
width: SWATCH_SIZE,
height: SWATCH_SIZE,
borderRadius: SWATCH_SIZE / 2,
},
swatchActive: {
borderWidth: 3,
borderColor: 'white',
},
swatchBordered: {
borderWidth: 1,
borderColor: 'rgba(0,0,0,0.25)',
},
});
Loading