playbook_ui 16.7.0.pre.alpha.PLAY2868datadefaultvalues16201 → 16.7.0.pre.alpha.PLAY2928removetrix16285

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +3 -2
  3. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -2
  4. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +2 -1
  5. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +31 -0
  6. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.html.erb +0 -2
  7. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.jsx +0 -2
  8. data/app/pb_kits/playbook/pb_date_picker/docs/_playground.json +1 -3
  9. data/app/pb_kits/playbook/pb_date_picker/docs/_playground.overrides.json +1 -3
  10. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +1 -1
  11. data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +262 -43
  12. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.html.erb +1 -0
  13. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.md +12 -0
  14. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_simple.html.erb +9 -0
  15. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_simple.md +8 -0
  16. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +2 -0
  17. data/app/pb_kits/playbook/pb_rich_text_editor/kit.schema.json +18 -9
  18. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +162 -0
  19. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +71 -0
  20. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_rails.js +202 -0
  21. data/dist/chunks/vendor.js +2 -2
  22. data/dist/menu.yml +1 -2
  23. data/dist/playbook.css +1 -1
  24. data/lib/playbook/version.rb +1 -1
  25. metadata +9 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8c942a94d890b530f5708a65f5fc6472d55b0b716f6ae45c236431d2750075d
4
- data.tar.gz: 479a54d947ce814bd8e939e63f73852edbd50f00130add31cb58391fcb2479b1
3
+ metadata.gz: 2239e69de7aee5cd1e20d3f9748fefbae1816ef4ba9853a3007da8d4d07fb506
4
+ data.tar.gz: ab819b0915d49393d5a302fc53f661f1b8b637ae6234c7682731d11703241fd7
5
5
  SHA512:
6
- metadata.gz: 597698fe69a18cb562969c3210cc2bec6c6453d81eb2e80609a08c3faef3ab58b8c6671f4544c8fbfe4689b405615ad55ce5dc5c350cda708a2ffcc25de062df
7
- data.tar.gz: 45c0cf03a2219898bab6cc3776bb220df91532eb03f8f78db98f7bb943f6824c89a5c430e6a4d9873b6962b3145ada1b79fe42d126b4e2bfe9f919a4f8be0041
6
+ metadata.gz: a738c39d91590b9e35bfb3c451878d718c11fb33c36a5f8d2bd4e8996870cacd791f775ab5d741631545f350895417c3f5ab870c839d5808293404a3f623f42c
7
+ data.tar.gz: 612c1c751828492b8bdbaed69d40f49a5da93e17e7ca69e6178b1d72d253bf4a445ba5f9975a5dbf82c794da1e3d2d8e4b0fbc947dcfa377f608a209089e3f0a
@@ -198,6 +198,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
198
198
  //@ts-ignore
199
199
  globalProps(filteredProps),
200
200
  error ? 'error' : null,
201
+ inLine && 'inline-date-picker',
201
202
  className
202
203
  )
203
204
 
@@ -280,7 +281,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
280
281
  }
281
282
  </div>
282
283
 
