I have some Text element with dynamically loaded text. It's an RTL language (Hebrew) text mixed with some English.
When the first char is English, it automatically sets to LTR direction.
When the first char is Hebrew, it automatically sets to RTL direction.
I'm not happy with that behavoir!
I'd like to set the element to be RTL anyway. Always.
In CSS that would be very simple:
text-align: right; direction: rtl;
How can I achieve the same in React Native?
When I had this problem (of individual lines of text in RTL language being incorrectly treated as LTR becuase they start with non-transliterated LTR text or numbers), I dealt with it using Unicode direction marker characters.
Here they are (they're the invisible characters between the quotes):
'' to force text to be treated as RTL
'' to force text to be treated as LTR
These change the behaviour you're seeing, explicitly saying how the text should be treated rather than letting the system assume.
How you apply these is up to you. I mostly did it with regex find-replace insertions in the source content, but you could do something like this (untested), making a swap-in replacement for useTranslation's t function that wraps the text in the appropriate Unicode control character:
import { I18nManager } from 'react-native'
// assuming you're using i18n hooks
import { useTranslation } from 'react-i18next'
const rtlMarkerChar = ''
const ltrMarkerChar = ''
const directionChar = I18nManager.isRTL ? rtlMarkerChar : ltrMarkerChar
// Use instead of `useTranslation` to force text right on RTL and left on LTR
// regardless of the initial character of the particular snippet of text
export const useLocaleAlignedText = () => {
const { t } = useTranslation()
return (key) => `${directionChar}${t(key)}`
}
// For example, this should be consistently RTL or LTR regardless of content
const SomeComponent = ({ contentKey }) => {
const t = useLocaleAlignedText()
return <Text>{t(contentKey)}</Text>
}
Be warned that the above might not work where your content contains newline characters, you might need to inject the control characters at the start of each line. This was one of the reasons I chose to inject the characters into the source material; but be warned also, that's hard work and easy to make mistakes.
To handle RTL for Text, Use style alignSelf: 'flex-start'
Example react-native:
<View>
<Text style={styles.headersText}>{headerTitle}</Text>
</View>
StyleSheet.create({ headersText: {
alignSelf: 'flex-start', // <- Here Handle RTL for Text
paddingHorizontal: 16,
paddingTop: 14,
color: 'black',
fontSize: 13,
},
});
I did this with :
textAlign:'right'
your Text should have this style.
This worked for me:
<Text style={{alignSelf: "flex-start"}}>
{text}
</Text>
BTW, if you wanna force RTL for the entire project you could just write something like this and run it in your main App component:
import { I18nManager } from "react-native";
const App = () => {
. . . . . . . .
const rtl = () => {
if (I18nManager.isRTL === false) {
I18nManager.allowRTL(true);
I18nManager.forceRTL(true);
}
};
. . . . . . . .
}
Related
I am trying to incorporate this WYSIWYG package into my react native project (0.64.3). I built my project with a managed workflow via Expo (~44.0.0).
The problem I am noticing is that the editor will sometimes render with the text from my database and sometimes render without it.
Here is a snippet of the function that retrieves the information from firebase.
const [note, setNote] = useState("");
const getNote = () => {
const myDoc = doc(db,"/users/" + user.uid + "/Destinations/Trip-" + trip.tripID + '/itinerary/' + date);
getDoc(myDoc)
.then(data => {
setNote(data.data()[date]);
}).catch();
}
The above code and the editor component are nested within a large function
export default function ItineraryScreen({route}) {
// functions
return (
<RichEditor
onChange={newText => {
setNote(newText)
}}
scrollEnabled={false}
ref={text}
initialFocus={false}
placeholder={'What are you planning to do this day?'}
initialContentHTML={note}
/>
)
}
Here is what it should look like with the text rendered (screenshot of simulator):
But this is what I get most of the time (screenshot from physical device):
My assumption is that there is a very slight delay between when the data for the text editor is actually available vs. when the editor is being rendered. I believe my simulator renders correctly because it is able to process the getNote() function faster.
what I have tried is using a setTimeOut function to the display of the parent View but it does not address the issue.
What do you recommend?
I believe I have solved the issue. I needed to parse the response better before assigning a value to note and only show the editor and toolbar once a value was established.
Before firebase gets queried, I assigned a null value to note
const [note, setNote] = useState(null);
Below, I will always assign value to note regardless of the outcome.
if(data.data() !== undefined){
setNote(data.data()[date]);
} else {
setNote("");
}
The last step was to only show the editor once note no longer had a null value.
{
note !== null &&
<RichToolbar
style={{backgroundColor:"white", width:"114%", flex:1, position:"absolute", left:0, zIndex:4, bottom: (toolbarVisible) ? keyboardHeight * 1.11 : 0 , marginBottom:-40, display: toolbarVisible ? "flex" : "none"}}
editor={text}
actions={[ actions.undo, actions.setBold, actions.setItalic, actions.setUnderline,actions.insertLink, actions.insertBulletsList, actions.insertOrderedList, actions.keyboard ]}
iconMap={{ [actions.heading1]: ({tintColor}) => (<Text style={[{color: tintColor}]}>H1</Text>), }}
/>
<RichEditor
disabled={disableEditor}
initialFocus={false}
onChange={ descriptionText => { setNote(descriptionText) }}
scrollEnabled={true}
ref={text}
placeholder={'What are you planning to do?'}
initialContentHTML={note}
/>
}
It is working properly.
I have a situation in which I want to display data in a FluentUI DetailsList, where column names can be very long, while the column content can be very narrow. In such a case, the header will be truncated.
See this codepen.
Is there any way to change this behavior, such that the header text wraps over multiple lines?
While I found this unanswered question from 2 years ago, I couldn't find an answer on the topic on neither Stackoverflow, Github or the offical documentation.
Here are some approaches I tried:
inject a CSS class with word-break: break-all; via the headerClassName field of IColumn
setting isMultiLine on the columns
The DetailsHeader component itself whose rendering I can override with onRenderDetailsHeader does not seem to offer any props for customizing how the text is displayed
Is there even a way to achieve the desired behaviour (wrapping over multiple lines instead of truncating long column headers)?
Most of FluentUI Components uses text-overflow: ellipsis. What you can do is to modify that "rule". Inside DetailsList you have onRenderDetailsHeader method which allows you to change header styles.
const onRenderDetailsHeader = (headerProps, defaultRender) => {
if (!headerProps || !defaultRender) {
//technically these may be undefined...
return null;
}
return defaultRender({
...headerProps,
styles: {
root: {
selectors: {
'.ms-DetailsHeader-cell': {
whiteSpace: 'normal',
textOverflow: 'clip',
lineHeight: 'normal',
},
'.ms-DetailsHeader-cellTitle': {
height: '100%',
alignItems: 'center',
},
},
},
},
})
}
<DetailsList
...
onRenderDetailsHeader={onRenderDetailsHeader}
/>
Codepen working solution
Note:
Play around with minWidth, maxWidth props inside this._columns to get expected behavior.
I am trying to have a repeating-linear-gradient for my view in React Native. However i couldn't find any information or library that would help me use it.
I found a library named react-native-linear-gradient but it seems to be helpful to only have simple linear gradient.
Thanks for your help in advance
CSS
background: repeating-linear-gradient(
-55deg,
#222,
#222 10px,
#333 10px,
#333 20px
);
In React, styles are specified with an object wherein the key is the camelCase version of the style name, and the value is the style’s value. If the value is not explicitly typeof 'number', the entire value must be a single string. Within that string, normal css style names can be used.
Here is an example:
<ExampleComponent
style={{
background: 'repeating-linear-gradient(-55deg, #222, #222 10px,#333 10px, #333 20px)',
backgroundSize: 'cover',
}}
/>
I have used react-native-linear-gradient for my splash screen
fist I have set 4 different colors and make it a gradient with white color.
const gradient1 = [Colors.secondary1Color, Colors.white];
const gradient2 = [Colors.primary1Color, Colors.white];
const gradient3 = [Colors.secondaryColor, Colors.white];
const gradient4 = [Colors.primaryColor, Colors.white];
I first set this.state = {changeGradient: true}
then I have this changeGradient function which changes the const gradient colors ever had a second
changeGradient = async () => {
console.log("changeGradient", await this.state.gradient);
if (this.state.changeGradient) {
setTimeout(async () => {
await this.setState(({ gradient }) => ({ gradient: gradient === gradient1 ? gradient2 : gradient === gradient2 ? gradient3 : gradient === gradient3 ? gradient4 : gradient1 }));
this.changeGradient();
}, 500);
}
};
Then, I render in the Lineargradient component
<LinearGradient colors={this.state.gradient} style={styles.container}>
</LinearGradient >
You're good to go!!!
Hope this helps you!
I've changed 'medium' font size with loadTheme like such:
loadTheme({
fonts: {
medium: {
fontFamily: fonts.fontFamily,
fontSize: fonts.fontSize.regular
}
}
)
However, the base Checkbox styles are loading font-size directly from FontSizes here:
https://github.com/OfficeDev/office-ui-fabric-react/blob/ace874ab7e56188a7d6de081915c63025def4e05/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.styles.ts#L223
I know I can override this on the component itself, but it seems like I shouldn't have to. Is this a bug? Shouldn't the component use theme font size by default?
Yes, Checkbox should be reading font from theme. In fact, in the fabric-7 branch, it does:
https://github.com/OfficeDev/office-ui-fabric-react/blob/14b1d77fc97fffb1c333a3601d62c3e30c4cf3b0/packages/office-ui-fabric-react/src/components/Checkbox/Checkbox.styles.ts#L136
Fabric 7 release is planned for May. Meanwhile you should be able to apply your own styling making use of the loadTheme call like this:
const checkboxStyling = (props) => {
return {
text: { ...props.theme.fonts.medium }
}
}
...
<Checkbox label='test' styles={checkboxStyling} />
This works in the following CodePen: https://codepen.io/jasongore/pen/JVwJGO
I have a .js file which holds global data (actually i am going to fill it from website). Here it is:
const DynGlobals = {
HomePageColor: {
color: '#e74c3c'
}
}
/*
or i can set it like this
HomePageColor: '#e74c3c'
/*
export { DynGlobals }
I have a view and trying to set it's style from this file. So far i have tried many things to create another const and set it to view's style but didn't work
const bgColorStyle = {
backgroundColor: {DynGlobals.HomePageColor.color}
}
with or without bracelets it doesn't work. Any advices on this?