diff --git a/docs/search/available-methods.md b/docs/search/available-methods.md
index 1d8397a5f..422757c37 100644
--- a/docs/search/available-methods.md
+++ b/docs/search/available-methods.md
@@ -192,3 +192,39 @@ public function configure(): void
$this->setTrimSearchStringDisabled();
}
```
+
+## Search Icon
+
+To help customise, a "Search Input Icon" has been added, allowing for the addition of an icon to the search input field.
+
+At present, the Search Icon is only available as a "left aligned" icon.
+
+This is presently only available for Tailwind implementations
+
+### setSearchIcon
+
+This adds an Icon to the Search Input Field, which expects an icon path (e.g. heroicon-m-magnifying-glass)
+
+```php
+public function configure(): void
+{
+ $this->setSearchIcon('heroicon-m-magnifying-glass');
+}
+```
+
+### setSearchIconAttributes
+
+This allows you to specify attributes for the Search Icon for the Input Field.
+
+Note that classes will be injected prior to styles, due to the behaviour of icons.
+
+```php
+public function configure(): void
+{
+ $this->setSearchIconAttributes([
+ 'class' => 'h-4 w-4',
+ 'style' => 'color: #000000',
+ ]);
+}
+
+```
\ No newline at end of file
diff --git a/resources/views/components/tools/toolbar/items/search-field.blade.php b/resources/views/components/tools/toolbar/items/search-field.blade.php
index 6bc8bb9c5..a52f06427 100644
--- a/resources/views/components/tools/toolbar/items/search-field.blade.php
+++ b/resources/views/components/tools/toolbar/items/search-field.blade.php
@@ -3,8 +3,21 @@
$this->isBootstrap,
- 'flex rounded-md shadow-sm' => $this->isTailwind,
+ 'rounded-md shadow-sm' => $this->isTailwind,
+ 'flex' => !$this->hasSearchIcon,
+ 'relative inline-flex flex-row' => $this->hasSearchIcon,
])>
+
+ @if($this->hasSearchIcon)
+
+
+ @svg($this->getSearchIcon, $this->getSearchIconClasses, $this->getSearchIconOtherAttributes())
+
+
+ @endif
+
getSearchOptions() }}="search"
placeholder="{{ $this->getSearchPlaceholder() }}"
@@ -12,11 +25,12 @@
{{
$attributes->merge($this->getSearchFieldAttributes())
->class([
- 'block w-full rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 rounded-none rounded-l-md focus:ring-0 focus:border-gray-300' => $this->isTailwind && $this->hasSearch() && (($this->getSearchFieldAttributes()['default'] ?? true) || ($this->getSearchFieldAttributes()['default-styling'] ?? true)),
- 'block w-full rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 rounded-md focus:ring focus:ring-opacity-50' => $this->isTailwind && !$this->hasSearch() && (($this->getSearchFieldAttributes()['default'] ?? true) || ($this->getSearchFieldAttributes()['default-styling'] ?? true)),
+ 'rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 rounded-none rounded-l-md focus:ring-0 focus:border-gray-300' => $this->isTailwind && $this->hasSearch() && (($this->getSearchFieldAttributes()['default'] ?? true) || ($this->getSearchFieldAttributes()['default-styling'] ?? true)),
+ 'rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 rounded-md focus:ring focus:ring-opacity-50' => $this->isTailwind && !$this->hasSearch() && (($this->getSearchFieldAttributes()['default'] ?? true) || ($this->getSearchFieldAttributes()['default-styling'] ?? true)),
'border-gray-300 dark:bg-gray-700 dark:text-white dark:border-gray-600 focus:border-gray-300' => $this->isTailwind && $this->hasSearch() && (($this->getSearchFieldAttributes()['default'] ?? true) || ($this->getSearchFieldAttributes()['default-colors'] ?? true)),
'border-gray-300 dark:bg-gray-700 dark:text-white dark:border-gray-600 focus:border-indigo-300 focus:ring-indigo-200' => $this->isTailwind && !$this->hasSearch() && (($this->getSearchFieldAttributes()['default'] ?? true) || ($this->getSearchFieldAttributes()['default-colors'] ?? true)),
-
+ 'block w-full' => !$this->hasSearchIcon,
+ 'pl-8 pr-4' => $this->hasSearchIcon,
'form-control' => $this->isBootstrap && $this->getSearchFieldAttributes()['default'] ?? true,
])
->except(['default','default-styling','default-colors'])
diff --git a/src/Traits/Configuration/SearchConfiguration.php b/src/Traits/Configuration/SearchConfiguration.php
index 77590071f..2a1c6e926 100644
--- a/src/Traits/Configuration/SearchConfiguration.php
+++ b/src/Traits/Configuration/SearchConfiguration.php
@@ -147,20 +147,6 @@ public function setSearchLazy(): self
return $this;
}
- public function setSearchPlaceholder(string $placeholder): self
- {
- $this->searchPlaceholder = $placeholder;
-
- return $this;
- }
-
- public function setSearchFieldAttributes(array $attributes = []): self
- {
- $this->setCustomAttributes('searchFieldAttributes', array_merge(['default' => false, 'default-colors' => false, 'default-styling' => false], $attributes));
-
- return $this;
- }
-
public function setTrimSearchString(bool $status): self
{
$this->trimSearchString = $status;
diff --git a/src/Traits/Helpers/SearchHelpers.php b/src/Traits/Helpers/SearchHelpers.php
index b9637b13c..387155271 100644
--- a/src/Traits/Helpers/SearchHelpers.php
+++ b/src/Traits/Helpers/SearchHelpers.php
@@ -121,25 +121,6 @@ public function getSearchOptions(): string
return '.live';
}
- public function getSearchPlaceholder(): string
- {
- if ($this->hasSearchPlaceholder()) {
- return $this->searchPlaceholder;
- }
-
- return __($this->getLocalisationPath().'Search');
- }
-
- public function hasSearchPlaceholder(): bool
- {
- return $this->searchPlaceholder !== null;
- }
-
- public function getSearchFieldAttributes(): array
- {
- return $this->getCustomAttributes('searchFieldAttributes', true);
- }
-
public function shouldTrimSearchString(): bool
{
return $this->trimSearchString ?? false;
diff --git a/src/Traits/Styling/HasSearchFieldStyling.php b/src/Traits/Styling/HasSearchFieldStyling.php
new file mode 100644
index 000000000..01283773e
--- /dev/null
+++ b/src/Traits/Styling/HasSearchFieldStyling.php
@@ -0,0 +1,11 @@
+ 'h-4 w-4', 'style' => 'color: #000000'];
+
+ #[Computed]
+ public function hasSearchIcon(): bool
+ {
+ return $this->searchIconSet;
+ }
+
+ #[Computed]
+ public function getSearchIcon(): string
+ {
+ return $this->hasSearchIcon() ? $this->searchIcon : 'heroicon-m-magnifying-glass';
+ }
+
+ #[Computed]
+ public function getSearchIconClasses(): string
+ {
+ return $this->getSearchIconAttributes()['class'];
+
+ }
+
+ #[Computed]
+ public function getSearchIconAttributes(): array
+ {
+ return $this->searchIconAttributes;
+ }
+
+ #[Computed]
+ public function getSearchIconOtherAttributes(): array
+ {
+ return collect($this->getSearchIconAttributes())->except('class')->toArray();
+ }
+
+ protected function setSearchIconStatus(bool $searchIconStatus): self
+ {
+ $this->searchIconSet = $searchIconStatus;
+
+ return $this;
+ }
+
+ protected function searchIconEnabled(): self
+ {
+ return $this->setSearchIconStatus(true);
+ }
+
+ protected function searchIconDisabled(): self
+ {
+ return $this->setSearchIconStatus(false);
+ }
+
+ protected function setSearchIcon(string $searchIcon): self
+ {
+ $this->searchIcon = $searchIcon;
+
+ return $this->searchIconEnabled();
+ }
+
+ protected function setSearchIconAttributes(array $searchIconAttributes): self
+ {
+ $this->searchIconAttributes = array_merge($this->searchIconAttributes, $searchIconAttributes);
+
+ return $this->searchIconEnabled();
+ }
+}
diff --git a/src/Traits/Styling/Search/HasSearchInput.php b/src/Traits/Styling/Search/HasSearchInput.php
new file mode 100644
index 000000000..f937f5ef5
--- /dev/null
+++ b/src/Traits/Styling/Search/HasSearchInput.php
@@ -0,0 +1,45 @@
+setCustomAttributes('searchFieldAttributes', array_merge(['default' => false, 'default-colors' => false, 'default-styling' => false], $attributes));
+
+ return $this;
+ }
+
+ public function getSearchFieldAttributes(): array
+ {
+ return $this->getCustomAttributes('searchFieldAttributes', true);
+ }
+
+ public function setSearchPlaceholder(string $placeholder): self
+ {
+ $this->searchPlaceholder = $placeholder;
+
+ return $this;
+ }
+
+ public function getSearchPlaceholder(): string
+ {
+ if ($this->hasSearchPlaceholder()) {
+ return $this->searchPlaceholder;
+ }
+
+ return __($this->getLocalisationPath().'Search');
+ }
+
+ public function hasSearchPlaceholder(): bool
+ {
+ return $this->searchPlaceholder !== null;
+ }
+}
diff --git a/src/Traits/WithSearch.php b/src/Traits/WithSearch.php
index ddfe98553..f4befabf9 100644
--- a/src/Traits/WithSearch.php
+++ b/src/Traits/WithSearch.php
@@ -8,20 +8,20 @@
use Rappasoft\LaravelLivewireTables\Traits\Configuration\SearchConfiguration;
use Rappasoft\LaravelLivewireTables\Traits\Core\QueryStrings\HasQueryStringForSearch;
use Rappasoft\LaravelLivewireTables\Traits\Helpers\SearchHelpers;
+use Rappasoft\LaravelLivewireTables\Traits\Styling\HasSearchFieldStyling;
trait WithSearch
{
use SearchConfiguration,
SearchHelpers;
use HasQueryStringForSearch;
+ use HasSearchFieldStyling;
public string $search = '';
#[Locked]
public bool $searchStatus = true;
- protected ?string $searchPlaceholder = null;
-
protected bool $searchVisibilityStatus = true;
protected ?bool $searchFilterBlur = null;
@@ -36,8 +36,6 @@ trait WithSearch
protected ?int $searchFilterThrottle = null;
- protected array $searchFieldAttributes = [];
-
protected bool $trimSearchString = false;
// TODO
diff --git a/tests/Unit/Traits/Configuration/SearchConfigurationTest.php b/tests/Unit/Traits/Configuration/SearchConfigurationTest.php
index 9daec3aeb..cc55f8362 100644
--- a/tests/Unit/Traits/Configuration/SearchConfigurationTest.php
+++ b/tests/Unit/Traits/Configuration/SearchConfigurationTest.php
@@ -3,6 +3,7 @@
namespace Rappasoft\LaravelLivewireTables\Tests\Unit\Traits\Configuration;
use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
+use Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\PetsTable;
use Rappasoft\LaravelLivewireTables\Tests\TestCase;
final class SearchConfigurationTest extends TestCase
@@ -180,11 +181,159 @@ public function test_can_set_search_placeholder(): void
public function test_can_set_search_field_attributes(): void
{
- $this->assertSame(['default' => true, 'default-colors' => true, 'default-styling' => true], $this->basicTable->getSearchFieldAttributes());
+ $mock = new class extends PetsTable
+ {
+ public ?array $testAttributesArray;
- $this->basicTable->setSearchFieldAttributes(['class' => 'bg-blue', 'style' => 'font-size: 3em;']);
+ public function configure(): void
+ {
+ $this->setDataTableFingerprint('test');
+ }
- $this->assertSame(['class' => 'bg-blue', 'default' => false, 'default-colors' => false, 'default-styling' => false, 'style' => 'font-size: 3em;'], $this->basicTable->getSearchFieldAttributes());
+ public function pubSetSearchFieldAttributes(array $attributes)
+ {
+ $this->setSearchFieldAttributes($attributes);
+ }
+ };
+
+ $mock->configure();
+ $mock->boot();
+
+ $this->assertSame(['default' => true, 'default-colors' => true, 'default-styling' => true], $mock->getSearchFieldAttributes());
+
+ $mock->pubSetSearchFieldAttributes(['class' => 'bg-blue', 'style' => 'font-size: 3em;']);
+
+ $this->assertSame(['class' => 'bg-blue', 'default' => false, 'default-colors' => false, 'default-styling' => false, 'style' => 'font-size: 3em;'], $mock->getSearchFieldAttributes());
+
+ }
+
+ public function test_can_set_search_icon(): void
+ {
+ $mock = new class extends PetsTable
+ {
+ public ?array $testAttributesArray;
+
+ public function configure(): void
+ {
+ $this->setDataTableFingerprint('test');
+ }
+
+ public function pubSetSearchFieldAttributes(array $attributes)
+ {
+ $this->setSearchFieldAttributes($attributes);
+ }
+
+ public function pubSetSearchIcon(string $searchIcon)
+ {
+ $this->setSearchIcon($searchIcon);
+ }
+
+ public function pubSetSearchIconAttributes(array $attributes)
+ {
+ $this->setSearchIconAttributes($attributes);
+ }
+ };
+
+ $mock->configure();
+ $mock->boot();
+
+ $this->assertFalse($mock->hasSearchIcon());
+ $mock->pubSetSearchIcon('heroicon-m-magnifying-glass-2');
+ $this->assertTrue($mock->hasSearchIcon());
+
+ $this->assertSame($mock->getSearchIcon(), 'heroicon-m-magnifying-glass-2');
+
+ }
+
+ public function test_can_set_search_icon_status(): void
+ {
+ $mock = new class extends PetsTable
+ {
+ public ?array $testAttributesArray;
+
+ public function configure(): void
+ {
+ $this->setDataTableFingerprint('test');
+ }
+
+ public function pubSetSearchFieldAttributes(array $attributes)
+ {
+ $this->setSearchFieldAttributes($attributes);
+ }
+
+ public function pubSetSearchIconEnabled()
+ {
+ $this->searchIconEnabled();
+ }
+
+ public function pubSetSearchIconDisabled()
+ {
+ $this->searchIconDisabled();
+ }
+ };
+
+ $mock->configure();
+ $mock->boot();
+
+ $this->assertFalse($mock->hasSearchIcon());
+ $mock->pubSetSearchIconEnabled();
+
+ $this->assertTrue($mock->hasSearchIcon());
+ $mock->pubSetSearchIconDisabled();
+ $this->assertFalse($mock->hasSearchIcon());
+
+ }
+
+ public function test_can_set_search_icon_attributes(): void
+ {
+ $mock = new class extends PetsTable
+ {
+ public ?array $testAttributesArray;
+
+ public function configure(): void
+ {
+ $this->setDataTableFingerprint('test');
+
+ }
+
+ public function pubSetSearchFieldAttributes(array $attributes)
+ {
+ $this->setSearchFieldAttributes($attributes);
+ }
+
+ public function pubSetSearchIcon(string $searchIcon)
+ {
+ $this->setSearchIcon($searchIcon);
+ }
+
+ public function pubSetSearchIconAttributes(array $attributes)
+ {
+ $this->setSearchIconAttributes($attributes);
+ }
+ };
+
+ $mock->configure();
+ $mock->boot();
+
+ $this->assertSame('h-4 w-4', $mock->getSearchIconClasses());
+ $this->assertSame([
+ 'style' => 'color: #000000',
+ ], $mock->getSearchIconOtherAttributes());
+
+ $mock->pubSetSearchIconAttributes([
+ 'style' => 'color: #FF0000',
+ 'class' => 'h-6 w-6',
+ ]);
+
+ $this->assertSame('h-6 w-6', $mock->getSearchIconClasses());
+ $this->assertSame([
+ 'style' => 'color: #FF0000',
+ ], $mock->getSearchIconOtherAttributes());
+
+ $this->assertSame([
+ 'class' => 'h-6 w-6',
+ 'style' => 'color: #FF0000',
+ ], $mock->getSearchIconAttributes());
}
}