Skip to content
Merged
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ mosaic and tree list modes, global search, the tab menu and four dashboard block

### Added

- Help in a box (2026-10-28): the new `help_style` form option, `plain` (the default, the small
grey `adm-help` line under the control) or `box`, draws a field's help as a lighter box under the
control (`adm-help-box`) in the form's own text size — the label's and the control's 14px rather
than 12px — for forms whose help is part of the reading. Help given as markup (`help_html`) gets
its headings, paragraphs, lists and `code` styled in the box. The option is inherited, so an admin
sets it once in `configureFormOptions()` and its fields, sub-forms and collection entries (the
prototype too) follow; a field can pick the other style for itself. The new
`options.help_style` (default `plain`) is the default of every form. The help keeps its place,
its id and the `adminata-field-help` hook in both styles. The option comes from the new
`HelpStyleTypeExtension` (`adminata.admin.form.extension.help_style`); `form_help` reads its
`help_style` view variable. Moved here from recomaty-panel#682, whose prototype drew the box
with a form theme and a stylesheet of its own.

- The sidebar keeps its place across page loads (2026-10-22): a click on an entry of a scrolled
menu no longer throws the menu back to the top. The next page shows the menu where the last one
left it, then scrolls it by the least distance that shows the current screen's entry (all that
Expand Down
1 change: 1 addition & 0 deletions UPGRADE-1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ New nodes:
|---|---|---|
| `options.theme.mode` | `system` | `light`, `dark` or `system`; resolved server-side from the `adminata_theme` cookie, so a page never paints the wrong theme first |
| `options.list_row_link` | `true` | clicking a list row opens the object |
| `options.help_style` | `plain` | how a form field's help is drawn: `plain` (a small line under the control) or `box` (a lighter box in the form's text size); a form or a field picks its own with the `help_style` form option |
| `options.sidebar_logout` | `true` | sign-out in the toolbar above the sidebar menu, asking first; `false` drops it |
| `options.released_version` | `null` | the application's released version, a badge at the foot of the sidebar; pass it from the deploy (`'%env(default::RELEASED_VERSION)%'`), empty shows nothing |

Expand Down
88 changes: 88 additions & 0 deletions assets/css/components/misc.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@
}
}

/*
* `help_style: box` (Form\Extension\HelpStyleTypeExtension): the help under the control as a
* lighter box in the form's own reading size — the label's and the control's 14px, never
* `adm-help`'s 12px — for forms whose help is part of the reading. The dark card is white at 3%
* over the page; the box is a step lighter than the card. Its markup (`help_html`) is styled in
* the components layer below.
*/
@utility adm-help-box {
margin-top: 0.5rem;
padding: 0.75rem 1rem;
border: 1px solid var(--color-gray-100);
border-radius: var(--radius-control);
background-color: var(--color-gray-50);
color: var(--color-gray-600);
font-size: var(--text-theme-sm);
line-height: var(--text-theme-sm--line-height);
overflow-wrap: anywhere;

@variant dark {
border-color: var(--color-gray-800);
background-color: rgb(255 255 255 / 5%);
color: var(--color-gray-400);
}
}

@utility adm-error {
margin-top: 0.375rem;
color: var(--color-error-500);
Expand Down Expand Up @@ -222,4 +247,67 @@
transform: rotate(360deg);
}
}

/*
* Help given as markup (`help_html`) in an `adm-help-box`: headings, paragraphs, lists of
* placeholders and code, which the preflight leaves unstyled — a list without its bullets
* reads as one run-on line.
*/
.adm-help-box h3,
.adm-help-box h4 {
margin: 0.75rem 0 0.25rem;
color: var(--color-gray-700);
font-weight: 600;
}

.adm-help-box h3:first-child,
.adm-help-box h4:first-child {
margin-top: 0;
}

.adm-help-box p + p {
margin-top: 0.5rem;
}

.adm-help-box ul,
.adm-help-box ol {
margin-block: 0.25rem;
padding-inline-start: 1.25rem;
}

.adm-help-box ul {
list-style: disc;
}

.adm-help-box ol {
list-style: decimal;
}

.adm-help-box li + li {
margin-top: 0.125rem;
}

.adm-help-box b,
.adm-help-box strong {
color: var(--color-gray-700);
font-weight: 600;
}

