Repository navigation
docs: custom style #816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
hejsztynx
merged 6 commits into
@kacperzolkiewski/custom-style
from
@ksienkiewicz/docs-custom-style
Oct 20, 2026
Merged
docs: custom style #816
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
c90e0cc
docs: custom style
hejsztynx cc13c69
fix: font change to something more conspicuous
hejsztynx dfbaaf4
docs: tweaks regarding colors
hejsztynx 22568b4
refactor: adjusted formatting button labels
hejsztynx 401ca03
feat: bigger formatting example buttons
hejsztynx 8e7df80
docs: review adjustments
hejsztynx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| --- | ||
| sidebar_position: 2 | ||
| --- | ||
|
|
||
| import InteractiveExample from '@site/src/components/InteractiveExample'; | ||
| import CustomStyleEditor from '@site/src/examples/CustomStyleEditor'; | ||
| import CustomStyleEditorSrc from '!!raw-loader!@site/src/examples/CustomStyleEditor'; | ||
|
|
||
| # Custom style | ||
|
|
||
| Aside from the predefined [basic styles](/rich-text-formatting/basic-styles) | ||
| you can apply a **custom style**, which consists of four pieces of formatting: | ||
| text color, highlight, font size and font family. Similarly as the style-toggling | ||
| methods, it applies to the current input's selection. | ||
|
|
||
| ## Setting a custom style | ||
|
|
||
| `setStyle` accepts an object with four optional fields: | ||
|
|
||
| ```tsx | ||
| setStyle( | ||
| { | ||
| foregroundColor?: string, | ||
| backgroundColor?: string, | ||
| fontSize?: number, | ||
| fontFamily?: string, | ||
| } | ||
| ); | ||
| ``` | ||
|
|
||
| Each call respects the already present custom style and modifies it with whatever | ||
| fields you pass. For example, if you want to remove a single field, pass `null`: | ||
|
|
||
| ```tsx | ||
| // Remove the highlight, keep the color, size and font as they are. | ||
| ref.current?.setStyle({ backgroundColor: null }); | ||
| ``` | ||
|
|
||
| Custom style doesn't conflict with or block any other style, so it combines | ||
| freely with both inline styles and paragraph styles. | ||
|
|
||
| :::note | ||
|
|
||
| If a current style modifies the same thing that **custom style** sets, we have the following priority: | ||
| **paragraph style** < **custom style** < **inline style**. E.g. if you try to apply `foregroundColor` custom style to a text with a link (which is an inline style), the link's foreground color stays. | ||
|
|
||
| ::: | ||
|
|
||
| ## Reading the current style | ||
|
|
||
| Since custom style carries values rather than a simple on/off flag, `onChangeState` | ||
| reports it as a separate `customStyle` object instead of the usual | ||
| `isActive` / `isBlocking` / `isConflicting` | ||
| [booleans](/fundamentals/core-concepts#the-style-state-model): | ||
|
|
||
| ```ts | ||
| customStyle: { | ||
| foregroundColor: string; | ||
| backgroundColor: string; | ||
| fontSize: number; | ||
| fontFamily: string; | ||
| } | ||
| ``` | ||
|
|
||
| Each field holds the value at the current selection. When a field isn't set, it comes back | ||
| empty: `''` for strings and `0` for `fontSize`. That makes it easy to check whether a field | ||
| is applied: | ||
|
|
||
| ```tsx | ||
| const customStyleButtons = [ | ||
| { | ||
| label: 'Color', | ||
| isActive: !!state?.customStyle.foregroundColor, | ||
| onPress: () => ref.current?.setStyle({ foregroundColor: '#e5484d' }), | ||
| }, | ||
| { | ||
| label: 'Font size', | ||
| isActive: !!state?.customStyle.fontSize, | ||
| onPress: () => ref.current?.setStyle({ fontSize: 26 }), | ||
| }, | ||
| ]; | ||
| ``` | ||
|
|
||
| :::tip | ||
|
|
||
| Pass colors to `setStyle` as hex or named colors (e.g. `'red'`). They are | ||
| always reported as uppercase hex strings - `#RRGGBB`, or `#RRGGBBAA`. | ||
|
|
||
| ::: | ||
|
|
||
| ## Try it out | ||
|
|
||
| Each button below sets one field of the custom style on the selection, and | ||
| removes it when the field is already applied. Select a word and give it a color, | ||
| then a highlight - notice how the second call doesn't touch the first one. Try | ||
| mixing them with different fonts and sizes. | ||
|
|
||
| <InteractiveExample src={CustomStyleEditorSrc} component={CustomStyleEditor} /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| import { EnrichedTextInput } from 'react-native-enriched-html'; | ||
| import type { | ||
| EnrichedTextInputInstance, | ||
| OnChangeStateEvent, | ||
| } from 'react-native-enriched-html'; | ||
| import { useRef, useState } from 'react'; | ||
| import { View, StyleSheet, Pressable, Text } from 'react-native'; | ||
| import { htmlStyle } from './htmlStyle'; | ||
|
|
||
| const TEXT_COLOR = '#ff8560'; | ||
| const HIGHLIGHT_COLOR = '#c1c6e5'; | ||
| const FONT_SIZE = 26; | ||
| const FONT_FAMILY = 'cursive'; | ||
|
|
||
| export default function App() { | ||
| const ref = useRef<EnrichedTextInputInstance>(null); | ||
| const [state, setState] = useState<OnChangeStateEvent | null>(null); | ||
|
|
||
| const customStyle = state?.customStyle; | ||
|
|
||
| const buttons = [ | ||
| { | ||
| label: 'Color', | ||
| isActive: !!customStyle?.foregroundColor, | ||
| onPress: () => | ||
| ref.current?.setStyle({ | ||
| foregroundColor: customStyle?.foregroundColor ? null : TEXT_COLOR, | ||
| }), | ||
| }, | ||
| { | ||
| label: 'Highlight', | ||
| isActive: !!customStyle?.backgroundColor, | ||
| onPress: () => | ||
| ref.current?.setStyle({ | ||
| backgroundColor: customStyle?.backgroundColor | ||
| ? null | ||
| : HIGHLIGHT_COLOR, | ||
| }), | ||
| }, | ||
| { | ||
| label: 'Font size', | ||
| isActive: !!customStyle?.fontSize, | ||
| onPress: () => | ||
| ref.current?.setStyle({ | ||
| fontSize: customStyle?.fontSize ? null : FONT_SIZE, | ||
| }), | ||
| }, | ||
| { | ||
| label: 'Font family', | ||
| isActive: !!customStyle?.fontFamily, | ||
| onPress: () => | ||
| ref.current?.setStyle({ | ||
| fontFamily: customStyle?.fontFamily ? null : FONT_FAMILY, | ||
| }), | ||
| }, | ||
| ]; | ||
|
|
||
| return ( | ||
| <View style={styles.container}> | ||
| <EnrichedTextInput | ||
| ref={ref} | ||
| style={styles.input} | ||
| htmlStyle={htmlStyle} | ||
| placeholder="Select some text and style it below..." | ||
| onChangeState={e => setState(e.nativeEvent)} | ||
| /> | ||
| <View style={styles.row}> | ||
| {buttons.map(button => ( | ||
| <Pressable | ||
| key={button.label} | ||
| style={[styles.button, button.isActive && styles.buttonActive]} | ||
| onPress={button.onPress}> | ||
| <Text style={[styles.text, button.isActive && styles.textActive]}> | ||
| {button.label} | ||
| </Text> | ||
| </Pressable> | ||
| ))} | ||
| </View> | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| container: { gap: 12 }, | ||
| input: { | ||
| fontSize: 18, | ||
| color: '#232736', | ||
| padding: 12, | ||
| borderRadius: 12, | ||
| minHeight: 96, | ||
| backgroundColor: '#eef0ff', | ||
| }, | ||
| row: { | ||
| flexDirection: 'row', | ||
| flexWrap: 'wrap', | ||
| justifyContent: 'center', | ||
| gap: 8, | ||
| }, | ||
| button: { | ||
| width: 120, | ||
| padding: 8, | ||
| borderRadius: 24, | ||
| borderWidth: 1, | ||
| borderColor: '#919fcf', | ||
| }, | ||
| buttonActive: { | ||
| borderColor: '#57b495', | ||
| backgroundColor: '#57b495', | ||
| }, | ||
| text: { | ||
| textAlign: 'center', | ||
| color: '#919fcf', | ||
| }, | ||
| textActive: { | ||
| color: '#eef0ff', | ||
| }, | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.