-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
RFC: Support for bidirectional text output in Fluent UI components #18921
Conversation
Asset size changesSize Auditor did not detect a change in bundle size for any component! Baseline commit: 035ba0498cee783b11b31dffa0cbf595b73d6ec8 (build) |
Perf Analysis (
|
Scenario | Render type | Master Ticks | PR Ticks | Iterations | Status |
---|---|---|---|---|---|
Avatar | mount | 816 | 783 | 5000 | |
BaseButton | mount | 887 | 907 | 5000 | |
Breadcrumb | mount | 2673 | 2559 | 1000 | |
ButtonNext | mount | 546 | 529 | 5000 | |
Checkbox | mount | 1540 | 1462 | 5000 | |
CheckboxBase | mount | 1265 | 1272 | 5000 | |
ChoiceGroup | mount | 4638 | 4678 | 5000 | |
ComboBox | mount | 963 | 962 | 1000 | |
CommandBar | mount | 10001 | 10009 | 1000 | |
ContextualMenu | mount | 6161 | 6215 | 1000 | |
DefaultButton | mount | 1094 | 1119 | 5000 | |
DetailsRow | mount | 3734 | 3638 | 5000 | |
DetailsRowFast | mount | 3644 | 3690 | 5000 | |
DetailsRowNoStyles | mount | 3454 | 3527 | 5000 | |
Dialog | mount | 2160 | 2179 | 1000 | |
DocumentCardTitle | mount | 148 | 151 | 1000 | |
Dropdown | mount | 3186 | 3238 | 5000 | |
FluentProviderNext | mount | 7166 | 7218 | 5000 | |
FocusTrapZone | mount | 1721 | 1724 | 5000 | |
FocusZone | mount | 1778 | 1779 | 5000 | |
IconButton | mount | 1679 | 1690 | 5000 | |
Label | mount | 326 | 326 | 5000 | |
Layer | mount | 1764 | 1750 | 5000 | |
Link | mount | 468 | 463 | 5000 | |
MakeStyles | mount | 1844 | 1797 | 50000 | |
MenuButton | mount | 1453 | 1429 | 5000 | |
MessageBar | mount | 1991 | 2001 | 5000 | |
Nav | mount | 3165 | 3218 | 1000 | |
OverflowSet | mount | 1031 | 1041 | 5000 | |
Panel | mount | 2052 | 2107 | 1000 | |
Persona | mount | 821 | 807 | 1000 | |
Pivot | mount | 1370 | 1368 | 1000 | |
PrimaryButton | mount | 1281 | 1274 | 5000 | |
Rating | mount | 7530 | 7488 | 5000 | |
SearchBox | mount | 1264 | 1315 | 5000 | |
Shimmer | mount | 2459 | 2465 | 5000 | |
Slider | mount | 1909 | 1868 | 5000 | |
SpinButton | mount | 4899 | 4931 | 5000 | |
Spinner | mount | 417 | 408 | 5000 | |
SplitButton | mount | 3076 | 3101 | 5000 | |
Stack | mount | 485 | 511 | 5000 | |
StackWithIntrinsicChildren | mount | 1546 | 1542 | 5000 | |
StackWithTextChildren | mount | 4417 | 4506 | 5000 | |
SwatchColorPicker | mount | 10064 | 10094 | 5000 | |
Tabs | mount | 1396 | 1393 | 1000 | |
TagPicker | mount | 2374 | 2381 | 5000 | |
TeachingBubble | mount | 11779 | 11713 | 5000 | |
Text | mount | 408 | 426 | 5000 | |
TextField | mount | 1361 | 1370 | 5000 | |
ThemeProvider | mount | 1158 | 1159 | 5000 | |
ThemeProvider | virtual-rerender | 600 | 602 | 5000 | |
Toggle | mount | 795 | 777 | 5000 | |
buttonNative | mount | 108 | 120 | 5000 |
Perf Analysis (@fluentui/react-northstar
)
Perf tests with no regressions
Scenario | Current PR Ticks | Baseline Ticks | Ratio |
---|---|---|---|
AttachmentMinimalPerf.default | 164 | 151 | 1.09:1 |
FlexMinimalPerf.default | 299 | 277 | 1.08:1 |
RadioGroupMinimalPerf.default | 463 | 428 | 1.08:1 |
LayoutMinimalPerf.default | 378 | 354 | 1.07:1 |
TreeWith60ListItems.default | 180 | 168 | 1.07:1 |
GridMinimalPerf.default | 345 | 324 | 1.06:1 |
SkeletonMinimalPerf.default | 356 | 337 | 1.06:1 |
IconMinimalPerf.default | 608 | 574 | 1.06:1 |
MenuMinimalPerf.default | 857 | 814 | 1.05:1 |
ReactionMinimalPerf.default | 385 | 365 | 1.05:1 |
SegmentMinimalPerf.default | 358 | 342 | 1.05:1 |
TooltipMinimalPerf.default | 1017 | 971 | 1.05:1 |
AlertMinimalPerf.default | 266 | 255 | 1.04:1 |
BoxMinimalPerf.default | 336 | 324 | 1.04:1 |
ChatDuplicateMessagesPerf.default | 292 | 281 | 1.04:1 |
TableManyItemsPerf.default | 1903 | 1823 | 1.04:1 |
AnimationMinimalPerf.default | 420 | 407 | 1.03:1 |
CarouselMinimalPerf.default | 475 | 459 | 1.03:1 |
ChatMinimalPerf.default | 649 | 629 | 1.03:1 |
FormMinimalPerf.default | 407 | 395 | 1.03:1 |
PortalMinimalPerf.default | 181 | 175 | 1.03:1 |
ProviderMinimalPerf.default | 998 | 973 | 1.03:1 |
RefMinimalPerf.default | 242 | 234 | 1.03:1 |
TableMinimalPerf.default | 407 | 396 | 1.03:1 |
TreeMinimalPerf.default | 811 | 791 | 1.03:1 |
CardMinimalPerf.default | 548 | 537 | 1.02:1 |
ListWith60ListItems.default | 643 | 632 | 1.02:1 |
AvatarMinimalPerf.default | 182 | 181 | 1.01:1 |
ButtonOverridesMissPerf.default | 1675 | 1660 | 1.01:1 |
ChatWithPopoverPerf.default | 377 | 374 | 1.01:1 |
DatepickerMinimalPerf.default | 5380 | 5315 | 1.01:1 |
DialogMinimalPerf.default | 770 | 761 | 1.01:1 |
DividerMinimalPerf.default | 357 | 354 | 1.01:1 |
ImageMinimalPerf.default | 365 | 363 | 1.01:1 |
ItemLayoutMinimalPerf.default | 1202 | 1185 | 1.01:1 |
LabelMinimalPerf.default | 394 | 390 | 1.01:1 |
ListMinimalPerf.default | 493 | 489 | 1.01:1 |
SplitButtonMinimalPerf.default | 3779 | 3756 | 1.01:1 |
TextMinimalPerf.default | 350 | 348 | 1.01:1 |
CustomToolbarPrototype.default | 3853 | 3822 | 1.01:1 |
ToolbarMinimalPerf.default | 919 | 914 | 1.01:1 |
AttachmentSlotsPerf.default | 1049 | 1052 | 1:1 |
ButtonMinimalPerf.default | 166 | 166 | 1:1 |
CheckboxMinimalPerf.default | 2710 | 2707 | 1:1 |
DropdownManyItemsPerf.default | 667 | 666 | 1:1 |
EmbedMinimalPerf.default | 4130 | 4145 | 1:1 |
HeaderSlotsPerf.default | 756 | 758 | 1:1 |
PopupMinimalPerf.default | 582 | 581 | 1:1 |
ProviderMergeThemesPerf.default | 1677 | 1678 | 1:1 |
SliderMinimalPerf.default | 1574 | 1569 | 1:1 |
TextAreaMinimalPerf.default | 491 | 489 | 1:1 |
DropdownMinimalPerf.default | 3145 | 3163 | 0.99:1 |
HeaderMinimalPerf.default | 357 | 362 | 0.99:1 |
MenuButtonMinimalPerf.default | 1639 | 1659 | 0.99:1 |
StatusMinimalPerf.default | 670 | 678 | 0.99:1 |
ButtonSlotsPerf.default | 531 | 541 | 0.98:1 |
ListNestedPerf.default | 540 | 550 | 0.98:1 |
LoaderMinimalPerf.default | 687 | 704 | 0.98:1 |
InputMinimalPerf.default | 1248 | 1282 | 0.97:1 |
AccordionMinimalPerf.default | 141 | 147 | 0.96:1 |
ListCommonPerf.default | 587 | 622 | 0.94:1 |
RosterPerf.default | 1132 | 1210 | 0.94:1 |
VideoMinimalPerf.default | 600 | 658 | 0.91:1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should do this at all for 2 reasons:
dir=auto
should only be used when the direction is unknown. It is not our responsibility to manage direction for the user as it varies case by case. Setting it as auto is a pattern we should not follow as it goes against the standards.- We should avoid "magic" in our library. From the RFC, it seems like the point of this change is to help users who are not aware of how direction works. However, applying stuff by default will cause confusion for users who are aware of how direction works.
|
||
### Pros and Cons | ||
|
||
Con: Having `dir='auto'` on each leaf node is in most cases (French app language / French text) redundant |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this section is quite hard to read in VIEW mode
Con: Having `dir='auto'` on each leaf node is in most cases (French app language / French text) redundant | |
#### Pros | |
- Developers do not need to be aware of the particularities of bidirectional text in most cases | |
#### Cons | |
- Having `dir='auto'` on each leaf node is in most cases (French app language / French text) redundant | |
- There are cases where texts are composed of multiple substrings. This happens in most cases for parametrized translations. Proposal: for parametrized translations, let the translation framework be responsible for setting the direction. |
|
||
Besides adding `dir='ltr'` or `dir='rtl'` on the root element (html or body), each leaf element that has plain text as child node, needs to have `dir='auto'` set by default. Developer can override it, if the direction is known. This will allow the browser to evaluate the direction of the text. | ||
|
||
This is mandatory for components where we expect user input to be displayed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this sentence is a bit confusing. user input -> does that means input
elements as well ? Can we re-phrase ?
^ 100%. based on the RFC problem statement/example - I'd say it should be email UI engineer responsibility to properly set |
I agree, do any other design systems handle this for their consumers ? It seems that we are just trying to compensate for users that don't really know how to internationalize their app, in that case they should probably know how to internationalize their app 😅. Alternatively they can simply wrap our components in their own apps to do this behaviour if they want that ironclad bidirectionality, I thought that was the point of hooks composition: const IntlText = () => {
const state = useText();
state.dir = 'auto'
useTextStyles(state);
return renderText(state);
} |
not I'm aware of any. Chakra provides a step by step guide how to do it on your own :) https://chakra-ui.com/docs/features/rtl-support |
For Teams, this will mean ~50% of components will need to be decomposed and recomposed to contain logic for setting rtl=auto. That is possible - but we should think if it is the right way to aproach it. |
as far as I can see in the linked page, it is only about handling styles, not text direction |
I have rarely seen a UI/UX developer that thinks about this when creating UI. I have worked with some of the most experienced developers that created multiple widely used component libraies. I have worked with developers from Arabic countries and from Israel, where you would expect that this might be more common scenario to solve. In large-scale orgs that Fluent UI need to support, it is highly unlikely that devs will think about RTL in their daily work. This is our experience. Some of the issues can be found in automation, but text direction turned out to be the most tricky one. For Teams, adding support for RTL was a very painful process. To avoid such difficulties, @fluent-ui/react-northstar had a requiement to handle RTL as much as possible. This requirement is still valid for react-components. This RFC proposes a way how to achive it - but there of course might be other ways. However we cannot say that we won't fulfil this requirement. We need to find a way to consistently set direction for elements that output text that was entered by the users. Implementation is of course open for discussion. It can be a layer on top of Fluent UI components, but for the developer, it needs to be very convenient. |
Because this pull request has not had activity for over 150 days, we're automatically closing it for house-keeping purposes. The pull request will still be available for reference. If it's still relevant to merge at some point, you can reopen or make a new version based on the latest code. |
@jurokapsiar should we reopen this? |
This PR introduces RFC for handling bidirectional strings output using Fluent UI components