.adm-help-box code {
padding-inline: 0.25rem;
border-radius: 0.25rem;
background-color: var(--color-gray-100);
font-size: 0.9em;
}

.dark .adm-help-box h3,
.dark .adm-help-box h4,
.dark .adm-help-box b,
.dark .adm-help-box strong {
color: var(--color-gray-300);
}

.dark .adm-help-box code {
background-color: rgb(255 255 255 / 8%);
}
}
1 change: 1 addition & 0 deletions assets/css/contract.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
".adm-form-row",
".adm-header",
".adm-help",
".adm-help-box",
".adm-icon-enum",
".adm-icon-enum__label",
".adm-input",
Expand Down
2 changes: 1 addition & 1 deletion assets/css/safelist.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions docs/admin-bundle/reference/action_create_edit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Adminata Options that may affect the create or edit view:
js_debug: false # enable or disable to show javascript debug messages
use_stickyforms: true # enable or disable the floating buttons
form_type: standard # can also be 'horizontal'
help_style: plain # can also be 'box', see "Help in a box" below

templates:
edit: '@Adminata/CRUD/edit.html.twig'
Expand Down Expand Up @@ -198,6 +199,35 @@ under all the columns, and a hook for ``adminata-reveal`` keeps working. Without
the tab is an ordinary grid of that many columns, one card per cell. The show page's tabs take
the same two options.

.. _form_help_box:

Help in a box
-------------

A field's ``help`` is a small grey line under the control (``adm-help``, 12px). For a form whose
help is part of the reading — long explanations, a list of the placeholders a template takes —
``help_style: box`` draws every help as a lighter box under the control instead
(``adm-help-box``), in the form's own text size, the label's and the control's. Help given as
markup (``help_html``) gets its headings, paragraphs, lists and ``code`` styled in the box.

The ``help_style`` form option is ``plain`` or ``box``, and it is inherited: a field or sub-form
that names none takes its parent's, so one admin sets it once for its whole form, collection
entries included::

final class DeviceSettingsAdmin extends AbstractAdmin
{
protected function configureFormOptions(array &$formOptions): void
{
$formOptions['help_style'] = 'box';
}
}

A single field can still pick the other style
(``->add('code', TextType::class, ['help' => '…', 'help_style' => 'plain'])``), and
``adminata.options.help_style: box`` makes the box the default of every form. In both styles the
help keeps its place under the control and its errors, its id and the ``adminata-field-help``
hook.

.. _form_tabs:

Tabs
Expand Down
3 changes: 3 additions & 0 deletions docs/admin-bundle/reference/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ is a container build error rather than a warning: ``options.skin``, ``options.us
# Open the object when a list row is clicked, using the route named by default_admin_route
list_row_link: true

# How a form field's help is drawn: plain, a small line under the control, or box, a lighter box in the form's text size; a form or a field picks its own with the help_style form option
help_style: plain # One of "plain"; "box"

# Offer sign-out in the toolbar above the sidebar menu, behind a firewall that configures a logout; it asks before it signs out
sidebar_logout: true

Expand Down
1 change: 1 addition & 0 deletions src/AdminataConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* default_translation_domain: string,
* dropdown_number_groups_per_colums: int,
* form_type: 'standard'|'horizontal',
* help_style: 'plain'|'box',
* html5_validate: bool,
* javascripts: list<string>,
* js_debug: bool,
Expand Down
3 changes: 3 additions & 0 deletions src/DependencyInjection/AdminataExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ public function load(array $configs, ContainerBuilder $container): void
->replaceArgument(0, $classes)
->replaceArgument(1, $config['options']);

$container->getDefinition('adminata.admin.form.extension.help_style')
->replaceArgument(0, $config['options']['help_style']);

