Skip to content

Commit

Permalink
add note about fake selections
Browse files Browse the repository at this point in the history
  • Loading branch information
KonnorRogers committed Nov 22, 2024
1 parent 4562d1f commit 7e6911f
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 63 deletions.
2 changes: 2 additions & 0 deletions docs/esbuild.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const esbuildOptions = {
assets: {
from: [path.resolve(__dirname, '../exports/styles/trix.css')],
to: [path.resolve(__dirname, 'src/rhino-editor/exports/styles/trix.css')],
from: [path.resolve(__dirname, '../exports/styles/rhino-editor.css')],
to: [path.resolve(__dirname, 'src/rhino-editor/exports/styles/rhino-editor.css')],
},
verbose: false,
watch: true,
Expand Down
21 changes: 21 additions & 0 deletions docs/src/_documentation/references/07-fake-selections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Fake Selections and Insertions
permalink: /references/fake-selections/
---

Rhino Editor has a couple of utilities for having "fake" insertions and selections.

You'll notice as of v0.14.0 when you move focus to the link dialog inputs, the editor will either show a fake insertion cursor, or show a fake selection "box" around the currently selected text.

There's also a fake cursor used for inline code blocks courtesy of the [Codemark Plugin](https://github.com/curvenote/editor/tree/main/packages/prosemirror-codemark)

The CSS for these fake selections comes directly from `"rhino-editor/exports/styles/trix.css"`.

However, some people may not use this because it can be overly opinionated. Fake selections / cursors can also be added to a CSS file via:

`@import "rhino-editor/exports/styles/rhino-editor.css"`

or from a JavaScript file:

`import "rhino-editor/exports/styles/rhino-editor.css"`

16 changes: 11 additions & 5 deletions esbuild.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ function AppendCssStyles () {
cursorStyles
} = await import(`./src/exports/styles/editor.js?cache=${date.toString()}`)

const finalString = `/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT BY HAND! */
${styles.toString()}
const banner = `/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT BY HAND! */`

const editorCSS = `
/* src/exports/styles/editor.js:hostStyles */
${hostStyles.toString()}
Expand All @@ -45,10 +46,15 @@ ${cursorStyles.toString()}
/* src/exports/styles/editor.js:toolbarButtonStyles */
${toolbarButtonStyles.toString()}
`
`.trim()

const trixCSS = `
${styles.toString()}
${editorCSS}
`.trim()

await fsPromises.writeFile(path.join(process.cwd(), "src", "exports", "styles", "trix.css"), finalString)
// await fsPromises.writeFile(path.join(process.cwd(), "exports", "styles", "trix.css"), finalString)
await fsPromises.writeFile(path.join(process.cwd(), "src", "exports", "styles", "trix.css"), banner + trixCSS)
await fsPromises.writeFile(path.join(process.cwd(), "src", "exports", "styles", "rhino-editor.css"), banner + editorCSS)
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/exports/extensions/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const selectionPlugin = (options: RhinoSelectionOptions) => {
// Show a fake cursor.
let widget = document.createElement("placeholder");
// TODO: Make this configurable.
widget.setAttribute("class", "rhino-fake-cursor-selection");
widget.setAttribute("class", "rhino-insertion-placeholder");
widget.setAttribute("readonly", "");
widget.setAttribute("contenteditable", "false");
deco = Decoration.widget(selection.to, widget, {});
Expand Down
4 changes: 2 additions & 2 deletions src/exports/styles/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ export const cursorStyles = css`
}
/** .fake-cursor-selection is for link "insertions" without selected text. */
:where(.rhino-editor) .rhino-fake-cursor-selection {
:where(.rhino-editor) .rhino-insertion-placeholder {
display: none;
user-select: none;
}
/**
This is used for showing a fake cursor for selections like link insertions
*/
:where(.rhino-editor)[link-dialog-expanded] .rhino-fake-cursor-selection {
:where(.rhino-editor)[link-dialog-expanded] .rhino-insertion-placeholder {
margin: 0;
padding: 0;
margin-right: -1px;
Expand Down
214 changes: 214 additions & 0 deletions src/exports/styles/rhino-editor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT BY HAND! *//* src/exports/styles/editor.js:hostStyles */

:host,
.trix-content {
/* General tokens */
--rhino-focus-ring: 0px 0px 1px 1px var(--rhino-button-active-border-color);
--rhino-border-radius: 4px;

--rhino-danger-border-color: red;
--rhino-danger-background-color: #ffdddd;

/* Editor tokens */
--rhino-text-color: #374151;
--rhino-dark-text-color: white;

--rhino-border-color: #cecece;
--rhino-placeholder-text-color: #cecece;
--rhino-dark-placeholder-text-color: gray;

/* Regular buttons */
--rhino-button-text-color: #889;
--rhino-button-dark-text-color: #eee;
--rhino-button-border-color: #cecece;

/** Disabled Buttons */
--rhino-button-disabled-text-color: #d1d5db;
--rhino-button-disabled-border-color: #d1d5db;
--rhino-button-disabled-background-color: #d1d5db;

/** Active buttons */
--rhino-button-active-border-color: #005a9c;
--rhino-button-active-background-color: rgb(226 239 255);

--rhino-toolbar-text-color: hsl(219, 6%, 43%);
--rhino-toolbar-icon-size: 1em;

--rhino-dialog-border-color: hsl(
var(--rhino-button-focus-background-color-hsl) / 50%
);

/** Focus buttons */
--rhino-button-focus-background-color: hsl(
var(--rhino-button-focus-background-color-hsl)
);

--rhino-button-focus-background-color-hsl: 219 26% 95%;

/**
* Override "--rhino-fake-selection-color" to change the color of .rhino-selection when the editor is not focused.
*/
--rhino-fake-selection-color: rgb(220, 220, 220);

display: block;

color: var(--rhino-text-color);
color: light-dark(var(--rhino-text-color), var(--rhino-dark-text-color));
}


/* src/exports/styles/editor.js:toolbarButtonStyles */

/**
* Cursor styles that are useful for providing a more "pleasant" editor experience.
*/
/**
* https://github.com/curvenote/editor/blob/main/packages/prosemirror-codemark/src/codemark.css
*/
@keyframes rhino-blink {
49% {
border-color: unset;
}
50% {
border-color: Canvas;
}
99% {
border-color: Canvas;
}
}
.rhino-editor .no-cursor {
caret-color: transparent;
}

:where(.rhino-editor) .fake-cursor {
margin: 0;
padding: 0;
margin-right: -1px;
border-left-width: 1px;
border-left-style: solid;
animation: rhino-blink 1s;
animation-iteration-count: infinite;
position: relative;
z-index: 1;
}

/** This is for actual "selection" which are highlighting more than 1 character. */
:where(.rhino-editor .ProseMirror):not(:focus-within) .rhino-selection {
background: var(--rhino-fake-selection-color);
}

/** .fake-cursor-selection is for link "insertions" without selected text. */
:where(.rhino-editor) .rhino-insertion-placeholder {
display: none;
user-select: none;
}

/**
This is used for showing a fake cursor for selections like link insertions
*/
:where(.rhino-editor)[link-dialog-expanded] .rhino-insertion-placeholder {
margin: 0;
padding: 0;
margin-right: -1px;
margin-left: -2px;
border-left-width: 4px;
border-left-style: solid;
border-color: Highlight;
position: relative;
z-index: 1;
display: inline;
}

.ProseMirror-separator {
display: none !important;
}


/* src/exports/styles/editor.js:toolbarButtonStyles */

.rhino-toolbar-button {
appearance: none;
-webkit-appearance: none;
border: 1px solid var(--rhino-border-color);
border-radius: var(--rhino-border-radius);
padding: 0.4em;
color: var(--rhino-button-text-color);
color: light-dark(
var(--rhino-button-text-color),
var(--rhino-button-dark-text-color)
);
background: Canvas;
font-size: inherit;
display: inline-grid;
}

.rhino-toolbar-button:is([aria-disabled="true"], :disabled) {
color: var(--rhino-button-disabled-text-color);
border-color: var(--rhino-button-disabled-border-color);
}

.rhino-toolbar-button[aria-disabled="true"]:focus {
border-color: var(--rhino-button-disabled-border-color);
}

.rhino-toolbar-button svg {
min-height: var(--rhino-toolbar-icon-size);
min-width: var(--rhino-toolbar-icon-size);

/* max-height / max-width needs to be set for safari */
max-height: var(--rhino-toolbar-icon-size);
max-width: var(--rhino-toolbar-icon-size);
}

.rhino-toolbar-button:is(:focus, :hover):not(
[aria-disabled="true"],
:disabled
) {
outline: transparent;
border-color: var(--rhino-button-active-border-color);
}

.rhino-toolbar-button:is(:focus):not([aria-disabled="true"], :disabled) {
box-shadow: var(--rhino-focus-ring);
}

/* Only change the background color in certain scenarios */
.rhino-toolbar-button:is(:hover):not(
[aria-disabled="true"],
:disabled,
[aria-pressed="true"],
[part~="toolbar__button--active"]
) {
background-color: var(--rhino-button-focus-background-color);
background-color: light-dark(
var(--rhino-button-focus-background-color),
gray
);
}

.rhino-toolbar-button:is([aria-disabled="true"], :disabled):not(
[part~="toolbar__button--active"]
) {
color: var(--rhino-button-disabled-text-color);
color: light-dark(var(--rhino-button-disabled-text-color), gray);
border-color: var(--rhino-button-disabled-border-color);
}

.rhino-toolbar-button:is(:focus, :hover):is(
[aria-disabled="true"],
:disabled
):not([part~="toolbar__button--active"]) {
outline: transparent;
color: var(--rhino-button-disabled-text-color);
color: light-dark(var(--rhino-button-disabled-text-color), gray);
border-color: var(--rhino-button-disabled-border-color);
box-shadow: 0 0 0 1px var(--rhino-button-disabled-border-color);
box-shadow: 0 0 0 1px
light-dark(var(--rhino-button-disabled-border-color), transparent);
}

svg,
::slotted(svg) {
height: var(--rhino-toolbar-icon-size);
width: var(--rhino-toolbar-icon-size);
}
Loading

0 comments on commit 7e6911f

Please sign in to comment.