diff --git a/CHANGELOG.md b/CHANGELOG.md index 3adee70813c..fdd9dc589cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -157,6 +157,7 @@ - Added `CraftCms\Cms\Element\Data\ElementSiteSettings`, the shared base for element URI and route settings. ([#19762](https://github.com/craftcms/cms/pull/19762)) - Added support for fluent plugin settings classes. ([#19574](https://github.com/craftcms/cms/pull/19574)) - Added support for refreshable standard plugin settings forms and conditional configuration of core form nodes. ([#19545](https://github.com/craftcms/cms/pull/19545)) +- Added `CraftCms\Cms\Form\Nodes\Group::expanded()`, allowing collapsible section groups to start expanded in Vue and HTML forms. ([#19772](https://github.com/craftcms/cms/pull/19772)) - Added `CraftCms\Cms\Route\CurrentElement`, a contextual attribute for injecting the matched element into controller actions and route closures. ([#19762](https://github.com/craftcms/cms/pull/19762)) - Added `CraftCms\Cms\Contracts\PluginInterface::createSettings()`, which replaces `createSettingsModel()`. ([#19574](https://github.com/craftcms/cms/pull/19574)) - Added `CraftCms\Cms\Dashboard\Widgets\Widget::component()` and `props()`, which replace `getBodyHtml()`. ([#19564](https://github.com/craftcms/cms/pull/19564)) diff --git a/resources/js/modules/forms/GroupNode.vue b/resources/js/modules/forms/GroupNode.vue index a5dae93d583..fac771b964e 100644 --- a/resources/js/modules/forms/GroupNode.vue +++ b/resources/js/modules/forms/GroupNode.vue @@ -13,6 +13,7 @@ type GroupNodeProps = { label?: string | null; collapsible?: boolean; + expanded?: boolean; /** Renders the group as one field rather than a section — see `Nodes\Group`. */ asField?: boolean; required?: boolean; @@ -104,6 +105,9 @@ v-else :is="node.props.collapsible ? 'craft-disclosure' : 'fieldset'" :label="node.props.collapsible ? node.props.label : undefined" + .opened=" + node.props.collapsible ? (node.props.expanded ?? false) : undefined + " :class="{ [`width-${node.props.width}`]: Boolean(node.props.width), hidden: Boolean(node.props.hidden), diff --git a/src/Form/Nodes/Group.php b/src/Form/Nodes/Group.php index fd1fd030b44..c5b2093e16b 100644 --- a/src/Form/Nodes/Group.php +++ b/src/Form/Nodes/Group.php @@ -49,6 +49,8 @@ class Group extends Container private bool $collapsible = false; + private bool $expanded = false; + private bool $asField = false; private bool $required = false; @@ -87,6 +89,7 @@ public static function renderHtml(NodePayload $node, FormPayload $payload, FormH if ($node->props['collapsible'] ?? false) { return Html::tag('craft-disclosure', $children->toHtml(), [ 'label' => $label, + 'opened' => $node->props['expanded'] ?? false, ...$attributes, ]); } @@ -115,6 +118,14 @@ public function collapsible(bool $collapsible = true): static return $this; } + /** Section appearance only; ignored unless the group is {@see self::collapsible()}. */ + public function expanded(bool $expanded = true): static + { + $this->expanded = $expanded; + + return $this; + } + /** * Renders the group as one field rather than a section — see the class * docblock. Takes precedence over {@see self::collapsible()}. @@ -194,6 +205,7 @@ public function props(): array return [ 'label' => $this->label, ...($this->collapsible && ! $this->asField ? ['collapsible' => true] : []), + ...($this->collapsible && ! $this->asField && $this->expanded ? ['expanded' => true] : []), ...($this->asField ? ['asField' => true] : []), ...($this->asField && $this->required ? ['required' => true] : []), ...Arr::whereNotNull([