-
Notifications
You must be signed in to change notification settings - Fork 8.6k
FEATURE: rich editor link ui for editing it #32583
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
Conversation
bc77e39
to
3c033a8
Compare
3c033a8
to
7a4687d
Compare
Can we avoid destroying/re-creating when my click ends up not changing the caret position? Kapture.2025-05-13.at.08.12.22.mp4 |
@chapoi It's not due to this work, but it's very annoying that showing a modal is removing the browsers scrollbars, it makes the page all jumpy, I know there are techniques to avoid this, could designers try to give it a go please? Kapture.2025-05-13.at.08.14.01.mp4 |
When I had focus through tab on one of the items menu and I press escape, I don't get back my caret position in the composer. |
Im not sure we should have cursor: pointer on the link given we now treat is as text. It's debatable, given this is still an action. But my reasoning is that seeing the cursor makes me think it's going to open the link right away. What do you think @chapoi ? |
When I edit a link by opening the modal, when I close it I don't get back my caret position in the composer. |
We have no spacing between the back button on edit mode: While in normal mode we have a lot of spacing: Doesnt feel right @chapoi |
Tricky one… I'd say keep the pointer, indicating something can be done feels most important. We could consider using
Yes, I know, but that left side spacing is very hard/impossible to get right due to the use of grid. I'll see if I can tweak it a bit.
Shouldn't that be "unlink"? |
FWIW slack is doing the regular text cursor, and some styling on hover of the link. |
Yes it should, but never got it showing |
@jjaffeux I’ll respond to the other things today, but getting this out first: Unlink is only available for non-autolinks, aren’t they working with I get it may be confusing, but I think supporting removing this autolink will still be confusing, with the caveat of being more work. Making a URL not autolink requires escaping it in the markdown, and I didn't think of a good way to make the escaped text linkable again/autolink on the rich editor - I think it's just simpler to omit the option in this case. |
OK I see, we can for sure start like this and see the feedback we get 👍 |
@jjaffeux I don't think we have an easy alternative in this case, what's destroying the menu is the EDIT: We can skip the menu's default |
Starts defining a more generic API, so a different toolbar instance can be used as a replacement on the main toolbar as well as a foundation for rendering the same toolbar as a floating element. This toolbar reuse started here for the link toolbar: #32583, then got extracted to this PR. --------- Co-authored-by: Sérgio Saquetim <1108771+megothss@users.noreply.github.com>
# Conflicts: # app/assets/javascripts/discourse/app/components/d-editor.gjs # app/assets/javascripts/discourse/tests/integration/components/d-editor-test.gjs # app/assets/stylesheets/common/d-editor.scss
Starts defining a more generic API, so a different toolbar instance can be used as a replacement on the main toolbar as well as a foundation for rendering the same toolbar as a floating element. This toolbar reuse started here for the link toolbar: #32583, then got extracted to this PR. --------- Co-authored-by: Sérgio Saquetim <1108771+megothss@users.noreply.github.com>
…iting modal behavior, floating positioning, etc
app/assets/javascripts/discourse/app/static/prosemirror/extensions/link-toolbar.js
Outdated
Show resolved
Hide resolved
if (event.key !== "Tab" || event.shiftKey) { | ||
return false; | ||
} | ||
|
||
const range = utils.getMarkRange( | ||
view.state.selection.$head, | ||
view.state.schema.marks.link | ||
); | ||
if (!range) { | ||
return false; | ||
} | ||
|
||
const activeMenu = document.querySelector( | ||
'[data-identifier="composer-link-toolbar"]' | ||
); | ||
if (!activeMenu) { | ||
return false; | ||
} | ||
|
||
event.preventDefault(); | ||
|
||
const focusable = activeMenu.querySelector( | ||
'button, a, [tabindex]:not([tabindex="-1"]), .select-kit' | ||
); | ||
|
||
if (focusable) { | ||
focusable.focus(); | ||
return true; | ||
} | ||
|
||
return false; |
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 have a better solution, but this part is unfortunate. Having to querySelector an element, always feels bad
updatePosition( | ||
menuInstance.trigger, | ||
menuInstance.content, | ||
{} | ||
); |
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 wonder if we shouldn't haven't this function on the menu instance itself, so we don't have to import float-kit internals
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.
Im pre-approving even if there are few thing to fix/improve, it's already working very well and in a good state.
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.
app/assets/javascripts/discourse/app/components/composer/toolbar-buttons.gjs
Outdated
Show resolved
Hide resolved
view.focus(); | ||
return false; | ||
} | ||
return rovingButtonBar(event); |
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.
Should we pass a containerClass here to be more specific, or would it be unnecessary?
@@ -18,7 +18,7 @@ import { i18n } from "discourse-i18n"; | |||
|
|||
export default class InsertHyperlink extends Component { |
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.
If this is only used in core, I would advise renaming this to UpsertHyperlink
or something for clarity to indicate it can be used for both insert + edit. If it's too much trouble + plugins are using it probably not necessary for now.
app/assets/javascripts/discourse/app/static/prosemirror/extensions/link-toolbar.js
Outdated
Show resolved
Hide resolved
Object.assign(linkState, attrs); | ||
} | ||
|
||
if (getContext().capabilities.viewport.sm) { |
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.
If I am reading this right, it's saying anything > small viewport (so anything not mobile) will do the DMenu stuff? I find this API a little tricky, because you can't reverse it without being verbose. For example the false condition which is a lot smaller means we are on mobile, but you can't do if (!getContext().capabilities.viewport.sm) { // replace toolbar }
because that will apply to XL and so on.
Would be cool if we had a viewport.lessThanSm
(with better naming) that uses max-width media queries for these scenarios.
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'll leave it as-is for now but I wonder if a "has pointer" check isn't best suited for this... we want to display the replaced toolbar because dealing with floating elements without a mouse isn't great, I think
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.
It's weird because we have this API in CSS but not in JS:
@include viewport.until(md)
But yeah having a pointer check could work too
@renato another one from the call today with Sam and Joffrey, if you are hovering on text and choose "Insert hyperlink" button, we don't prefill the text in the modal with the text under the cursor Also on the open external link button, we should change the tooltip to "Open link in external tab" or something rather than "Visit link" |
I responded on dev, I don't agree with this – and it's kind of a scope creep, let's discuss and address in a follow-up PR if needed. Having a single word under the cursor but NOT selected be auto-added while opening the Insert hyperlink modal seems like a stretch to me. |
Starts defining a more generic API, so a different toolbar instance can be used as a replacement on the main toolbar as well as a foundation for rendering the same toolbar as a floating element. This toolbar reuse started here for the link toolbar: #32583, then got extracted to this PR. --------- Co-authored-by: Sérgio Saquetim <1108771+megothss@users.noreply.github.com>
# Conflicts: # app/assets/stylesheets/common/d-editor.scss # spec/system/composer/prosemirror_editor_spec.rb
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.
Thanks for the refactors @renato , I think this is a lot clearer to read and follow and doesn't have the giant indentation issue either 👌
Displays a floating toolbar when the selection position is in a link, on desktop. On mobile, replaces the existing toolbar with the link toolbar temporarily.
Desktop
Kapture.2025-04-26.at.15.49.04.1.mp4
Mobile