Skip to content
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

Table layout stylization. #17989

Draft
wants to merge 16 commits into
base: ck/epic/email-editing
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion packages/ckeditor5-icons/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export { default as IconTableOfContents } from '../theme/icons/table-of-contents
export { default as IconTableProperties } from '../theme/icons/table-properties.svg';
export { default as IconTableRow } from '../theme/icons/table-row.svg';
export { default as IconTable } from '../theme/icons/table.svg';
export { default as IconTableLayout } from '../theme/icons/table.svg'; // TODO: Add table layout icon.
export { default as IconTableLayout } from '../theme/icons/table-layout.svg';
export { default as IconTemplateGeneric } from '../theme/icons/template-generic.svg';
export { default as IconTemplate } from '../theme/icons/template.svg';
export { default as IconTextAlternative } from '../theme/icons/text-alternative.svg';
Expand Down
1 change: 1 addition & 0 deletions packages/ckeditor5-icons/theme/icons/table-layout.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/ckeditor5-table/src/tablelayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import TableLayoutEditing from './tablelayout/tablelayoutediting.js';
import PlainTableOutput from './plaintableoutput.js';
import TableColumnResize from './tablecolumnresize.js';

import '../theme/tablelayout.css';

/**
* The table layout plugin.
*/
Expand Down
7 changes: 2 additions & 5 deletions packages/ckeditor5-table/src/tablelayout/tablelayoutui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
*/

import { Plugin } from 'ckeditor5/src/core.js';
import { IconTableLayout } from 'ckeditor5/src/icons.js'; // TODO: Remember to update in ckeditor5-icons when icon is ready.
import {
createDropdown,
MenuBarMenuView
} from 'ckeditor5/src/ui.js';
import { IconTableLayout } from 'ckeditor5/src/icons.js';
import { createDropdown, MenuBarMenuView } from 'ckeditor5/src/ui.js';
import type { ObservableChangeEvent } from 'ckeditor5/src/utils.js';

import InsertTableView from '../ui/inserttableview.js';
Expand Down
119 changes: 119 additions & 0 deletions packages/ckeditor5-table/tests/manual/tablelayout.html
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,123 @@ <h3>Source: &lt;figure&gt;&lt;table&gt; containing &lt;thead&gt;/&lt;th&gt; => r
</tbody>
</table>
</figure>

<h3>Look of widget type around and selection handle is changed in layout tables, also only hovered table shows mention
earlier widget handlers.</h3>
<p></p>
<table class="table content-table" role="presentation">
<tbody>
<tr>
<td>
<p>foo</p>
<table class="table content-table" role="presentation">
<tbody>
<tr>
<td style="width:33.333333%;">bar</td>
<td style="width:33.333333%;">
<table class="table layout-table"
style="border-color:hsl(120, 75%, 60%);border-style:solid;width:100%;"
role="presentation">
<tbody>
<tr>
<td>baz</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td style="border-color:hsl(0, 75%, 60%);">&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
</td>
<td style="width:33.333333%;">&nbsp;</td>
</tr>
<tr>
<td style="width:33.333333%;">&nbsp;</td>
<td style="width:33.333333%;">&nbsp;</td>
<td style="width:33.333333%;">&nbsp;</td>
</tr>
</tbody>
</table>
</td>
<td>b</td>
<td>c</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
<p></p>
</div>


<h2>Example table to copy and paste</h2>

<div class="external-table-wrapper">

<table style="width: 40%;">
<tbody>
<tr>
<td>
<table>
<tbody>
<tr>
<td style="width:33.333333%;">&nbsp;</td>
<td style="width:33.333333%;">&nbsp;</td>
<td style="width:33.333333%;">&nbsp;</td>
</tr>
<tr>
<td style="width:33.333333%;">&nbsp;</td>
<td style="width:33.333333%;">&nbsp;</td>
<td style="width:33.333333%;">&nbsp;</td>
</tr>
</tbody>
</table>
</td>
<td>b</td>
<td>c</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
</div>

<style>
.external-table-wrapper {
margin-top: 20px;
padding: 2em;
background-color: rgba(0, 0, 0, 0.1);
border: 1px solid grey;
border-radius: 8px;
}

