Content
-{{ content }}
+ {{ content }}
diff --git a/demos/setup/style.scss b/demos/setup/style.scss index f7509f871..b637b3410 100644 --- a/demos/setup/style.scss +++ b/demos/setup/style.scss @@ -1,4 +1,23 @@ -$colorBlack: #000; +/* Base HTML and global element styles*/ +:root { + --white: #FFF; + --black: #2E2B29; + --black-contrast: #110F0E; + --gray-1: rgba(61, 37, 20, 0.05); + --gray-2: rgba(61, 37, 20, 0.08); + --gray-3: rgba(61, 37, 20, 0.12); + --gray-4: rgba(53, 38, 28, 0.30); + --gray-5: rgba(28, 25, 23, 0.60); + --purple: #6A00F5; + --purple-contrast: #5800CC; + --purple-light: rgba(88, 5, 255, 0.05); + --yellow-contrast: #FACC15; + --yellow: rgba(250, 204, 21, 0.4); + --yellow-light: #FFFAE5; + --red: #FF5C33; + --red-light: #FFEBE5; + --shadow: 0px 12px 33px 0px rgba(0, 0, 0, 0.06), 0px 3.618px 9.949px 0px rgba(0, 0, 0, 0.04); +} *, *::before, @@ -9,32 +28,46 @@ $colorBlack: #000; html { font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; line-height: 1.5; - -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; } body { - margin: 1rem; min-height: 10rem; + margin: 0; } +:first-child { + margin-top: 0; +} + +.tiptap { + caret-color: var(--purple); + margin: 1.5rem; + + &:focus { + outline: none; + } +} + +/* Custom scrollbar styles */ ::-webkit-scrollbar { - width: 14px; height: 14px; + width: 14px; } ::-webkit-scrollbar-track { - border: 4px solid transparent; background-clip: padding-box; - border-radius: 8px; background-color: transparent; + border: 4px solid transparent; + border-radius: 8px; } ::-webkit-scrollbar-thumb { - border: 4px solid rgba(0, 0, 0, 0); background-clip: padding-box; - border-radius: 8px; background-color: rgba(0, 0, 0, 0); + border: 4px solid rgba(0, 0, 0, 0); + border-radius: 8px; } :hover::-webkit-scrollbar-thumb { @@ -47,37 +80,276 @@ body { ::-webkit-scrollbar-button { display: none; - width: 0; height: 0; + width: 0; } ::-webkit-scrollbar-corner { background-color: transparent; } +/* Specific element and component styles */ button, input, -select { - font-size: inherit; +select, +textarea { + background: var(--gray-2); + border-radius: 0.5rem; + border: none; + color: var(--black); font-family: inherit; - color: black; - margin: 0.1rem; - border: 1px solid black; - border-radius: 0.3rem; - padding: 0.1rem 0.4rem; - background: white; - accent-color: black; + font-size: 0.875rem; + font-weight: 500; + line-height: 1.15; + margin: none; + padding: 0.375rem 0.625rem; + transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1); + + &:hover { + background-color: var(--gray-3); + color: var(--black-contrast); + } &[disabled] { - opacity: 0.3; + background: var(--gray-1); + color: var(--gray-4); + } + + &:checked { + accent-color: var(--purple); + } + + &.primary { + background: var(--black); + color: var(--white); + + &:hover { + background-color: var(--black-contrast); + } + + &[disabled] { + background: var(--gray-1); + color: var(--gray-4); + } + } + + &.is-active { + background: var(--purple); + color: var(--white); + + &:hover { + background-color: var(--purple-contrast); + color: var(--white); + } } } -.tiptap:focus { - outline: none; +button:not([disabled]), +select:not([disabled]) { + cursor: pointer; } -.is-active { - background: black; - color: white; +input[type="text"], +textarea { + background-color: unset; + border: 1px solid var(--gray-3); + border-radius: 0.5rem; + color: var(--black); + + &::placeholder { + color: var(--gray-4); + } + + &:hover { + background-color: unset; + border-color: var(--gray-4); + } + + &:focus-visible, &:focus { + border-color: var(--purple); + outline: none; + } } + +select { + /* reset */ + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position: right 0.1rem center; + background-size: 1.25rem 1.25rem; + padding-right: 1.25rem; + + &:focus { + outline: 0; + } +} + +form { + align-items: flex-start; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.hint { + align-items: center; + background-color: var(--yellow-light); + border-radius: 0.5rem; + border: 1px solid var(--gray-2); + display: flex; + flex-direction: row; + font-size: 0.75rem; + gap: 0.5rem; + line-height: 1.15; + min-height: 1.75rem; + padding: 0.25rem 0.5rem; + + &.purple-spinner, + &.error { + justify-content: center; + text-align: center; + width: 100%; + } + + &.purple-spinner { + background-color: var(--purple-light); + + &::after { + content: ""; + background-image: url("data:image/svg+xml;utf8,"); + background-size: cover; + background-repeat: no-repeat; + background-position: center; + height: 1rem; + width: 1rem; + } + } + + &.error { + background-color: var(--red-light); + } +} + +.label, +.label-small, +.label-large { + color: var(--black); + font-size: 0.8125rem; + font-weight: 500; + line-height: 1.15; +} + +.label-small { + color: var(--gray-5); + font-size: 0.75rem; + font-weight: 400; +} + +.label-large { + font-size: 0.875rem; + font-weight: 700; +} + +hr { + border: none; + border-top: 1px solid var(--gray-3); + margin: 0; + width: 100%; +} + +/* Layout and structure */ +#app, +.container { + display: flex; + flex-direction: column; +} + +.button-group { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; +} + +.control-group { + align-items: flex-start; + display: flex; + flex-direction: column; + gap: 1rem; + margin: 1.5rem; +} + +[data-node-view-wrapper] > .control-group { + margin: 1.5rem 0; +} + +.flex-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1rem; + justify-content: space-between; + width: 100%; +} + +.switch-group { + align-items: center; + background: var(--gray-2); + border-radius: 0.5rem; + display: flex; + flex-direction: row; + flex-wrap: wrap; + flex: 0 1 auto; + justify-content: flex-start; + padding: 0.125rem; + + label { + align-items: center; + border-radius: 0.375rem; + color: var(--gray-5); + cursor: pointer; + display: flex; + flex-direction: row; + font-size: 0.75rem; + font-weight: 500; + gap: 0.25rem; + line-height: 1.15; + min-height: 1.5rem; + padding: 0 0.375rem; + transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1); + + &:has(input:checked) { + background-color: var(--white); + color: var(--black-contrast); + } + + &:hover { + color: var(--black); + } + + input { + display: none; + margin: unset; + } + } +} + +.output-group { + background-color: var(--gray-1); + display: flex; + flex-direction: column; + font-family: 'JetBrainsMono', monospace; + font-size: 0.75rem; + gap: 1rem; + margin-top: 2.5rem; + padding: 1.5rem; + + label { + color: var(--black); + font-size: 0.875rem; + font-weight: 700; + line-height: 1.15; + } +} \ No newline at end of file diff --git a/demos/src/Commands/Cut/React/index.jsx b/demos/src/Commands/Cut/React/index.jsx index 3b5164055..66a871ec2 100644 --- a/demos/src/Commands/Cut/React/index.jsx +++ b/demos/src/Commands/Cut/React/index.jsx @@ -21,10 +21,12 @@ const MenuBar = ({ editor }) => { }, [editor]) return ( - <> - - - > +
- this is a basic example of tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists: + this is a basic example of Tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
- this is a basic example of tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists: + this is a basic example of Tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
body {
-display: none;
+ display: none;
}
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too. diff --git a/demos/src/Examples/Default/React/index.spec.js b/demos/src/Examples/Default/React/index.spec.js index b23e72c17..005560dee 100644 --- a/demos/src/Examples/Default/React/index.spec.js +++ b/demos/src/Examples/Default/React/index.spec.js @@ -21,41 +21,41 @@ context('/src/Examples/Default/React/', () => { }) const buttonMarks = [ - { label: 'bold', tag: 'strong' }, - { label: 'italic', tag: 'em' }, - { label: 'strike', tag: 's' }, + { label: 'Bold', tag: 'strong' }, + { label: 'Italic', tag: 'em' }, + { label: 'Strike', tag: 's' }, ] buttonMarks.forEach(m => { it(`should disable ${m.label} when the code tag is enabled for cursor`, () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('code').click() + cy.get('button').contains('Code').click() cy.get('button').contains(m.label).should('be.disabled') }) it(`should enable ${m.label} when the code tag is disabled for cursor`, () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('code').click() - cy.get('button').contains('code').click() + cy.get('button').contains('Code').click() + cy.get('button').contains('Code').click() cy.get('button').contains(m.label).should('not.be.disabled') }) it(`should disable ${m.label} when the code tag is enabled for selection`, () => { cy.get('.tiptap').type('{selectall}Hello world{selectall}') - cy.get('button').contains('code').click() + cy.get('button').contains('Code').click() cy.get('button').contains(m.label).should('be.disabled') }) it(`should enable ${m.label} when the code tag is disabled for selection`, () => { cy.get('.tiptap').type('{selectall}Hello world{selectall}') - cy.get('button').contains('code').click() - cy.get('button').contains('code').click() + cy.get('button').contains('Code').click() + cy.get('button').contains('Code').click() cy.get('button').contains(m.label).should('not.be.disabled') }) it(`should apply ${m.label} when the button is pressed`, () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('paragraph').click() + cy.get('button').contains('Paragraph').click() cy.get('.tiptap').type('{selectall}') cy.get('button').contains(m.label).click() cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world') @@ -64,40 +64,40 @@ context('/src/Examples/Default/React/', () => { it('should clear marks when the button is pressed', () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('paragraph').click() + cy.get('button').contains('Paragraph').click() cy.get('.tiptap').type('{selectall}') - cy.get('button').contains('bold').click() + cy.get('button').contains('Bold').click() cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world') - cy.get('button').contains('clear marks').click() + cy.get('button').contains('Clear marks').click() cy.get('.tiptap strong').should('not.exist') }) it('should clear nodes when the button is pressed', () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('bullet list').click() + cy.get('button').contains('Bullet list').click() cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world') cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}') - cy.get('button').contains('clear nodes').click() + cy.get('button').contains('Clear nodes').click() cy.get('.tiptap ul').should('not.exist') cy.get('.tiptap p').should('have.length', 3) }) const buttonNodes = [ - { label: 'h1', tag: 'h1' }, - { label: 'h2', tag: 'h2' }, - { label: 'h3', tag: 'h3' }, - { label: 'h4', tag: 'h4' }, - { label: 'h5', tag: 'h5' }, - { label: 'h6', tag: 'h6' }, - { label: 'bullet list', tag: 'ul' }, - { label: 'ordered list', tag: 'ol' }, - { label: 'code block', tag: 'pre code' }, - { label: 'blockquote', tag: 'blockquote' }, + { label: 'H1', tag: 'h1' }, + { label: 'H2', tag: 'h2' }, + { label: 'H3', tag: 'h3' }, + { label: 'H4', tag: 'h4' }, + { label: 'H5', tag: 'h5' }, + { label: 'H6', tag: 'h6' }, + { label: 'Bullet list', tag: 'ul' }, + { label: 'Ordered list', tag: 'ol' }, + { label: 'Code block', tag: 'pre code' }, + { label: 'Blockquote', tag: 'blockquote' }, ] buttonNodes.forEach(n => { it(`should set ${n.label} when the button is pressed`, () => { - cy.get('button').contains('paragraph').click() + cy.get('button').contains('Paragraph').click() cy.get('.tiptap').type('{selectall}Hello world{selectall}') cy.get('button').contains(n.label).click() @@ -109,35 +109,35 @@ context('/src/Examples/Default/React/', () => { it('should add a hr when on the same line as a node', () => { cy.get('.tiptap').type('{rightArrow}') - cy.get('button').contains('horizontal rule').click() + cy.get('button').contains('Horizontal rule').click() cy.get('.tiptap hr').should('exist') cy.get('.tiptap h1').should('exist') }) it('should add a hr when on a new line', () => { cy.get('.tiptap').type('{rightArrow}{enter}') - cy.get('button').contains('horizontal rule').click() + cy.get('button').contains('Horizontal rule').click() cy.get('.tiptap hr').should('exist') cy.get('.tiptap h1').should('exist') }) it('should add a br', () => { cy.get('.tiptap').type('{rightArrow}') - cy.get('button').contains('hard break').click() + cy.get('button').contains('Hard break').click() cy.get('.tiptap h1 br').should('exist') }) it('should undo', () => { cy.get('.tiptap').type('{selectall}{backspace}') - cy.get('button').contains('undo').click() + cy.get('button').contains('Undo').click() cy.get('.tiptap').should('contain', 'Hello world') }) it('should redo', () => { cy.get('.tiptap').type('{selectall}{backspace}') - cy.get('button').contains('undo').click() + cy.get('button').contains('Undo').click() cy.get('.tiptap').should('contain', 'Hello world') - cy.get('button').contains('redo').click() + cy.get('button').contains('Redo').click() cy.get('.tiptap').should('not.contain', 'Hello world') }) }) diff --git a/demos/src/Examples/Default/React/styles.scss b/demos/src/Examples/Default/React/styles.scss index 4d2b2c81e..7694d7322 100644 --- a/demos/src/Examples/Default/React/styles.scss +++ b/demos/src/Examples/Default/React/styles.scss @@ -1,56 +1,91 @@ /* Basic editor styles */ .tiptap { - > * + * { - margin-top: 0.75em; + :first-child { + margin-top: 0; } - ul, + /* List styles */ + ul, ol { padding: 0 1rem; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - line-height: 1.1; - } - - code { - background-color: rgba(#616161, 0.1); - color: #616161; - } - - pre { - background: #0D0D0D; - color: #FFF; - font-family: 'JetBrainsMono', monospace; - padding: 0.75rem 1rem; - border-radius: 0.5rem; - - code { - color: inherit; - padding: 0; - background: none; - font-size: 0.8rem; + margin: 1.25rem 1rem 1.25rem 0.4rem; + + li p { + margin-top: 0.25em; + margin-bottom: 0.25em; } } - img { - max-width: 100%; - height: auto; + /* Heading styles */ + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; + } + + h1, + h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.4rem; + } + + h2 { + font-size: 1.2rem; + } + + h3 { + font-size: 1.1rem; + } + + h4, + h5, + h6 { + font-size: 1rem; + } + + /* Code and preformatted text styles */ + code { + background-color: var(--purple-light); + border-radius: 0.4rem; + color: var(--black); + font-size: 0.85rem; + padding: 0.25em 0.3em; + } + + pre { + background: var(--black); + border-radius: 0.5rem; + color: var(--white); + font-family: 'JetBrainsMono', monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } } blockquote { + border-left: 3px solid var(--gray-3); + margin: 1.5rem 0; padding-left: 1rem; - border-left: 2px solid rgba(#0D0D0D, 0.1); } hr { border: none; - border-top: 2px solid rgba(#0D0D0D, 0.1); + border-top: 1px solid var(--gray-2); margin: 2rem 0; } } diff --git a/demos/src/Examples/Default/Svelte/index.spec.js b/demos/src/Examples/Default/Svelte/index.spec.js index 4e2c71b79..dc0e1c0a5 100644 --- a/demos/src/Examples/Default/Svelte/index.spec.js +++ b/demos/src/Examples/Default/Svelte/index.spec.js @@ -21,15 +21,15 @@ context('/src/Examples/Default/React/', () => { }) const buttonMarks = [ - { label: 'bold', tag: 'strong' }, - { label: 'italic', tag: 'em' }, - { label: 'strike', tag: 's' }, + { label: 'Bold', tag: 'strong' }, + { label: 'Italic', tag: 'em' }, + { label: 'Strike', tag: 's' }, ] buttonMarks.forEach(m => { it(`should apply ${m.label} when the button is pressed`, () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('paragraph').click() + cy.get('button').contains('Paragraph').click() cy.get('.tiptap').type('{selectall}') cy.get('button').contains(m.label).click() cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world') @@ -38,40 +38,40 @@ context('/src/Examples/Default/React/', () => { it('should clear marks when the button is pressed', () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('paragraph').click() + cy.get('button').contains('Paragraph').click() cy.get('.tiptap').type('{selectall}') - cy.get('button').contains('bold').click() + cy.get('button').contains('Bold').click() cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world') - cy.get('button').contains('clear marks').click() + cy.get('button').contains('Clear marks').click() cy.get('.tiptap strong').should('not.exist') }) it('should clear nodes when the button is pressed', () => { cy.get('.tiptap').type('{selectall}Hello world') - cy.get('button').contains('bullet list').click() + cy.get('button').contains('Bullet list').click() cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world') cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}') - cy.get('button').contains('clear nodes').click() + cy.get('button').contains('Clear nodes').click() cy.get('.tiptap ul').should('not.exist') cy.get('.tiptap p').should('have.length', 3) }) const buttonNodes = [ - { label: 'h1', tag: 'h1' }, - { label: 'h2', tag: 'h2' }, - { label: 'h3', tag: 'h3' }, - { label: 'h4', tag: 'h4' }, - { label: 'h5', tag: 'h5' }, - { label: 'h6', tag: 'h6' }, - { label: 'bullet list', tag: 'ul' }, - { label: 'ordered list', tag: 'ol' }, - { label: 'code block', tag: 'pre code' }, - { label: 'blockquote', tag: 'blockquote' }, + { label: 'H1', tag: 'h1' }, + { label: 'H2', tag: 'h2' }, + { label: 'H3', tag: 'h3' }, + { label: 'H4', tag: 'h4' }, + { label: 'H5', tag: 'h5' }, + { label: 'H6', tag: 'h6' }, + { label: 'Bullet list', tag: 'ul' }, + { label: 'Ordered list', tag: 'ol' }, + { label: 'Code block', tag: 'pre code' }, + { label: 'Blockquote', tag: 'blockquote' }, ] buttonNodes.forEach(n => { it(`should set ${n.label} when the button is pressed`, () => { - cy.get('button').contains('paragraph').click() + cy.get('button').contains('Paragraph').click() cy.get('.tiptap').type('{selectall}Hello world{selectall}') cy.get('button').contains(n.label).click() @@ -83,35 +83,35 @@ context('/src/Examples/Default/React/', () => { it('should add a hr when on the same line as a node', () => { cy.get('.tiptap').type('{rightArrow}') - cy.get('button').contains('horizontal rule').click() + cy.get('button').contains('Horizontal rule').click() cy.get('.tiptap hr').should('exist') cy.get('.tiptap h1').should('exist') }) it('should add a hr when on a new line', () => { cy.get('.tiptap').type('{rightArrow}{enter}') - cy.get('button').contains('horizontal rule').click() + cy.get('button').contains('Horizontal rule').click() cy.get('.tiptap hr').should('exist') cy.get('.tiptap h1').should('exist') }) it('should add a br', () => { cy.get('.tiptap').type('{rightArrow}') - cy.get('button').contains('hard break').click() + cy.get('button').contains('Hard break').click() cy.get('.tiptap h1 br').should('exist') }) it('should undo', () => { cy.get('.tiptap').type('{selectall}{backspace}') - cy.get('button').contains('undo').click() + cy.get('button').contains('Undo').click() cy.get('.tiptap').should('contain', 'Hello world') }) it('should redo', () => { cy.get('.tiptap').type('{selectall}{backspace}') - cy.get('button').contains('undo').click() + cy.get('button').contains('Undo').click() cy.get('.tiptap').should('contain', 'Hello world') - cy.get('button').contains('redo').click() + cy.get('button').contains('Redo').click() cy.get('.tiptap').should('not.contain', 'Hello world') }) }) diff --git a/demos/src/Examples/Default/Svelte/index.svelte b/demos/src/Examples/Default/Svelte/index.svelte index d43c0f0e3..6e915f09d 100644 --- a/demos/src/Examples/Default/Svelte/index.svelte +++ b/demos/src/Examples/Default/Svelte/index.svelte @@ -1,6 +1,9 @@ {#if editor} -
#
followed by a space to get a heading. Try #
, ##
, ###
, ####
, #####
, ######
for different levels.
- Those conventions are called input rules in tiptap. Some of them are enabled by default. Try >
for blockquotes, *
, -
or +
for bullet lists, or \`foobar\`
to highlight code, ~~tildes~~
to strike text, or ==equal signs==
to highlight text.
+ Those conventions are called input rules in Tiptap. Some of them are enabled by default. Try >
for blockquotes, *
, -
or +
for bullet lists, or \`foobar\`
to highlight code, ~~tildes~~
to strike text, or ==equal signs==
to highlight text.
You can overwrite existing input rules or add your own to nodes, marks and extensions.
diff --git a/demos/src/Examples/MarkdownShortcuts/React/styles.scss b/demos/src/Examples/MarkdownShortcuts/React/styles.scss
index 6932a405b..d23c43fc9 100644
--- a/demos/src/Examples/MarkdownShortcuts/React/styles.scss
+++ b/demos/src/Examples/MarkdownShortcuts/React/styles.scss
@@ -1,53 +1,98 @@
+/* Basic editor styles */
.tiptap {
- > * + * {
- margin-top: 0.75em;
+ :first-child {
+ margin-top: 0;
}
- ul,
+ /* List styles */
+ ul,
ol {
padding: 0 1rem;
- }
-
- h1,
- h2,
- h3,
- h4,
- h5,
- h6 {
- line-height: 1.1;
- }
-
- code {
- background-color: rgba(#616161, 0.1);
- color: #616161;
- }
-
- pre {
- background: #0D0D0D;
- color: #FFF;
- font-family: 'JetBrainsMono', monospace;
- padding: 0.75rem 1rem;
- border-radius: 0.5rem;
-
- code {
- color: inherit;
- padding: 0;
- background: none;
- font-size: 0.8rem;
+ margin: 1.25rem 1rem 1.25rem 0.4rem;
+
+ li p {
+ margin-top: 0.25em;
+ margin-bottom: 0.25em;
}
}
- img {
- max-width: 100%;
- height: auto;
+ /* Heading styles */
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ line-height: 1.1;
+ margin-top: 2.5rem;
+ text-wrap: pretty;
}
- hr {
- margin: 1rem 0;
+ h1,
+ h2 {
+ margin-top: 3.5rem;
+ margin-bottom: 1.5rem;
+ }
+
+ h1 {
+ font-size: 1.4rem;
+ }
+
+ h2 {
+ font-size: 1.2rem;
+ }
+
+ h3 {
+ font-size: 1.1rem;
+ }
+
+ h4,
+ h5,
+ h6 {
+ font-size: 1rem;
+ }
+
+ /* Code and preformatted text styles */
+ code {
+ background-color: var(--purple-light);
+ border-radius: 0.4rem;
+ color: var(--black);
+ font-size: 0.85rem;
+ padding: 0.25em 0.3em;
+ }
+
+ pre {
+ background: var(--black);
+ border-radius: 0.5rem;
+ color: var(--white);
+ font-family: 'JetBrainsMono', monospace;
+ margin: 1.5rem 0;
+ padding: 0.75rem 1rem;
+
+ code {
+ background: none;
+ color: inherit;
+ font-size: 0.8rem;
+ padding: 0;
+ }
+ }
+
+ mark {
+ background-color: #FAF594;
+ border-radius: 0.4rem;
+ box-decoration-break: clone;
+ padding: 0.1rem 0.3rem;
}
blockquote {
+ border-left: 3px solid var(--gray-3);
+ margin: 1.5rem 0;
padding-left: 1rem;
- border-left: 2px solid rgba(#0D0D0D, 0.1);
+ }
+
+ hr {
+ border: none;
+ border-top: 1px solid var(--gray-2);
+ margin: 2rem 0;
}
}
diff --git a/demos/src/Examples/MarkdownShortcuts/Vue/index.vue b/demos/src/Examples/MarkdownShortcuts/Vue/index.vue
index c2705ac76..034550d4a 100644
--- a/demos/src/Examples/MarkdownShortcuts/Vue/index.vue
+++ b/demos/src/Examples/MarkdownShortcuts/Vue/index.vue
@@ -34,7 +34,7 @@ export default {
To test that, start a new line and type #
followed by a space to get a heading. Try #
, ##
, ###
, ####
, #####
, ######
for different levels.
- Those conventions are called input rules in tiptap. Some of them are enabled by default. Try >
for blockquotes, *
, -
or +
for bullet lists, or \`foobar\`
to highlight code, ~~tildes~~
to strike text, or ==equal signs==
to highlight text.
+ Those conventions are called input rules in Tiptap. Some of them are enabled by default. Try >
for blockquotes, *
, -
or +
for bullet lists, or \`foobar\`
to highlight code, ~~tildes~~
to strike text, or ==equal signs==
to highlight text.
You can overwrite existing input rules or add your own to nodes, marks and extensions. @@ -55,15 +55,23 @@ export default { diff --git a/demos/src/Examples/Menus/React/index.jsx b/demos/src/Examples/Menus/React/index.jsx index c6a86209b..b05c7e1f7 100644 --- a/demos/src/Examples/Menus/React/index.jsx +++ b/demos/src/Examples/Menus/React/index.jsx @@ -64,7 +64,7 @@ export default () => { onClick={() => editor.chain().focus().toggleBulletList().run()} className={editor.isActive('bulletList') ? 'is-active' : ''} > - Bullet List + Bullet list } diff --git a/demos/src/Examples/Menus/React/styles.scss b/demos/src/Examples/Menus/React/styles.scss index d9820d58d..cf6f3bc01 100644 --- a/demos/src/Examples/Menus/React/styles.scss +++ b/demos/src/Examples/Menus/React/styles.scss @@ -1,53 +1,144 @@ +/* Basic editor styles */ .tiptap { - > * + * { - margin-top: 0.75em; + :first-child { + margin-top: 0; } - ul, + /* List styles */ + ul, ol { padding: 0 1rem; + margin: 1.25rem 1rem 1.25rem 0.4rem; + + li p { + margin-top: 0.25em; + margin-bottom: 0.25em; + } + } + + /* Heading styles */ + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; + } + + h1, + h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.4rem; + } + + h2 { + font-size: 1.2rem; + } + + h3 { + font-size: 1.1rem; + } + + h4, + h5, + h6 { + font-size: 1rem; + } + + /* Code and preformatted text styles */ + code { + background-color: var(--purple-light); + border-radius: 0.4rem; + color: var(--black); + font-size: 0.85rem; + padding: 0.25em 0.3em; + } + + pre { + background: var(--black); + border-radius: 0.5rem; + color: var(--white); + font-family: 'JetBrainsMono', monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } + } + + blockquote { + border-left: 3px solid var(--gray-3); + margin: 1.5rem 0; + padding-left: 1rem; + } + + hr { + border: none; + border-top: 1px solid var(--gray-2); + margin: 2rem 0; } } +/* Bubble menu */ .bubble-menu { + background-color: var(--white); + border: 1px solid var(--gray-1); + border-radius: 0.7rem; + box-shadow: var(--shadow); display: flex; - background-color: #0D0D0D; padding: 0.2rem; - border-radius: 0.5rem; button { - border: none; - background: none; - color: #FFF; - font-size: 0.85rem; - font-weight: 500; - padding: 0 0.2rem; - opacity: 0.6; + background-color: unset; + + &:hover { + background-color: var(--gray-3); + } - &:hover, &.is-active { - opacity: 1; + background-color: var(--purple); + + &:hover { + background-color: var(--purple-contrast); + } } } } +/* Floating menu */ .floating-menu { display: flex; - background-color: #0D0D0D10; - padding: 0.2rem; + background-color: var(--gray-3); + padding: 0.1rem; border-radius: 0.5rem; button { - border: none; - background: none; - font-size: 0.85rem; - font-weight: 500; - padding: 0 0.2rem; - opacity: 0.6; + background-color: unset; + padding: 0.275rem 0.425rem; + border-radius: 0.3rem; + + &:hover { + background-color: var(--gray-3); + } - &:hover, &.is-active { - opacity: 1; + background-color: var(--white); + color: var(--purple); + + &:hover { + color: var(--purple-contrast); + } } } } diff --git a/demos/src/Examples/Menus/Vue/index.vue b/demos/src/Examples/Menus/Vue/index.vue index b52941c32..4f4cf9f78 100644 --- a/demos/src/Examples/Menus/Vue/index.vue +++ b/demos/src/Examples/Menus/Vue/index.vue @@ -28,7 +28,7 @@ H2
This is a simple paragraph.
-Here is another paragraph inside this document.
@@ -72,11 +72,11 @@ export default () => {-Here we have another paragraph inside a blockquote.
--
+
+
![]()
- → With the Typography extension, tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side. + → With the Typography extension, Tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side.
Try it out and type (c)
, ->
, >>
, 1/2
, !=
, --
or 1x1
here:
diff --git a/demos/src/Examples/Savvy/React/styles.scss b/demos/src/Examples/Savvy/React/styles.scss
index 377369437..feee91627 100644
--- a/demos/src/Examples/Savvy/React/styles.scss
+++ b/demos/src/Examples/Savvy/React/styles.scss
@@ -1,38 +1,33 @@
/* Basic editor styles */
.tiptap {
- > * + * {
- margin-top: 0.75em;
- }
-
- h1,
- h2,
- h3,
- h4,
- h5,
- h6 {
- line-height: 1.1;
+ :first-child {
+ margin-top: 0;
}
+ /* Code and preformatted text styles */
code {
- background-color: rgba(#616161, 0.1);
- color: #616161;
- }
-}
-
-/* Color swatches */
-.color {
- white-space: nowrap;
-
- &::before {
- background-color: var(--color);
- border: 1px solid rgba(128, 128, 128, 0.3);
- border-radius: 2px;
- content: " ";
- display: inline-block;
- height: 1em;
- margin-bottom: 0.15em;
- margin-right: 0.1em;
- vertical-align: middle;
- width: 1em;
+ background-color: var(--purple-light);
+ border-radius: 0.4rem;
+ color: var(--black);
+ font-size: 0.85rem;
+ padding: 0.25em 0.3em;
+ }
+
+ /* Color swatches */
+ .color {
+ white-space: nowrap;
+
+ &::before {
+ background-color: var(--color);
+ border: 1px solid rgba(128, 128, 128, 0.3);
+ border-radius: 2px;
+ content: " ";
+ display: inline-block;
+ height: 1em;
+ margin-bottom: 0.15em;
+ margin-right: 0.1em;
+ vertical-align: middle;
+ width: 1em;
+ }
}
}
diff --git a/demos/src/Examples/Savvy/Vue/index.vue b/demos/src/Examples/Savvy/Vue/index.vue
index b296747bd..a824b6097 100644
--- a/demos/src/Examples/Savvy/Vue/index.vue
+++ b/demos/src/Examples/Savvy/Vue/index.vue
@@ -37,7 +37,7 @@ export default {
],
content: `
- → With the Typography extension, tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side. + → With the Typography extension, Tiptap understands »what you mean« and adds correct characters to your text — it’s like a “typography nerd” on your side.
Try it out and type (c)
, ->
, >>
, 1/2
, !=
, --
or 1x1
here:
@@ -64,40 +64,35 @@ export default {
diff --git a/demos/src/Examples/Tables/React/index.jsx b/demos/src/Examples/Tables/React/index.jsx
index 7fab59158..acc42ca7b 100644
--- a/demos/src/Examples/Tables/React/index.jsx
+++ b/demos/src/Examples/Tables/React/index.jsx
@@ -60,69 +60,71 @@ const MenuBar = ({ editor }) => {
}
return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
+
colgroup
and rowspan
colgroup
and rowspan
Here is an example: @@ -160,20 +162,20 @@ export default () => {
- Another Editor -
- +Another Editor
+