diff --git a/src/Elements/Attributes/ClassNames.php b/src/Elements/Attributes/ClassNames.php index 9c33c10..672fa30 100644 --- a/src/Elements/Attributes/ClassNames.php +++ b/src/Elements/Attributes/ClassNames.php @@ -233,7 +233,15 @@ protected function variantClassNames(): array // Start with default always $variants = new BaseCollection('default'); - // Merge in other variants if they're set + // Apply implicit variants + $implicit = ['disabled', 'readonly', 'required']; + foreach ($implicit as $attribute) { + if ($this->element->attributes->get($attribute, false)) { + $variants->push($attribute); + } + } + + // Merge in other variants if they're set (last, so that they take precedence) if ($variant = $this->element->getViewData('variant')) { $variants = $variants->merge((array) $variant); } diff --git a/tests/Unit/VariantTest.php b/tests/Unit/VariantTest.php index fad5da9..1b6504f 100644 --- a/tests/Unit/VariantTest.php +++ b/tests/Unit/VariantTest.php @@ -153,4 +153,76 @@ public function test_variants_can_be_combined_and_partially_merged(): void 'input-not-nested-variant', ]); } + + public function test_disabled_variant_is_applied_dynamically(): void + { + $this->app['config']->set('aire.variant_classes', [ + 'input' => [ + 'default' => [ + 'base' => 'input-default', + ], + 'disabled' => [ + 'base' => 'input-disabled', + 'color' => 'input-disabled-color', + ], + ], + ]); + + $disabled = $this->aire()->input()->disabled(); + $enabled = $this->aire()->input()->disabled()->disabled(false); // set then unset + + $this->assertSelectorClassNames($disabled, 'input', ['input', 'input-disabled', 'input-disabled-color']); + $this->assertSelectorMissingClassNames($disabled, 'input', ['input-default']); + + $this->assertSelectorClassNames($enabled, 'input', ['input', 'input-default']); + $this->assertSelectorMissingClassNames($enabled, 'input', ['input-disabled', 'input-disabled-color']); + } + + public function test_readonly_variant_is_applied_dynamically(): void + { + $this->app['config']->set('aire.variant_classes', [ + 'input' => [ + 'default' => [ + 'base' => 'input-default', + ], + 'readonly' => [ + 'base' => 'input-readonly', + 'color' => 'input-readonly-color', + ], + ], + ]); + + $read_only = $this->aire()->input()->readOnly(); + $read_write = $this->aire()->input()->readOnly()->readOnly(false); // set then unset + + $this->assertSelectorClassNames($read_only, 'input', ['input', 'input-readonly', 'input-readonly-color']); + $this->assertSelectorMissingClassNames($read_only, 'input', ['input-default']); + + $this->assertSelectorClassNames($read_write, 'input', ['input', 'input-default']); + $this->assertSelectorMissingClassNames($read_write, 'input', ['input-readonly', 'input-readonly-color']); + } + + public function test_required_variant_is_applied_dynamically(): void + { + $this->app['config']->set('aire.variant_classes', [ + 'input' => [ + 'default' => [ + 'base' => 'input-default', + ], + 'required' => [ + 'base' => 'input-required', + 'color' => 'input-required-color', + ], + ], + ]); + + $required = $this->aire()->input()->required(); + $optional = $this->aire()->input()->required()->required(false); // set then unset + + $this->assertSelectorClassNames($required, 'input', ['input', 'input-required', 'input-required-color']); + $this->assertSelectorMissingClassNames($required, 'input', ['input-default']); + + $this->assertSelectorClassNames($optional, 'input', ['input', 'input-default']); + $this->assertSelectorMissingClassNames($optional, 'input', ['input-required', 'input-required-color']); + } }