.external-table-wrapper table,
.external-table-wrapper td,
.external-table-wrapper th {
border: 1px solid black;
border-collapse: collapse;
}
</style>
15 changes: 13 additions & 2 deletions packages/ckeditor5-table/tests/manual/tablelayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor.js';
import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset.js';
import GeneralHtmlSupport from '@ckeditor/ckeditor5-html-support/src/generalhtmlsupport.js';
import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line';
import Table from '../../src/table.js';
import TableToolbar from '../../src/tabletoolbar.js';
Expand All @@ -23,6 +24,7 @@ const config = {
image: { toolbar: [ 'toggleImageCaption', 'imageTextAlternative' ] },
plugins: [
ArticlePluginSet,
GeneralHtmlSupport,
HorizontalLine,
Table,
TableToolbar,
Expand All @@ -45,8 +47,17 @@ const config = {
table: {
contentToolbar: [
'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties', 'toggleTableCaption'
],
tableToolbar: [ 'bold', 'italic' ]
]
},
htmlSupport: {
allow: [
{
name: /.*/,
attributes: true,
classes: true,
styles: true
}
]
},
menuBar: {
isVisible: true
Expand Down
51 changes: 51 additions & 0 deletions packages/ckeditor5-table/theme/tablelayout.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

.ck-editor__editable {
&.ck-editor__editable_inline {
& > .ck-widget.ck-widget_with-selection-handle.layout-table:first-child {
margin-top: var(--ck-spacing-large);
}
}

& .table.layout-table {
/* Do not reserve space above and below the layout table. */
margin-top: 0;
margin-bottom: 0;

& > table {
border-spacing: 0.5px;
}

/* Widget type around overrides. */
&.ck-widget {
&:hover > .ck-widget__selection-handle {
opacity: 0.75;
visibility: visible;

&:hover {
opacity: 1;
}
}

&:has( .ck-widget:hover ) > .ck-widget__selection-handle {
opacity: 0;
visibility: hidden;
}
}
}
}

.ck-content {
& .table.layout-table:not(figure) {
/* Table layout set to fixed only when width is set. But we need to filter other possibilities `*-width`, */
&[style^="width:"],
&[style*=" width:"],
&[style*=";width:"],
&[style*="'width:"] {
table-layout: fixed;
}
}
}
125 changes: 125 additions & 0 deletions packages/ckeditor5-theme-lark/theme/ckeditor5-table/tablelayout.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

:root {
--ck-table-layout-widget-type-around-button-size: 16px;
--ck-table-layout-widget-type-around-icon-width: 10px;
--ck-table-layout-widget-type-around-icon-height: 8px;
--ck-table-layout-default-border-color: hsl(0, 0%, 58%);
--ck-table-layout-widget-handler-icon-size: 10px;
}


.ck-editor__editable {
& .table.layout-table {
--ck-widget-type-around-button-size: var(--ck-table-layout-widget-type-around-button-size);

& > table {
border-collapse: separate;
}

/* Removed default background color from focused table cell */
& > table > tbody > tr > td {
--ck-color-selector-focused-cell-background: transparent;

padding: 1px 2px;
border: none;

&[style^="width:"],
&[style*=" width:"],
&[style*=";width:"],
&[style*="'width:"] {
min-width: auto;
}
}

/* Default table layout stylization in editing view.
When border is not set.
But it need to be more strict cause of style attributes like `border-collapse`. */

& > table[style*="border-collapse"]:not(
& > table[style*="border:"],
& > table[style*="border-w"],
& > table[style*="border-s"],
& > table[style*="border-colo"]),
& > table > tbody > tr > td[style*="border-collapse"]:not(
& > table > tbody > tr > td[style*="border:"],
& > table > tbody > tr > td[style*="border-w"],
& > table > tbody > tr > td[style*="border-s"],
& > table > tbody > tr > td[style*="border-colo"]) {
border: none;
outline: var(--ck-table-layout-default-border-color) 1px dashed;
}

/* Widget type around overrides. */
&.ck-widget {
& .ck-widget__type-around__button svg {
width: var(--ck-table-layout-widget-type-around-icon-width);
height: var(--ck-table-layout-widget-type-around-icon-height);
}

& > .ck-widget__type-around {
& > .ck-widget__type-around__button {
&.ck-widget__type-around__button_before,
&.ck-widget__type-around__button_after {
transform: translateY(0);
}

&.ck-widget__type-around__button_before {
border-radius: 0 0 100px 100px;
}

&.ck-widget__type-around__button_after {
border-radius: 100px 100px 0 0;
}
}
}

&.ck-widget_with-selection-handle {
--ck-widget-handler-icon-size: var(--ck-table-layout-widget-handler-icon-size);

& > .ck-widget__selection-handle {
transform: translateY(calc(0px - var(--ck-widget-outline-thickness)));
z-index: var(--ck-z-default);
}

& > .ck-widget__type-around {
& > .ck-widget__type-around__button_before {
margin-left: var(--ck-table-layout-widget-type-around-button-size);
left: min(10%, 30px);
}
}
}

&.ck-widget.ck-widget_selected {
& > .ck-widget__type-around {
& > .ck-widget__type-around__button_before {
&::after {
border-radius: 0 0 100px 100px;
}
}

& > .ck-widget__type-around__button_after {
&::after {
border-radius: 100px 100px 0 0;
}
}
}
}
}
}
}

.ck.ck-editor__editable_inline {
/*
* This value should match with the default margins of the block elements (like .media, .image or .table)
* to avoid a content jumping when the fake selection container shows up (See https://github.com/ckeditor/ckeditor5/issues/9825).
*/
& > :last-child,
/* Fallback for hidden fake selection div */
& > :nth-last-child(2):has( + .ck-fake-selection-container) {
margin-bottom: var(--ck-spacing-large);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@
}
}
}

/* Hide the selection handler on mouse hover over the widget of all the widget parents. */
&:has( .ck-widget:hover ) > .ck-widget__selection-handle {
opacity: 0;
visibility: hidden;
}
}

/* In a RTL environment, align the selection handler to the right side of the widget */
Expand Down
Loading