Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 43 additions & 0 deletions docs/documentation/docs/controls/RichText.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ const onRenderCustomLabel = (rtProps: IRichTextProps): JSX.Element => {
}
```

It is also possible to provide custom formatting styles for built-in rich text elements. These styles are scoped to the current RichText instance and applied both in edit mode and read-only mode.

```TypeScript
<RichText
value={this.props.value}
customStyles={{
normal: {
color: '#323130',
lineHeight: 1.6
},
header2: {
fontSize: '30px',
color: '#005a9e'
},
blockQuote: {
backgroundColor: '#f3f2f1',
borderLeft: '4px solid #005a9e',
paddingLeft: '12px'
}
}}
onChange={(text) => this.onTextChange(text)}
/>
```

## Implementation

The RichText control can be configured with the following properties:
Expand All @@ -72,11 +96,29 @@ The RichText control can be configured with the following properties:
| className | string | no | The custom CSS class to apply to the RichText control. |
| style | React.CSSProperties | no | The custom styles to apply to the RichText control. |
| isEditMode | boolean | no | `true` indicates that users will be able to edit the content of the RichText control. `false` will display the rich text as read-only. |
| placeholder | string | no | Placeholder text to show when the editor is empty. |
| styleOptions | StyleOptions | no | Define the styles you want to show or hide for the rich text editor |
| value | string | no | Sets the rich text to display in the RichText control. |
| customColors | ISwatchColor[] | no | Additional colors to include in the side-panel font color swatch. |
| customStyles | IRichTextCustomFormattingStyles | no | Object-based formatting styles applied by the control to built-in rich text elements such as normal text, headings, block quotes, and lists. |
| onChange | (text: string) => string | no | onChange handler for the RichText control. The function must return a `string` containing the rich text to display in the RichText control. |
| onRenderLabel | (props: IRichTextProps) => JSX.Element | no | Custom renderer for the RichText control's label. The function must return a `JSX.Element`. |

`IRichTextCustomFormattingStyles` interface

| Property | Type | Required | Description |
| ---- | ---- | ---- | ---- |
| normal | React.CSSProperties | no | Styles applied to the root rich text content. |
| header2 | React.CSSProperties | no | Styles applied to `h2` content. |
| header3 | React.CSSProperties | no | Styles applied to `h3` content. |
| header4 | React.CSSProperties | no | Styles applied to `h4` content. |
| blockQuote | React.CSSProperties | no | Styles applied to `blockquote` content. |
| div | React.CSSProperties | no | Styles applied to `div` content. |
| p | React.CSSProperties | no | Styles applied to `p` content. |
| ul | React.CSSProperties | no | Styles applied to `ul` content. |
| ol | React.CSSProperties | no | Styles applied to `ol` content. |
| li | React.CSSProperties | no | Styles applied to `li` content. |

`StyleOptions` interface

| Property | Type | Required | Description |
Expand All @@ -86,6 +128,7 @@ The RichText control can be configured with the following properties:
| showItalic | boolean | no | Indicates whether to show the **Italic** toolbar button or not. Default value is `true` |
| showLink | boolean | no | Indicates whether to show the **Hyperlink** toolbar button or not. Default value is `true` |
| showList | boolean | no | Indicates whether to show the **List** toolbar button or not. Default value is `true` |
| showImage | boolean | no | Indicates whether to show the **Image** toolbar button or not. Default value is `true` |
| showMore | boolean | no | Indicates whether to show the **More** toolbar button or not. Note that this option is independent from the other `show___` options. I.e.: Setting `showBold` to `false` will disable the **Bold** toolbar, but will not disable it from the formatting pane. Default value is `true` |
| showStyles | boolean | no | Indicates whether to show the **Headings** toolbar button or not. Note that this option is independent from the other `show___` options. I.e.: Setting `showBold` to `false` will disable the **Bold** toolbar, but will not disable it from the formatting pane. Default value is `true` |
| showUnderline | boolean | no | Indicates whether to show the **Underline** toolbar button or not. Note that this option is independent from the other `show___` options. I.e.: Setting `showBold` to `false` will disable the **Bold** toolbar, but will not disable it from the formatting pane. Default value is `true` |
Expand Down
94 changes: 55 additions & 39 deletions src/controls/richText/RichText.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
@import 'pkg:@fluentui/react/dist/sass/References.scss';

:export {
NeutralLighterAlt: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
NeutralPrimary: "[theme:neutralPrimary, default:#{$ms-color-neutralPrimary}]";
NeutralTertiary: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]";
ThemePrimary: "[theme:themePrimary, default:#{$ms-color-themePrimary}]";
NeutralLighter: "[theme:neutralLighter, default:#{$ms-color-neutralLighter}]";
NeutralDark: "[theme:neutralDark, default:#{$ms-color-neutralDark}]";
ThemeDarker: "[theme:themeDarker, default:#{$ms-color-themeDarker}]";
White: "[theme:white, default:#{$ms-color-white}]";
}

.richtext {
color: inherit;
}
Expand Down Expand Up @@ -96,20 +107,23 @@
font-style: normal;
font-weight: normal;
font-size: 8px;
speak: none;
top: 50%;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
color: var(--rt-neutralLighterAlt, #f8f8f8);
}

.toolbarSubmenuDisplayButton {
width: 100%;
}

.editorShell {
position: relative;
}

:global {
.pnp-richtext-quill-container {
.ql-toolbar {
background-color: transparent;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
color: var(--rt-neutralLighterAlt, #f8f8f8);
border: none;
display: none;

Expand All @@ -122,31 +136,31 @@
}

.ms-Button {
background-color: "[theme:neutralPrimary, default:#{$ms-color-neutralPrimary}]";
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]" !important;
background-color: var(--rt-neutralPrimary, #323130);
color: var(--rt-neutralLighterAlt, #f8f8f8) !important;

&:hover {
background-color: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]";
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
background-color: var(--rt-neutralTertiary, #a19f9d);
color: var(--rt-neutralLighterAlt, #f8f8f8);
}

&:focus {
border: 1px solid "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
border: 1px solid var(--rt-neutralLighterAlt, #f8f8f8);
outline: 0;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
color: var(--rt-neutralLighterAlt, #f8f8f8);
}

&:active {
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
color: var(--rt-neutralLighterAlt, #f8f8f8);
}

&.is-checked {
background-color: "[theme:themePrimary, default:#{$ms-color-themePrimary}]" !important;
background-color: var(--rt-themePrimary, #0078d4) !important;
}
}
.ms-Dropdown-title {
background-color: "[theme:neutralPrimary, default:#{$ms-color-neutralPrimary}]";
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]" !important;
background-color: var(--rt-neutralPrimary, #323130);
color: var(--rt-neutralLighterAlt, #f8f8f8) !important;
border: none;
min-height: 34px;
padding-bottom: 0px;
Expand All @@ -156,21 +170,22 @@
-webkit-transition: all 0.3s;
transition: all 0.3s;
-webkit-transition-property: background-color, color;
transition-property: background-color, color;
border-radius: 0;

&:hover {
background-color: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]";
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
background-color: var(--rt-neutralTertiary, #a19f9d);
color: var(--rt-neutralLighterAlt, #f8f8f8);
}

&:focus {
border: 1px solid "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
border: 1px solid var(--rt-neutralLighterAlt, #f8f8f8);
outline: 0;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
color: var(--rt-neutralLighterAlt, #f8f8f8);
}

&:active {
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
color: var(--rt-neutralLighterAlt, #f8f8f8);
}
}

Expand All @@ -182,8 +197,8 @@

.ql-snow.ql-toolbar button,
.ql-snow .ql-toolbar button {
background-color: "[theme:neutralPrimary, default:#{$ms-color-neutralPrimary}]";
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]";
background-color: var(--rt-neutralPrimary, #323130);
color: var(--rt-neutralLighterAlt, #f8f8f8);
font-size: 16px;
min-width: 34px;
height: 34px;
Expand All @@ -198,7 +213,7 @@
font-family: "Segoe UI Web (West European)", Segoe UI, -apple-system,
BlinkMacSystemFont, Roboto, Helvetica Neue, sans-serif;
border: none;
margin-bottom: 2px;
margin-bottom: 0;
z-index: 3;
-webkit-animation-name: ms-fadeIn, ms-slideUpIn10;
animation-name: ms-fadeIn, ms-slideUpIn10;
Expand All @@ -225,21 +240,22 @@
.ql-active .ql-editor:hover {
border-width: 1px;
border-style: solid;
border-color: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]";
border-color: var(--rt-neutralTertiary, #a19f9d);
}

.ql-active .ql-editor:focus,
.ql-active .ql-editor:active,
.ql-active .ql-editor:active:hover {
border-width: 1px;
border-style: solid;
border-color: "[theme:themePrimary, default:#{$ms-color-themePrimary}]";
border-color: var(--rt-themePrimary, #0078d4);
}

.ql-active .ql-toolbar {
display: inline-flex;
position: absolute;
top: -28px;
bottom: 100%;
left: 0;
opacity: 1;
height: 34px;
-webkit-box-shadow: 0 0 5px 0 #c8c8c8;
Expand Down Expand Up @@ -282,12 +298,11 @@
ul {
-webkit-font-smoothing: antialiased;
line-height: 1.3;
// margin: 0 0 16px;
word-wrap: break-word;
}

blockquote {
border-bottom-color: "[theme:neutralLighter, default:#{$ms-color-neutralLighter}]";
border-bottom-color: var(--rt-neutralLighter, #edebe9);
border-bottom-style: solid;
border-bottom-width: 1px;
border-left-style: none;
Expand All @@ -296,7 +311,7 @@
border-right-style: none;
border-right-width: 0;
border-right-color: transparent;
border-top-color: "[theme:neutralLighter, default:#{$ms-color-neutralLighter}]";
border-top-color: var(--rt-neutralLighter, #edebe9);
border-top-style: solid;
border-top-width: 1px;
font-size: 20px;
Expand Down Expand Up @@ -385,7 +400,7 @@

.ql-editor.ql-blank::before {
font-style: normal;
color: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]";
color: var(--rt-neutralTertiary, #a19f9d);
font-size: 18px;
font-weight: 400;
line-height: 1.3;
Expand All @@ -396,9 +411,9 @@
.ql-editor {
border-width: 1px;
border-style: solid;
border-color: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]";
border-color: var(--rt-neutralTertiary, #a19f9d);
&:hover {
border-color: "[theme:neutralDark, default:#{$ms-color-neutralDark}]";
border-color: var(--rt-neutralDark, #201f1e);
}
&:active::after, &:active:focus::after, &:active:hover::after, &:focus::after {
content: "";
Expand All @@ -407,7 +422,7 @@
border-style: solid;
border-width: 2px;
inset: -1px;
border-color: "[theme:themePrimary, default:#{$ms-color-themePrimary}]";
border-color: var(--rt-themePrimary, #0078d4);
border-radius: 2px;
}
}
Expand All @@ -416,9 +431,9 @@
// hyperlink color on dark theme
.ql-editor {
a {
color: "[theme:themePrimary, default: #{$ms-color-themePrimary}]";
color: var(--rt-themePrimary, #0078d4);
&:hover {
color: "[theme:themeDarker, default: #{$ms-color-themeDarker}]";
color: var(--rt-themeDarker, #004578);
}
}
}
Expand All @@ -430,23 +445,24 @@

div#DropDownStyles-list, div#DropDownAlign-list, div#DropDownLists-list {
.ms-Dropdown-item {
background-color: "[theme:neutralPrimary, default:#{$ms-color-neutralPrimary}]" !important;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]" !important;
background-color: var(--rt-neutralPrimary, #323130) !important;
color: var(--rt-neutralLighterAlt, #f8f8f8) !important;
-webkit-transition: all 0.3s;
transition: all 0.3s;
-webkit-transition-property: background-color, color;
transition-property: background-color, color;
}

.ms-Dropdown-item:hover {
background-color: "[theme:neutralTertiary, default:#{$ms-color-neutralTertiary}]" !important;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]" !important;
background-color: var(--rt-neutralTertiary, #a19f9d) !important;
color: var(--rt-neutralLighterAlt, #f8f8f8) !important;
cursor: pointer;
}

.ms-Dropdown-item.is-selected,
.ms-Dropdown-item.is-selected:hover {
background-color: "[theme:themePrimary, default:#{$ms-color-themePrimary}]" !important;
color: "[theme:neutralLighterAlt, default:#{$ms-color-neutralLighterAlt}]" !important;
background-color: var(--rt-themePrimary, #0078d4) !important;
color: var(--rt-neutralLighterAlt, #f8f8f8) !important;
}
}
}
Expand Down
Loading