// remove non-Mopa compatibility layer
if (isset($bundles['MopaBootstrapBundle'])) {
$container->removeDefinition('adminata.admin.form.extension.field.mopa');
Expand Down
6 changes: 6 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
* default_label_catalogue: string,
* dropdown_number_groups_per_colums: int,
* form_type: 'standard'|'horizontal',
* help_style: 'plain'|'box',
* html5_validate: bool,
* js_debug: bool,
* list_action_button_content: 'text'|'icon'|'all',
Expand Down Expand Up @@ -379,6 +380,11 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultTrue()
->info('Open the object when a list row is clicked, using the route named by default_admin_route')
->end()
->enumNode('help_style')
->values(['plain', 'box'])
->defaultValue('plain')
->info('How a form field\'s help is drawn: plain, a small line under the control, or box, a lighter box in the form\'s text size; a form or a field picks its own with the help_style form option')
->end()
->booleanNode('sidebar_logout')
->defaultTrue()
->info('Offer sign-out in the toolbar above the sidebar menu, behind a firewall that configures a logout; it asks before it signs out')
Expand Down
101 changes: 101 additions & 0 deletions src/Form/Extension/HelpStyleTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace IDCT\Adminata\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
* How a field's help is drawn: `plain`, the small grey line under the control, or `box`, a
* lighter box under the control set in the form's own text size, for forms whose help is
* part of the reading (recomaty/recomaty-panel#682).
*
* The `help_style` option is inherited. A form or field without one of its own takes its
* parent's, so an admin sets it once for its whole form — the root form's options, from
* `configureFormOptions()` — and its sub-forms and collection entries (the prototype too)
* follow; a field can still pick the other style for itself. A form at the top with none
* takes `adminata.options.help_style`.
*
* The resolved style is the view variable `help_style`, which `form_help` of
* `@Adminata/Form/form_admin_fields.html.twig` reads to pick `adm-help` or `adm-help-box`.
*/
final class HelpStyleTypeExtension extends AbstractTypeExtension
{
public const string PLAIN = 'plain';

public const string BOX = 'box';

/**
* @var list<string>
*/
public const array STYLES = [self::PLAIN, self::BOX];

/**
* @param string $default the style of a form at the top that names none, `adminata.options.help_style`
*/
public function __construct(
private readonly string $default = self::PLAIN,
) {
if (!\in_array($default, self::STYLES, true)) {
throw new \InvalidArgumentException(\sprintf(
'The default help style must be one of "%s", got "%s".',
implode('", "', self::STYLES),
$default,
));
}
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver
->setDefault('help_style', null)
->setAllowedValues('help_style', [null, ...self::STYLES])
->setInfo('help_style', 'How the help is drawn: "plain" or "box"; null takes the parent form\'s, and the top form\'s default is adminata.options.help_style.');
}

/**
* @param array<string, mixed> $options
*/
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$own = $options['help_style'] ?? null;

$view->vars['help_style'] = \is_string($own) ? $own : $this->inherited($view);
}

/**
* @return string[]
*
* @phpstan-return class-string<FormTypeInterface>[]
*/
public static function getExtendedTypes(): iterable
{
return [FormType::class];
}

/**
* The parent's resolved style. A parent's `buildView()` has run before its children's
* views are created, the collection prototype's included, so the variable is there.
*/
private function inherited(FormView $view): string
{
$parentStyle = $view->parent?->vars['help_style'] ?? null;

return \is_string($parentStyle) ? $parentStyle : $this->default;
}
}
10 changes: 10 additions & 0 deletions src/Resources/config/form_types.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use IDCT\Adminata\Form\Extension\ChoiceTypeExtension;
use IDCT\Adminata\Form\Extension\Field\Type\FormTypeFieldExtension;
use IDCT\Adminata\Form\Extension\Field\Type\MopaCompatibilityTypeFieldExtension;
use IDCT\Adminata\Form\Extension\HelpStyleTypeExtension;
use IDCT\Adminata\Form\Type\AdminType;
use IDCT\Adminata\Form\Type\ChoiceFieldMaskType;
use IDCT\Adminata\Form\Type\Filter\ChoiceType;
Expand Down Expand Up @@ -91,6 +92,15 @@
'extended_type' => SymfonyChoiceType::class,
])

// The `help_style` form option; its default is `adminata.options.help_style`.
->set('adminata.admin.form.extension.help_style', HelpStyleTypeExtension::class)
->tag('form.type_extension', [
'extended_type' => FormType::class,
])
->args([
abstract_arg('default help style'),
])

// NEXT_MAJOR: Remove this service definition.
->set('adminata.admin.form.filter.type.number', NumberType::class)
->tag('form.type', ['alias' => 'adminata_type_filter_number'])
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/public/app.css

Large diffs are not rendered by default.

Loading
Loading