283
- {!hideIcon &&
284
+ {!hideIcon && !inLine &&
284
285
  <div
285
286
  className={iconWrapperClass()}
286
287
  id={`cal-icon-${pickerId}`}
@@ -292,7 +293,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
292
293
  </div>
293
294
  }
294
295
 
295
- {hideIcon && inLine ?
296
+ {inLine ?
296
297
  <div>
297
298
  <div
298
299
  className={`${iconWrapperClass()} date-picker-inline-icon-plus`}
@@ -42,7 +42,7 @@
42
42
  <input type="hidden" id="<%= "#{object.end_date_id}" %>" name="<%= "#{object.end_date_name}" %>">
43
43
  <% end %>
44
44
 
45
- <% if !object.hide_icon %>
45
+ <% if !object.hide_icon && !object.inline %>
46
46
  <div
47
47
  class="<%= object.icon_wrapper_class %>"
48
48
  id="cal-icon-<%= object.picker_id %>"
@@ -55,7 +55,7 @@
55
55
  <% end %>
56
56
 
57
57
  <!-- Inline -->
58
- <% if object.hide_icon && object.inline %>
58
+ <% if object.inline %>
59
59
  <!-- Plus Icon -->
60
60
  <div
61
61
  class="<%= object.icon_wrapper_class %> date-picker-inline-icon-plus"
@@ -92,7 +92,8 @@ module Playbook
92
92
 
93
93
  def classname
94
94
  default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
95
- generate_classname("pb_date_picker_kit") + default_margin_bottom
95
+ inline_class = inline ? " inline-date-picker" : ""
96
+ generate_classname("pb_date_picker_kit") + default_margin_bottom + inline_class
96
97
  end
97
98
 
98
99
  def date_picker_config
@@ -66,6 +66,37 @@ describe('DatePicker Kit', () => {
66
66
  expect(kit).not.toHaveAttribute('data-default-value')
67
67
  })
68
68
 
69
+ test('inLine alone adds inline-date-picker class and inline control icons, not the calendar icon', () => {
70
+ const testId = 'datepicker-inline-only'
71
+ render(
72
+ <DatePicker
73
+ data={{ testid: testId }}
74
+ inLine
75
+ pickerId="date-picker-inline-only"
76
+ />
77
+ )
78
+
79
+ const kit = screen.getByTestId(testId)
80
+ expect(kit).toHaveClass('inline-date-picker')
81
+ expect(kit.querySelector('#cal-icon-date-picker-inline-only')).not.toBeInTheDocument()
82
+ expect(kit.querySelector('#date-picker-inline-only-icon-plus')).toBeInTheDocument()
83
+ expect(kit.querySelector('#date-picker-inline-only-angle-down')).toBeInTheDocument()
84
+ })
85
+
86
+ test('hideIcon without inLine does not render inline control icons', () => {
87
+ const testId = 'datepicker-hide-icon-only'
88
+ render(
89
+ <DatePicker
90
+ data={{ testid: testId }}
91
+ hideIcon
92
+ pickerId="date-picker-hide-icon-only"
93
+ />
94
+ )
95
+
96
+ const kit = screen.getByTestId(testId)
97
+ expect(kit.querySelector('#date-picker-hide-icon-only-icon-plus')).not.toBeInTheDocument()
98
+ })
99
+
69
100
  test('shows DatePicker date format m/d/Y', async () => {
70
101
  const testId = 'datepicker-date'
71
102
  render(
@@ -1,6 +1,4 @@
1
1
  <%= pb_rails("date_picker", props: {
2
- classname: "inline-date-picker",
3
- hide_icon: true,
4
2
  inline: true,
5
3
  picker_id: "date-picker-inline"
6
4
  }) %>
@@ -6,8 +6,6 @@ const DatePickerInline = (props) => {
6
6
  return (
7
7
  <div>
8
8
  <DatePicker
9
- className="inline-date-picker"
10
- hideIcon
11
9
  inLine
12
10
  pickerId="date-picker-inline"
13
11
  {...props}
@@ -113,9 +113,7 @@
113
113
  "name": "inline_date",
114
114
  "pickerId": "playground-date-inline",
115
115
  "label": "Inline",
116
- "className": "inline-date-picker",
117
- "inLine": true,
118
- "hideIcon": true
116
+ "inLine": true
119
117
  }
120
118
  },
121
119
  {
@@ -88,9 +88,7 @@
88
88
  "name": "inline_date",
89
89
  "pickerId": "playground-date-inline",
90
90
  "label": "Inline",
91
- "className": "inline-date-picker",
92
- "inLine": true,
93
- "hideIcon": true
91
+ "inLine": true
94
92
  }
95
93
  },
96
94
  {
@@ -142,7 +142,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
142
142
  // Determine if toolbar should be shown
143
143
  const shouldShowToolbar = focus && advancedEditor ? showToolbarOnFocus : advancedEditorToolbar
144
144
 
145
- const labelFor = advancedEditor ? fieldId : (id ? id : (inputOptions.id ? `${inputOptions.id}_trix` : undefined))
145
+ const labelFor = advancedEditor ? fieldId : (id ? id : (inputOptions?.id ? `${inputOptions.id}_trix` : undefined))
146
146
 
147
147
  return (
148
148
  <div
@@ -8,38 +8,53 @@
8
8
  @import "../tokens/transition";
9
9
  @import "previewer_mixin";
10
10
 
11
- [class^="pb_rich_text_editor_kit"] {
12
- &.inline {
13
- .toolbar {
14
- opacity: 0;
15
- transition: all 0.3s ease-in-out 0s;
16
- }
17
-
18
- &:focus-within .toolbar {
19
- opacity: 100;
20
- }
21
-
22
- .ProseMirror {
23
- border: 1px solid transparent;
24
- transition: all 0.3s ease-in-out 0s;
25
- }
26
-
27
- &:focus-within .ProseMirror {
28
- border: 1px solid $input_border_default;
29
- border-top: none;
30
- }
31
-
32
- &:hover {
33
- .toolbar {
34
- opacity: 100;
35
- }
36
-
37
- .ProseMirror {
38
- border: 1px solid $input_border_default;
39
- border-top: none;
40
- }
41
- }
11
+ // Rails TipTap root: flex/grid children default to min-width: auto, so the toolbar’s
12
+ // intrinsic width can force horizontal page/dialog scroll. Pin the kit to the parent width.
13
+ [data-pb-rte-tiptap="true"] {
14
+ box-sizing: border-box;
15
+ display: block;
16
+ max-width: 100%;
17
+ min-width: 0;
18
+ width: 100%;
19
+ }
20
+
21
+ .pb_rich_text_editor_kit {
22
+ box-sizing: border-box;
23
+ max-width: 100%;
24
+ min-width: 0;
25
+
26
+ &.inline {
27
+ .toolbar {
28
+ opacity: 0;
29
+ transition: all 0.3s ease-in-out 0s;
30
+ }
31
+
32
+ &:focus-within .toolbar {
33
+ opacity: 100;
34
+ }
35
+
36
+ .ProseMirror {
37
+ border: 1px solid transparent;
38
+ transition: all 0.3s ease-in-out 0s;
39
+ }
40
+
41
+ &:focus-within .ProseMirror {
42
+ border: 1px solid $input_border_default;
43
+ border-top: none;
44
+ }
45
+
46
+ &:hover {
47
+ .toolbar {
48
+ opacity: 100;
49
+ }
50
+
51
+ .ProseMirror {
52
+ border: 1px solid $input_border_default;
53
+ border-top: none;
42
54
  }
55
+ }
56
+ }
57
+
43
58
  .toolbar_button {
44
59
  display: flex;
45
60
  align-items: center;
@@ -73,18 +88,76 @@
73
88
  }
74
89
  }
75
90
 
91
+ // Active state for toolbar (Rails kit uses pb_button_kit pb_button_link; override link variant when active)
92
+ .toolbar button.pb_button_kit.is-active {
93
+ color: $primary;
94
+ background-color: $bg_light;
95
+ }
96
+
76
97
  .pb_rich_text_editor_tiptap_toolbar_sticky {
77
98
  position: sticky;
78
99
  top: 0;
79
100
  z-index: 10;
80
101
  }
102
+
103
+ .rte-editor-wrap {
104
+ box-sizing: border-box;
105
+ max-width: 100%;
106
+ min-width: 0;
107
+ }
108
+
109
+ .pb_rich_text_editor_advanced_container {
110
+ max-width: 100%;
111
+ min-width: 0;
112
+ }
113
+
81
114
  .toolbar {
82
115
  border-radius: $border_rad_heaviest $border_rad_heaviest 0 0;
83
116
  border: 1px solid $input_border_default;
84
117
  overflow-x: auto;
118
+ // Single horizontal row + scroll in narrow modals/sidebars (wrap used to stack controls vertically).
85
119
  &_block {
120
+ align-items: center;
121
+ display: flex;
122
+ flex-wrap: nowrap;
86
123
  gap: $space_xs;
124
+ min-width: 0;
125
+ overflow-x: auto;
126
+ -webkit-overflow-scrolling: touch;
127
+ }
128
+
129
+ // React: keep one horizontal scroll on .toolbar (avoid nested scroll + trailing history cluster).
130
+ &:not(.rte-rails-toolbar-layout) {
131
+ > .pb_flex_kit.pb_flex_kit_justify_content_between {
132
+ box-sizing: border-box;
133
+ column-gap: $space_sm;
134
+ flex-wrap: nowrap;
135
+ justify-content: flex-start;
136
+ min-width: 100%;
137
+ width: max-content;
138
+ }
139
+
140
+ > .pb_flex_kit > .pb_flex_item_kit.toolbar_block {
141
+ flex: 0 0 auto;
142
+ min-width: 0;
143
+ overflow-x: visible;
144
+ }
145
+
146
+ > .pb_flex_kit > .pb_flex_item_kit:last-child {
147
+ flex: 0 0 auto;
148
+ }
87
149
  }
150
+
151
+ // Vertical section separators use ::before/::after with height: 100%. With
152
+ // align-items: center on .toolbar_block the kit’s cross size was 0, so the
153
+ // lines disappeared (master only had gap on .toolbar_block, default stretch).
154
+ .pb_section_separator_kit.pb_section_separator_vertical {
155
+ align-self: center;
156
+ flex-shrink: 0;
157
+ height: $space_xl;
158
+ }
159
+
160
+ // React ToolbarDropdown — match master (fixed width trigger; prod playbook.cloud).
88
161
  .editor-dropdown-button {
89
162
  background: transparent;
90
163
  border: none;
@@ -93,23 +166,115 @@
93
166
  font-weight: $light;
94
167
  padding: ($space_xs - 1) 0px;
95
168
  width: $space_xl * 3;
169
+
96
170
  &:focus-visible {
97
171
  box-shadow: unset;
98
172
  }
99
173
  }
174
+
175
+ &.rte-rails-toolbar-layout {
176
+ max-width: 100%;
177
+ min-width: 0;
178
+
179
+ .rte-rails-toolbar-row {
180
+ align-items: center;
181
+ box-sizing: border-box;
182
+ column-gap: $space_sm;
183
+ display: flex;
184
+ flex-wrap: nowrap;
185
+ justify-content: flex-start;
186
+ min-width: 100%;
187
+ padding: $space_xxs $space_sm;
188
+ width: max-content;
189
+ }
190
+
191
+ .rte-toolbar-left {
192
+ align-items: center;
193
+ display: flex;
194
+ flex: 0 0 auto;
195
+ flex-wrap: nowrap;
196
+ gap: $space_xs;
197
+ min-width: 0;
198
+ overflow-x: visible;
199
+ }
200
+
201
+ .rte-toolbar-right {
202
+ align-items: center;
203
+ display: flex;
204
+ flex: 0 0 auto;
205
+ gap: $space_xs;
206
+ }
207
+
208
+ // Align dropdown trigger with icon row (React wraps Popover + SectionSeparator in one flex line).
209
+ .pb_popover_reference_wrapper {
210
+ align-items: center;
211
+ display: inline-flex;
212
+ }
213
+
214
+ // Override master’s fixed-width React trigger: Rails block-style label + icons needs flexible width.
215
+ .editor-dropdown-button {
216
+ justify-content: flex-start;
217
+ letter-spacing: normal;
218
+ line-height: 1;
219
+ max-width: 100%;
220
+ min-height: unset;
221
+ padding: ($space_xs - 1) $space_xs;
222
+ text-align: left;
223
+ width: auto;
224
+
225
+ .pb_button_content {
226
+ align-items: center;
227
+ display: inline-flex;
228
+ line-height: 1;
229
+ }
230
+
231
+ .pb_button_content > .pb_flex_kit {
232
+ align-items: center;
233
+ }
234
+
235
+ .rte-block-style-trigger-inner {
236
+ align-items: center;
237
+ }
238
+
239
+ .rte-block-style-trigger-icon,
240
+ .rte-block-style-chevron {
241
+ display: inline-flex;
242
+ flex-shrink: 0;
243
+ line-height: 0;
244
+
245
+ .pb_icon_kit {
246
+ align-items: center;
247
+ display: flex;
248
+ line-height: 0;
249
+ }
250
+
251
+ svg {
252
+ display: block;
253
+ }
254
+ }
255
+
256
+ .rte-block-style-trigger-label {
257
+ align-items: center;
258
+ display: inline-flex;
259
+ line-height: 1.2;
260
+ }
261
+
262
+ &:focus-visible {
263
+ box-shadow: unset;
264
+ }
265
+ }
266
+ }
100
267
  }
101
268
 
269
+ // TipTap content — match master (prod playbook React tab).
102
270
  .ProseMirror {
103
271
  background: $white;
104
272
  border: 1px solid $input_border_default;
105
273
  border-radius: $border_rad_heaviest;
106
274
  height: 100%;
107
- padding: 1rem 1.5rem 1.5rem 1.5rem;
108
275
  line-height: $lh_loose;
276
+ padding: 1rem 1.5rem 1.5rem 1.5rem;
109
277
  @include transition_default;
110
- :first-child {
111
- margin-top: 0;
112
- }
113
278
 
114
279
  h4,
115
280
  h5,
@@ -161,9 +326,32 @@
161
326
  ul {
162
327
  @include preview_tiptap_ul;
163
328
  }
329
+
330
+ // After heading mixins: first block should not pick up extra top margin (wins over `p { margin-top: 1rem }`).
331
+ > :first-child {
332
+ margin-top: 0;
333
+ }
334
+ }
335
+
336
+ // Toolbar + editor stack: toolbar keeps its border; editor has no top stroke (classic layout).
337
+ // Avoid relying on a wrapper-only frame — partial deploys then looked “borderless” because
338
+ // ProseMirror had been forced to border: none.
339
+ .pb_rich_text_editor_advanced_container.toolbar-active {
340
+ .ProseMirror {
341
+ border-top: none;
342
+ border-top-left-radius: initial;
343
+ border-top-right-radius: initial;
344
+ }
164
345
  }
165
346
  }
166
347
 
348
+ // Rails-only: outer kit sets `data-pb-rte-tiptap` — roomier padding + wrapping for vanilla TipTap in forms/dialogs.
349
+ [data-pb-rte-tiptap="true"] .pb_rich_text_editor_kit .ProseMirror {
350
+ overflow-wrap: anywhere;
351
+ padding: 1.25rem 1.5rem 1.5rem 1.5rem;
352
+ word-break: break-word;
353
+ }
354
+
167
355
  .pb_tiptap_toolbar_dropdown_list_item {
168
356
  &.is-active,
169
357
  &:active {
@@ -188,20 +376,51 @@
188
376
  }
189
377
  }
190
378
  }
191
- .pb_rich_text_editor_advanced_container {
379
+
380
+ // Rails RTE: block-style menu uses Nav (popover) instead of React NavItem class hook.
381
+ .pb_rich_text_editor_kit .pb_popover_tooltip .pb_nav_list_item_link.is-active {
382
+ background-color: $bg_light;
383
+ border-radius: unset !important;
384
+ color: $primary;
385
+
386
+ .pb_nav_list_item_text,
387
+ .pb_nav_list_item_icon_left {
388
+ color: $primary !important;
389
+ }
390
+ }
391
+
392
+ .pb_rich_text_editor_kit .pb_popover_tooltip .pb_nav_list_kit_item:hover .pb_nav_list_item_link:not(.is-active) {
393
+ background-color: $neutral_subtle;
394
+ border-radius: unset !important;
395
+
396
+ .pb_nav_list_item_text,
397
+ .pb_nav_list_item_icon_left {
398
+ background-color: unset;
399
+ color: $text_lt_light !important;
400
+ }
401
+ }
402
+
403
+ // No toolbar: ring the whole control.
404
+ .pb_rich_text_editor_advanced_container:not(.toolbar-active) {
192
405
  transition: box-shadow 0.3s ease-in-out, border-radius 0.3s ease-in-out;
193
406
  &:focus-visible,
194
407
  &:focus-within {
195
- outline: unset;
196
- box-shadow: 0 0 0 1px $input_border_state;
197
408
  border-radius: $border_rad_heaviest;
409
+ box-shadow: 0 0 0 1px $input_border_state;
410
+ outline: unset;
198
411
  transition: box-shadow 0.3s ease-in-out, border-radius 0.3s ease-in-out;
199
412
  }
200
- &.toolbar-active {
201
- .ProseMirror {
202
- border-top: none;
203
- border-top-left-radius: initial;
204
- border-top-right-radius: initial;
413
+ }
414
+
415
+ // Toolbar + editor: use border color (not an outer box-shadow) so the bottom isn’t doubled.
416
+ .pb_rich_text_editor_advanced_container.toolbar-active {
417
+ &:focus-within {
418
+ .toolbar {
419
+ border-color: $input_border_state;
420
+ }
421
+
422
+ .ProseMirror {
423
+ border-color: $input_border_state;
205
424
  }
206
425
  }
207
426
  }
@@ -0,0 +1 @@
1
+ <%= pb_rails("rich_text_editor", props: { input_options: { id: 'hidden_input_id', name: "hidden_input_name" }, value: "Add your text here. You can format your text, add links, quotes, and bullets." }) %>
@@ -0,0 +1,12 @@
1
+ The Rails rich text editor is a TipTap surface with no React. The UI (toolbar, block-style menu, formatting actions) is rendered with Playbook Rails kits (`pb_rails`). The editor document is a vanilla TipTap `Editor` instance; HTML is synced to a hidden `<input>` so standard Rails forms can submit the value.
2
+
3
+ ### How TipTap is loaded (Rails)
4
+
5
+ - The kit’s module script (`rich_text_editor_rails.js`) uses `import()` with **full URLs** on [esm.sh](https://esm.sh) (e.g. `@tiptap/core@2.8.0`). esm.sh resolves dependencies server-side, so **no `<script type="importmap">`** is required—this avoids conflicts when the host page already has an import map (e.g. Vite in dev, or another app map) because Firefox only applies one native map.
6
+ - You do not need TipTap in your app’s npm dependencies or Gemfile for this kit; the browser loads modules from esm.sh when the page runs.
7
+ - Ensure **CSP** allows loading scripts from `https://esm.sh` (and esm.sh’s redirected module URLs) if you use a strict `script-src` / `connect-src`.
8
+
9
+ ### Relation to the React implementation
10
+
11
+ - Same core: both use TipTap v2 on top of ProseMirror; styling lives in Playbook SCSS (`_tiptap_styles.scss`) so the editor chrome lines up between platforms.
12
+ - Different shell: Rails uses ERB + Playbook Rails components + inline module script. React uses `RichTextEditor` / `_tiptap_editor.tsx` and TipTap wired through the bundled Playbook React package—see Advanced Default for that stack and when you need TipTap installed in your JavaScript bundle.
@@ -0,0 +1,9 @@
1
+ <%= pb_rails("rich_text_editor", props: {
2
+ simple: true,
3
+ label: "Notes",
4
+ input_options: {
5
+ id: "rails_rte_simple_demo",
6
+ name: "content",
7
+ },
8
+ value: "<p>Use <strong>Bold</strong> and <em>Italic</em> from the toolbar.</p>",
9
+ }) %>
@@ -0,0 +1,8 @@
1
+ ### Simple toolbar (`simple: true`)
2
+
3
+ Pass **`simple: true`** for a compact toolbar: **Bold**, **Italic**, **Undo**, and **Redo** (same history controls as the full toolbar—plain buttons, not popovers).
4
+
5
+ - No block-style dropdown (no “Paragraph” / headings / lists in the menu).
6
+ - No **`pb_popover`** on the toolbar—useful in **native `<dialog>`** modals, turbo-loaded panels, or other tight layouts where the full block menu is awkward to position.
7
+
8
+ The underlying TipTap document still accepts the same HTML as the default Rails editor; `simple` only changes which **toolbar controls** are shown.
@@ -1,6 +1,8 @@
1
1
  examples:
2
2
 
3
3
  rails:
4
+ - rich_text_editor_rails_default: "Rails (TipTap)"
5
+ - rich_text_editor_rails_simple: "Rails (TipTap — Simple toolbar)"
4
6
 
5
7
  react:
6
8
  - rich_text_editor_advanced_default: Advanced Default
@@ -3,7 +3,8 @@
3
3
  "name": "RichTextEditor",
4
4
  "description": "RichTextEditor component",
5
5
  "platforms": [
6
- "react"
6
+ "react",
7
+ "rails"
7
8
  ],
8
9
  "props": {
9
10
  "advancedEditor": {
@@ -33,7 +34,8 @@
33
34
  "inputOptions": {
34
35
  "type": "GenericObject",
35
36
  "platforms": [
36
- "react"
37
+ "react",
38
+ "rails"
37
39
  ]
38
40
  },
39
41
  "inline": {
@@ -45,7 +47,8 @@
45
47
  "label": {
46
48
  "type": "string",
47
49
  "platforms": [
48
- "react"
50
+ "react",
51
+ "rails"
49
52
  ]
50
53
  },
51
54
  "extensions": {
@@ -69,7 +72,8 @@
69
72
  "placeholder": {
70
73
  "type": "string",
71
74
  "platforms": [
72
- "react"
75
+ "react",
76
+ "rails"
73
77
  ]
74
78
  },
75
79
  "inputHeight": {
@@ -97,14 +101,18 @@
97
101
  "requiredIndicator": {
98
102
  "type": "boolean",
99
103
  "platforms": [
100
- "react"
101
- ]
104
+ "react",
105
+ "rails"
106
+ ],
107
+ "default": false
102
108
  },
103
109
  "simple": {
104
110
  "type": "boolean",
105
111
  "platforms": [
106
- "react"
107
- ]
112
+ "react",
113
+ "rails"
114
+ ],
115
+ "default": false
108
116
  },
109
117
  "sticky": {
110
118
  "type": "boolean",
@@ -121,7 +129,8 @@
121
129
  "value": {
122
130
  "type": "string",
123
131
  "platforms": [
124
- "react"
132
+ "react",
133
+ "rails"
125
134
  ]
126
135
  },
127
136
  "maxWidth": {