Skip to content

Customizing the disclosure

How a theme changes the look of the ai_disclosure theme hook, without forking the module.

The class tree

Every class below is produced by templates/ai-disclosure.html.twig. "Legal" means the element is part of the disclosure itself, and a theme that removes it drops the disclosure. "Decoration" means it is presentation only, safe to restyle or remove.

Class Contains
ai-disclosure-wrapper The presentation wrapper around the disclosure, only printed when the "Style" display setting is "Card". With "Plain" it is not printed at all, and .ai-disclosure is the outermost element. Decoration
ai-disclosure-wrapper--card Modifier: the module's reference bordered-box look. Decoration
ai-disclosure The disclosure's structure. Also carries --required, --undetermined or --voluntary, and --unobtrusive when the ¶1 non-invasive form applies. Present regardless of style - the wrapper is what changes, not this. Legal (the element itself is needed to hold the label)
ai-disclosure--required Modifier: the label is legally required for this grade. Decoration (a styling hook; the verdict itself is label_requirement, not this class)
ai-disclosure--undetermined Modifier: the site has not determined whether the label is required. Always rendered, whatever the display's visibility setting. Decoration
ai-disclosure--voluntary Modifier: the label is shown by site policy, not by legal requirement. Decoration
ai-disclosure--unobtrusive Modifier: the Art. 50(4) ¶1 non-invasive form, for a manifestly artistic deep fake. Smaller footprint, never hidden - no display: none, no aria-hidden. Decoration
ai-disclosure__header The icon-left, text-right row. Structure
ai-disclosure__figure Wraps the icon, only present when there is one. Structure
ai-disclosure__picture The <picture> element, only in the automatic icon variant. Structure
ai-disclosure__icon The <img> itself. Sizing goes here, never on __picture: a <picture> element ignores height/width CSS, the browser paints the <img> inside it. Legal (the icon is the label the Commission defines)
ai-disclosure__text Wraps the sentence and the legal line. Structure
ai-disclosure__sentence The grade's disclosure sentence. Legal
ai-disclosure__legal The Art. 50(4) legal line: the site's disclosure notice when the label is required, its undetermined notice when the verdict is undetermined, absent when the label is not required. Legal
ai-disclosure__details The "How was AI used?" expandable section, only when there is a description. Decoration
ai-disclosure__summary The details element's summary text. Decoration
ai-disclosure__body The converted, filtered description markup. Decoration
ai-disclosure__statement The editorial statement link paragraph, only when configured. Decoration

Any row above can also be absent because the grade hides that part; see Grades. A grade cannot hide the icon or the sentence where the label is required. Write CSS that tolerates a missing part.

Custom properties

Set them on both selectors, .ai-disclosure-wrapper, .ai-disclosure. Custom properties inherit downwards only, and the card draws its border on the wrapper, which is the ancestor of .ai-disclosure: a value set on .ai-disclosure alone never reaches it.

Every rule reads them with a fallback, so a theme overrides what it needs and leaves the rest. A rule in the theme's own CSS is enough; the module's stylesheet stays untouched.

Property Default Effect
--ai-disclosure-gap 0.75em Space between the icon and the text in the header
--ai-disclosure-icon-height 2em The icon's rendered height (width follows, the icons are not square)
--ai-disclosure-border-width 1px Width of the card border and the details divider
--ai-disclosure-border-color rgb(128, 128, 128, 0.35) Color of the card border and the details divider
--ai-disclosure-border-radius 4px Corner radius of the card
--ai-disclosure-padding 1em 1.25em Inner padding of the card
--ai-disclosure-sentence-weight 700 Font weight of the disclosure sentence, card style only
--ai-disclosure-secondary-size 0.9em Font size of the legal line and the statement link, card style only
--ai-disclosure-secondary-opacity 0.75 Opacity of the legal line and the statement link, card style only
--ai-disclosure-divider-gap 0.75em Space above and below the divider that separates the details section from the header, card style only

Examples

Change only the border color from a theme

One rule in the theme's own CSS, and nothing else:

.ai-disclosure-wrapper,
.ai-disclosure {
  --ai-disclosure-border-color: rgb(20, 60, 120, 0.4);
}

Change only the card, keep the structure

The card lives on its own wrapper, .ai-disclosure-wrapper--card. Restyle that wrapper in the theme's own CSS and nothing inside .ai-disclosure changes:

.ai-disclosure-wrapper--card {
  border: 2px solid #333;
  border-radius: 0;
}

To drop the wrapper instead, set the display's "Style" setting to "Plain". The wrapper is then not printed at all and .ai-disclosure becomes the outermost element.

Replace the module's stylesheet with the theme's own

A mechanism of Drupal itself, not a setting of this module: it replaces the library's asset outright, regardless of any display setting.

# my_theme.info.yml
libraries-override:
  ai_disclosure/disclosure:
    css:
      component:
        css/ai-disclosure.css: css/my-theme-ai-disclosure.css

Overriding the template

The template itself is ai-disclosure.html.twig. A theme overrides it the usual Drupal way, by copying it into its own templates/ directory. Theme suggestions are available to target a specific grade or entity type without a preprocess hook:

  • ai-disclosure--[grade-id].html.twig, e.g. ai-disclosure--ai-deepfake.html.twig
  • ai-disclosure--[entity-type].html.twig, e.g. ai-disclosure--media.html.twig

How a theme changes the look of the compliance report page (/admin/reports/ai-disclosure) without forking the module.

The exposed filters

The exposed form is plain Views output: no template, no theme hook, no wrapper of this module's own - the same as core's own admin views (/admin/content, /admin/reports/dblog). The admin theme lays out labels and controls on its own; ai_disclosure.module does not alter the form at all.

The header

AiDisclosureUngradedSurface::render() (a views area plugin) builds the "Configuration notices" <details>, class ai-disclosure-report__notices, closed by default, titled with the notice count. Its only rule, the bottom margin, lives in css/ai-disclosure.css, part of the disclosure library.

The export command - "Export to CSV", two plain links, "Full" and "Filtered", the second naming its row count once a filter is active - belongs entirely to the ai_disclosure_csv_export submodule: its own template (templates/ai-disclosure-report-export.html.twig) and library (ai_disclosure_csv_export/export). The two links carry the admin theme's own button and button--small classes - their color, border, spacing and focus state all come from the theme, not from this module. Its own classes - ai-disclosure-report__export, __export-label, __export-link - stay alongside the theme's, so the command is still identifiable and themeable on its own; its stylesheet (css/ai-disclosure-report-export.css) adds the two rules the theme cannot give it on its own: aligning the command to the end of the view's footer, next to the pager, the same place core puts a feed's own alternate-format link, last; and the greyed-out look of "Filtered" when no filter is active - a plain, non-interactive <span> at that point, not a disabled <a>, since links have no disabled state of their own.

Class Contains
ai-disclosure-report__notices The <details> wrapping the "Ungraded surface" and "Broken disclosure references" lists, closed by default, titled with the notice count. Structure

Custom properties

None of the module's own: --ai-disclosure-report-* custom properties are not declared anywhere in ai_disclosure. The export submodule declares none of its own either - the links' appearance is the admin theme's button classes, not a local custom property.