From f7bceaa29fbb4a91e9754b6efdee38ccc4e68780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Dalmolin?= Date: Sat, 25 Oct 2025 17:59:13 -0300 Subject: [PATCH 1/4] Added proper way to customize editor styles --- README.md | 36 +++++++++++++++++-- resources/dist/commentions.js | 2 +- resources/js/commentions.js | 4 +-- resources/views/comment-list.blade.php | 1 + resources/views/comment.blade.php | 2 +- resources/views/comments-modal.blade.php | 1 + resources/views/comments.blade.php | 3 +- .../components/comments-entry.blade.php | 1 + src/Config.php | 16 +++++++++ src/Filament/Actions/CommentsAction.php | 3 ++ src/Filament/Actions/CommentsTableAction.php | 3 ++ src/Filament/Concerns/HasTipTapCssClasses.php | 23 ++++++++++++ .../Infolists/Components/CommentsEntry.php | 2 ++ src/Livewire/Comment.php | 7 ++++ src/Livewire/CommentList.php | 2 ++ src/Livewire/Comments.php | 7 ++++ 16 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 src/Filament/Concerns/HasTipTapCssClasses.php diff --git a/README.md b/README.md index d9d92e2..f9777ed 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,7 @@ use Kirschbaum\Commentions\Filament\Actions\CommentsAction; CommentsAction::make() ->mentionables(User::all()) ->perPage(10) - + ]) ``` Without Pagination: @@ -257,7 +257,7 @@ use Kirschbaum\Commentions\Filament\Actions\CommentsAction; CommentsAction::make() ->mentionables(User::all()) ->disablePagination(); - + ]) ``` Advanced Usage: @@ -386,6 +386,38 @@ class User extends Authenticatable implements Commenter, HasName, HasAvatar } ``` +### Customizing TipTap Editor Styles + +You can customize the TipTap editor CSS classes used using the `Config` class: + +```php +use Kirschbaum\Commentions\Config; + +Config::resolveTipTapCssClassesUsing(function () { + return 'prose max-w-none focus:outline-none p-4'; +}); +``` + +And you can also override the classes on a per-component basis using the `tipTapCssClasses()` method: + +```php +use Kirschbaum\Commentions\Filament\Infolists\Components\CommentsEntry; + +CommentsEntry::make('comments') + ->mentionables(fn (Model $record) => User::all()) + ->tipTapCssClasses('prose max-w-none focus:outline-none p-4') +``` + +Or with actions: + +```php +use Kirschbaum\Commentions\Filament\Actions\CommentsAction; + +CommentsAction::make() + ->mentionables(User::all()) + ->tipTapCssClasses('prose max-w-none focus:outline-none p-4') +``` + ### Translations You can publish the package translation files and override any strings used by the UI. diff --git a/resources/dist/commentions.js b/resources/dist/commentions.js index 25e363a..b6c8626 100644 --- a/resources/dist/commentions.js +++ b/resources/dist/commentions.js @@ -99,4 +99,4 @@ img.ProseMirror-separator { :class="{ 'comm:bg-gray-100': $store.filamentCommentsMentionsFiltered.selectedIndex === index }" > - `,s})(),showOnCreate:!0,interactive:!0,trigger:"manual",placement:document.dir==="rtl"?"bottom-end":"bottom-start",theme:"light",arrow:!0})},onUpdate:o=>{o.clientRect&&t[0].setProps({getReferenceClientRect:o.clientRect})},onKeyDown:o=>{let s=Alpine.store("filamentCommentsMentionsFiltered").items,l=Alpine.store("filamentCommentsMentionsFiltered").selectedIndex;if(o.event.key==="ArrowDown")return Alpine.store("filamentCommentsMentionsFiltered").selectedIndex=(l+1)%s.length,!0;if(o.event.key==="ArrowUp")return Alpine.store("filamentCommentsMentionsFiltered").selectedIndex=(l-1+s.length)%s.length,!0;if(o.event.key==="Enter"){let a=s[l];return a&&i({id:a.id,label:a.name}),!0}return o.event.key==="Escape"?(t[0].hide(),!0):!1},onExit:()=>{t[0].hide()}}}}},Kf=Xg;document.addEventListener("alpine:init",()=>{Alpine.data("editor",(n,e,t,r)=>{let i;return{updatedAt:Date.now(),init(){let o=this;i=new gi({element:this.$refs.element,extensions:[of,lf.configure({HTMLAttributes:{class:"mention"},suggestion:Kf(e)}),af.configure({placeholder:r})],editorProps:{attributes:{class:"comm:prose comm:dark:prose-invert comm:prose-sm comm:sm:prose-base comm:lg:prose-lg comm:xl:prose-2xl comm:focus:outline-none comm:p-4 comm:min-w-full comm:w-full comm:rounded-lg comm:border comm:border-gray-300 comm:dark:border-gray-700"}},placeholder:"Type something...",content:n,onCreate({editor:s}){o.updatedAt=Date.now()},onUpdate({editor:s}){Livewire.dispatchTo(`commentions::${t}`,"body:updated",{value:s.getHTML()}),o.updatedAt=Date.now()},onSelectionUpdate({editor:s}){o.updatedAt=Date.now()}}),Livewire.on(`${t}:content:cleared`,()=>{i.commands.setContent("")})},isLoaded(){return i},isActive(o,s={}){return i.isActive(o,s)}}})}); + `,s})(),showOnCreate:!0,interactive:!0,trigger:"manual",placement:document.dir==="rtl"?"bottom-end":"bottom-start",theme:"light",arrow:!0})},onUpdate:o=>{o.clientRect&&t[0].setProps({getReferenceClientRect:o.clientRect})},onKeyDown:o=>{let s=Alpine.store("filamentCommentsMentionsFiltered").items,l=Alpine.store("filamentCommentsMentionsFiltered").selectedIndex;if(o.event.key==="ArrowDown")return Alpine.store("filamentCommentsMentionsFiltered").selectedIndex=(l+1)%s.length,!0;if(o.event.key==="ArrowUp")return Alpine.store("filamentCommentsMentionsFiltered").selectedIndex=(l-1+s.length)%s.length,!0;if(o.event.key==="Enter"){let a=s[l];return a&&i({id:a.id,label:a.name}),!0}return o.event.key==="Escape"?(t[0].hide(),!0):!1},onExit:()=>{t[0].hide()}}}}},Kf=Xg;document.addEventListener("alpine:init",()=>{Alpine.data("editor",(n,e,t,r,i)=>{let o;return{updatedAt:Date.now(),init(){let s=this,l="comm:prose comm:dark:prose-invert comm:prose-sm comm:sm:prose-base comm:lg:prose-lg comm:xl:prose-2xl comm:focus:outline-none comm:p-4 comm:min-w-full comm:w-full comm:rounded-lg comm:border comm:border-gray-300 comm:dark:border-gray-700";o=new gi({element:this.$refs.element,extensions:[of,lf.configure({HTMLAttributes:{class:"mention"},suggestion:Kf(e)}),af.configure({placeholder:r})],editorProps:{attributes:{class:i||l}},placeholder:"Type something...",content:n,onCreate({editor:a}){s.updatedAt=Date.now()},onUpdate({editor:a}){Livewire.dispatchTo(`commentions::${t}`,"body:updated",{value:a.getHTML()}),s.updatedAt=Date.now()},onSelectionUpdate({editor:a}){s.updatedAt=Date.now()}}),Livewire.on(`${t}:content:cleared`,()=>{o.commands.setContent("")})},isLoaded(){return o},isActive(s,l={}){return o.isActive(s,l)}}})}); diff --git a/resources/js/commentions.js b/resources/js/commentions.js index c245176..db8fdfa 100644 --- a/resources/js/commentions.js +++ b/resources/js/commentions.js @@ -5,7 +5,7 @@ import Placeholder from '@tiptap/extension-placeholder' import suggestion from './suggestion' document.addEventListener('alpine:init', () => { - Alpine.data('editor', (content, mentions, component, placeholder) => { + Alpine.data('editor', (content, mentions, component, placeholder, editorCssClasses) => { let editor return { @@ -30,7 +30,7 @@ document.addEventListener('alpine:init', () => { ], editorProps: { attributes: { - class: `comm:prose comm:dark:prose-invert comm:prose-sm comm:sm:prose-base comm:lg:prose-lg comm:xl:prose-2xl comm:focus:outline-none comm:p-4 comm:min-w-full comm:w-full comm:rounded-lg comm:border comm:border-gray-300 comm:dark:border-gray-700`, + class: editorCssClasses, }, }, placeholder: 'Type something...', diff --git a/resources/views/comment-list.blade.php b/resources/views/comment-list.blade.php index 0bf33ad..bef0d29 100644 --- a/resources/views/comment-list.blade.php +++ b/resources/views/comment-list.blade.php @@ -19,6 +19,7 @@ class="comm:w-8 comm:h-8 comm:text-gray-400 comm:dark:text-gray-500" :key="$comment->getContentHash()" :comment="$comment" :mentionables="$mentionables" + :tip-tap-css-classes="$tipTapCssClasses" /> @endforeach diff --git a/resources/views/comment.blade.php b/resources/views/comment.blade.php index d574332..0d24835 100644 --- a/resources/views/comment.blade.php +++ b/resources/views/comment.blade.php @@ -92,7 +92,7 @@ class="comm:text-xs comm:text-gray-300 comm:ml-1" @if ($editing)
-
+
diff --git a/resources/views/comments-modal.blade.php b/resources/views/comments-modal.blade.php index 51a2ca5..b241cc0 100644 --- a/resources/views/comments-modal.blade.php +++ b/resources/views/comments-modal.blade.php @@ -10,5 +10,6 @@ :per-page-increment="$perPageIncrement ?? null" :sidebar-enabled="$sidebarEnabled ?? true" :show-subscribers="$showSubscribers ?? true" + :tip-tap-css-classes="$tipTapCssClasses ?? null" />
diff --git a/resources/views/comments.blade.php b/resources/views/comments.blade.php index bb175ed..1c532f8 100644 --- a/resources/views/comments.blade.php +++ b/resources/views/comments.blade.php @@ -8,7 +8,7 @@ {{-- tiptap editor --}}
@@ -40,6 +40,7 @@ :per-page="$perPage ?? 5" :load-more-label="$loadMoreLabel ?? __('commentions::comments.show_more')" :per-page-increment="$perPageIncrement ?? null" + :tip-tap-css-classes="$tipTapCssClasses" />
diff --git a/resources/views/filament/infolists/components/comments-entry.blade.php b/resources/views/filament/infolists/components/comments-entry.blade.php index 24fb420..3884c78 100644 --- a/resources/views/filament/infolists/components/comments-entry.blade.php +++ b/resources/views/filament/infolists/components/comments-entry.blade.php @@ -8,5 +8,6 @@ :load-more-label="$getLoadMoreLabel()" :per-page-increment="$getPerPageIncrement()" :sidebar-enabled="$isSidebarEnabled()" + :tip-tap-css-classes="$getTipTapCssClasses()" /> diff --git a/src/Config.php b/src/Config.php index 8a59d2b..7f9038a 100644 --- a/src/Config.php +++ b/src/Config.php @@ -14,6 +14,8 @@ class Config protected static ?Closure $resolveCommentUrl = null; + protected static ?Closure $resolveTipTapCssClasses = null; + public static function resolveAuthenticatedUserUsing(Closure $callback): void { static::$resolveAuthenticatedUser = $callback; @@ -78,4 +80,18 @@ public static function getAllowedReactions(): array { return config('commentions.reactions.allowed', ['👍']); } + + public static function resolveTipTapCssClassesUsing(Closure $callback): void + { + static::$resolveTipTapCssClasses = $callback; + } + + public static function getTipTapCssClasses(): ?string + { + if (static::$resolveTipTapCssClasses instanceof Closure) { + return call_user_func(static::$resolveTipTapCssClasses); + } + + return 'comm:prose comm:dark:prose-invert comm:prose-sm comm:sm:prose-base comm:lg:prose-lg comm:xl:prose-2xl comm:focus:outline-none comm:p-4 comm:min-w-full comm:w-full comm:rounded-lg comm:border comm:border-gray-300 comm:dark:border-gray-700'; + } } diff --git a/src/Filament/Actions/CommentsAction.php b/src/Filament/Actions/CommentsAction.php index 264697a..0252ff8 100644 --- a/src/Filament/Actions/CommentsAction.php +++ b/src/Filament/Actions/CommentsAction.php @@ -8,6 +8,7 @@ use Kirschbaum\Commentions\Filament\Concerns\HasPagination; use Kirschbaum\Commentions\Filament\Concerns\HasPolling; use Kirschbaum\Commentions\Filament\Concerns\HasSidebar; +use Kirschbaum\Commentions\Filament\Concerns\HasTipTapCssClasses; class CommentsAction extends Action { @@ -15,6 +16,7 @@ class CommentsAction extends Action use HasPagination; use HasPolling; use HasSidebar; + use HasTipTapCssClasses; protected function setUp(): void { @@ -32,6 +34,7 @@ protected function setUp(): void 'perPageIncrement' => $this->getPerPageIncrement() ?: $this->getPerPage(), 'sidebarEnabled' => $this->isSidebarEnabled(), 'showSubscribers' => $this->showSubscribers(), + 'tipTapCssClasses' => $this->getTipTapCssClasses(), ])) ->modalWidth($this->isSidebarEnabled() ? '4xl' : 'xl') ->label(__('commentions::comments.label')) diff --git a/src/Filament/Actions/CommentsTableAction.php b/src/Filament/Actions/CommentsTableAction.php index 03883b1..d09630b 100644 --- a/src/Filament/Actions/CommentsTableAction.php +++ b/src/Filament/Actions/CommentsTableAction.php @@ -7,12 +7,14 @@ use Kirschbaum\Commentions\Filament\Concerns\HasMentionables; use Kirschbaum\Commentions\Filament\Concerns\HasPolling; use Kirschbaum\Commentions\Filament\Concerns\HasSidebar; +use Kirschbaum\Commentions\Filament\Concerns\HasTipTapCssClasses; class CommentsTableAction extends Action { use HasMentionables; use HasPolling; use HasSidebar; + use HasTipTapCssClasses; protected function setUp(): void { @@ -26,6 +28,7 @@ protected function setUp(): void 'pollingInterval' => $this->getPollingInterval(), 'sidebarEnabled' => $this->isSidebarEnabled(), 'showSubscribers' => $this->showSubscribers(), + 'tipTapCssClasses' => $this->getTipTapCssClasses(), ])) ->modalWidth($this->isSidebarEnabled() ? '4xl' : 'xl') ->label(__('commentions::comments.label')) diff --git a/src/Filament/Concerns/HasTipTapCssClasses.php b/src/Filament/Concerns/HasTipTapCssClasses.php new file mode 100644 index 0000000..fd404d3 --- /dev/null +++ b/src/Filament/Concerns/HasTipTapCssClasses.php @@ -0,0 +1,23 @@ +tipTapCssClasses = $classes; + + return $this; + } + + public function getTipTapCssClasses(): ?string + { + return $this->evaluate($this->tipTapCssClasses) ?? Config::getTipTapCssClasses(); + } +} diff --git a/src/Filament/Infolists/Components/CommentsEntry.php b/src/Filament/Infolists/Components/CommentsEntry.php index bd89b5f..1d6031f 100644 --- a/src/Filament/Infolists/Components/CommentsEntry.php +++ b/src/Filament/Infolists/Components/CommentsEntry.php @@ -7,6 +7,7 @@ use Kirschbaum\Commentions\Filament\Concerns\HasPagination; use Kirschbaum\Commentions\Filament\Concerns\HasPolling; use Kirschbaum\Commentions\Filament\Concerns\HasSidebar; +use Kirschbaum\Commentions\Filament\Concerns\HasTipTapCssClasses; class CommentsEntry extends Entry { @@ -14,6 +15,7 @@ class CommentsEntry extends Entry use HasPagination; use HasPolling; use HasSidebar; + use HasTipTapCssClasses; protected string $view = 'commentions::filament.infolists.components.comments-entry'; } diff --git a/src/Livewire/Comment.php b/src/Livewire/Comment.php index cdd49d1..82eb5e9 100644 --- a/src/Livewire/Comment.php +++ b/src/Livewire/Comment.php @@ -22,6 +22,8 @@ class Comment extends Component public bool $editing = false; + public ?string $tipTapCssClasses = null; + protected $rules = [ 'commentBody' => 'required|string', ]; @@ -115,4 +117,9 @@ public function toggleReaction(string $reaction): void $this->dispatch('comment:reaction:saved'); } + + public function getTipTapCssClasses(): ?string + { + return $this->tipTapCssClasses ?? Config::getTipTapCssClasses(); + } } diff --git a/src/Livewire/CommentList.php b/src/Livewire/CommentList.php index 2887391..4f687d7 100644 --- a/src/Livewire/CommentList.php +++ b/src/Livewire/CommentList.php @@ -19,6 +19,8 @@ class CommentList extends Component public Model $record; + public ?string $tipTapCssClasses = null; + public function render() { return view('commentions::comment-list'); diff --git a/src/Livewire/Comments.php b/src/Livewire/Comments.php index 2824998..c6876db 100644 --- a/src/Livewire/Comments.php +++ b/src/Livewire/Comments.php @@ -24,6 +24,8 @@ class Comments extends Component public string $commentBody = ''; + public ?string $tipTapCssClasses = null; + protected $rules = [ 'commentBody' => 'required|string', ]; @@ -67,4 +69,9 @@ public function getPlaceholder(): string { return __('commentions::comments.placeholder'); } + + public function getTipTapCssClasses(): ?string + { + return $this->tipTapCssClasses ?? Config::getTipTapCssClasses(); + } } From 5767fd25b7aa61c8f48ae8dd140756e2dd4d6853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Dalmolin?= Date: Sat, 25 Oct 2025 18:03:40 -0300 Subject: [PATCH 2/4] Updated readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f9777ed..faef36d 100644 --- a/README.md +++ b/README.md @@ -388,7 +388,7 @@ class User extends Authenticatable implements Commenter, HasName, HasAvatar ### Customizing TipTap Editor Styles -You can customize the TipTap editor CSS classes used using the `Config` class: +You can customize the TipTap editor CSS classes used using the `Config` class. ```php use Kirschbaum\Commentions\Config; @@ -418,6 +418,8 @@ CommentsAction::make() ->tipTapCssClasses('prose max-w-none focus:outline-none p-4') ``` +**Important**: Make sure to whitelist the classes in your Tailwind config if you override them. + ### Translations You can publish the package translation files and override any strings used by the UI. From adfdb426c9af35788feb0748c50825cf994f5a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Dalmolin?= Date: Sat, 25 Oct 2025 18:05:35 -0300 Subject: [PATCH 3/4] Fixed code style --- src/Filament/Concerns/HasTipTapCssClasses.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Filament/Concerns/HasTipTapCssClasses.php b/src/Filament/Concerns/HasTipTapCssClasses.php index fd404d3..2d2bca1 100644 --- a/src/Filament/Concerns/HasTipTapCssClasses.php +++ b/src/Filament/Concerns/HasTipTapCssClasses.php @@ -7,9 +7,9 @@ trait HasTipTapCssClasses { - protected string | Closure | null $tipTapCssClasses = null; + protected string|Closure|null $tipTapCssClasses = null; - public function tipTapCssClasses(string | Closure | null $classes): static + public function tipTapCssClasses(string|Closure|null $classes): static { $this->tipTapCssClasses = $classes; From eed113d1965180f7f281001f49fca21e8526a878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Dalmolin?= Date: Sat, 25 Oct 2025 18:09:08 -0300 Subject: [PATCH 4/4] Using default classes to avoid issues --- resources/js/commentions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/js/commentions.js b/resources/js/commentions.js index db8fdfa..617f169 100644 --- a/resources/js/commentions.js +++ b/resources/js/commentions.js @@ -8,6 +8,8 @@ document.addEventListener('alpine:init', () => { Alpine.data('editor', (content, mentions, component, placeholder, editorCssClasses) => { let editor + const defaultEditorCssClasses = `comm:prose comm:dark:prose-invert comm:prose-sm comm:sm:prose-base comm:lg:prose-lg comm:xl:prose-2xl comm:focus:outline-none comm:p-4 comm:min-w-full comm:w-full comm:rounded-lg comm:border comm:border-gray-300 comm:dark:border-gray-700`; + return { updatedAt: Date.now(), @@ -30,7 +32,7 @@ document.addEventListener('alpine:init', () => { ], editorProps: { attributes: { - class: editorCssClasses, + class: editorCssClasses || defaultEditorCssClasses, }, }, placeholder: 'Type something...',