Skip to content

feat(elements): add h2-as-heading and h2-as-intro stylesheets - #683

Open
wesleyboar wants to merge 8 commits into
TACC:mainfrom
wesleyboar:feat/h2-as-heading-and-intro
Open

feat(elements): add h2-as-heading and h2-as-intro stylesheets#683
wesleyboar wants to merge 8 commits into
TACC:mainfrom
wesleyboar:feat/h2-as-heading-and-intro

Conversation

@wesleyboar

Copy link
Copy Markdown
Member

Overview

Adds two opt-in stylesheets that let a site override how core-styles.cms.css styles a bare <h2>, without changing core-styles.cms.css itself.

Related

Changes

  • added core-styles.h2-as-heading.css — resets a bare <h2> to a plain heading (browser defaults), for sites using <h2> correctly. Does not affect .h2/p.h2.
  • added core-styles.h2-as-intro.css — reproduces core-styles.cms.css's current <h2> treatment as a standalone file, compiled from the same mixins so it can't drift. No-op atop v2 today; published now so it's ready for sites that need it once that default changes.

Testing

  1. npm run build:css
  2. git status --short dist/ — only dist/core-styles.h2-as-heading.css and dist/core-styles.h2-as-intro.css should appear; no other dist/*.css changes.

Notes

No CHANGELOG entry (frozen) and no version bump, per current release-via-GitHub-Releases process.

core-styles.cms.css styles a bare <h2> as a large, accent-colored intro
paragraph, a legacy pattern from CMS editors misusing <h2> instead of
<p class="h2">. That default cannot change without breaking existing CMS
content, so this adds two opt-in stylesheets instead:

- core-styles.h2-as-heading.css: resets <h2> to a plain heading, for sites
  using <h2> correctly, loadable atop core-styles.cms.css today.
- core-styles.h2-as-intro.css: reproduces cms.css's current <h2> treatment
  standalone, compiled from the same mixins so it can't drift. A no-op atop
  v2 today; published now so it is ready if that default ever changes.

Neither affects .h2/p.h2, which is a separate, unscoped selector already.
Replace prose explanation with a permalink to the source file each patches
against, plus a cross-reference to its sibling file.
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add opt-in h2 override stylesheets (plain heading vs CMS intro)

✨ Enhancement 🕐 10-20 Minutes

Grey Divider

AI Description

• Add opt-in stylesheet to revert bare  back to browser-default heading styles.
• Add opt-in stylesheet to preserve CMS “intro paragraph”  styling via shared mixins.
• Publish both as built dist assets so sites can load them without changing cms defaults.
Diagram

graph TD
  A["src/_imports h2 heading"] --> B(("CSS build")) --> C["dist h2 heading"]
  D["src/_imports h2 intro"] --> B --> E["dist h2 intro"]
  F["dist core-styles.cms"] --> G["Consumer site"]
  C --> G
  E --> G
  subgraph Legend
    direction LR
    _src["Source CSS"] ~~~ _build(("Build step")) ~~~ _dist["Dist CSS"] ~~~ _site["Consumer"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Change core-styles.cms.css default styling
  • ➕ Eliminates need for extra opt-in assets
  • ➕ Simplifies consumer configuration long-term
  • ➖ High risk of breaking existing CMS content that relies on current presentation
  • ➖ Requires coordinated rollout and remediation across sites
2. Gate styling behind CSS layers or a feature flag variable
  • ➕ Keeps a single cms stylesheet while allowing per-site opt-in/opt-out
  • ➕ Can provide a clearer upgrade path with defaults controlled centrally
  • ➖ Introduces new layering/flag conventions that consumers must understand
  • ➖ Still requires careful backward compatibility and documentation
3. Scope legacy intro styling to explicit classes only (e.g., .h2 / p.h2)
  • ➕ Encourages semantic HTML by default
  • ➕ Removes surprising element-level styling
  • ➖ Breaks existing CMS content that uses bare for intro text
  • ➖ Requires content migration or templating changes

Recommendation: The PR’s approach (shipping two opt-in stylesheets) is the safest compatibility strategy: it avoids breaking legacy CMS markup while giving standards-compliant sites a clean, explicit way to restore semantic behavior. Keeping the “intro” variant compiled from the same mixins as cms.css is also a strong choice to prevent drift if the default changes later.

Files changed (4) +51 / -0

Enhancement (4) +51 / -0
core-styles.h2-as-heading.cssAdd built dist stylesheet to revert bare h2 to defaults +2/-0

Add built dist stylesheet to revert bare h2 to defaults

• Introduces a minified, published CSS asset that resets bare <h2> color, sizing, weight, and margins using revert. Intended to be loaded after core-styles.cms.css to restore semantic heading behavior without affecting .h2/p.h2.

dist/core-styles.h2-as-heading.css

core-styles.h2-as-intro.cssAdd built dist stylesheet that preserves CMS intro-style h2 +2/-0

Add built dist stylesheet that preserves CMS intro-style h2

• Introduces a minified, published CSS asset that applies the CMS “intro paragraph” treatment to bare <h2> within main content scope. This is intended as a future-proof opt-in once cms.css changes its default behavior.

dist/core-styles.h2-as-intro.css

core-styles.h2-as-heading.cssAdd source entrypoint for h2-as-heading override +21/-0

Add source entrypoint for h2-as-heading override

• Adds a documented import entrypoint that restores bare <h2> to browser defaults via revert properties. Explicitly documents why cms.css styles <h2> differently and clarifies that .h2/p.h2 are not impacted.

src/lib/_imports/core-styles.h2-as-heading.css

core-styles.h2-as-intro.cssAdd source entrypoint for h2-as-intro override using shared mixins +26/-0

Add source entrypoint for h2-as-intro override using shared mixins

• Adds a documented import entrypoint that recreates cms.css’s bare <h2> styling using shared selector utilities and heading mixins. Scopes the rule to main content and excludes portal/React app areas to match existing CMS behavior.

src/lib/_imports/core-styles.h2-as-intro.css

@qodo-code-review

qodo-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Portal h2 styles not scoped ⊘ Outdated 🐞 Bug ≡ Correctness
Description
In core-styles.h2-as-intro.css, the selector :where(:--main-content, :not(:--portal-content)) is
an OR-condition and :--portal-content expands to just #root, so the rule can match <h2> outside
main content and still apply within portal content. This contradicts the in-file comments (“not
header, not navbar” and “prevent … within a React app”) and can cause unintended global <h2>
restyling when a site opts into this stylesheet.
Code

src/lib/_imports/core-styles.h2-as-intro.css[R21-24]

+:where(:--main-content, :not(:--portal-content)) {
+    & h2 {
+        @mixin heading;
+        @mixin heading-2;
Evidence
The new stylesheet uses :where(:--main-content, :not(:--portal-content)), but :--portal-content
is defined as #root, so the selector cannot exclude portal descendants and is not limited to main
content; the built dist output shows the expanded selector used at runtime.

src/lib/_imports/core-styles.h2-as-intro.css[19-26]
src/lib/_imports/tools/selectors.common.css[10-13]
dist/core-styles.h2-as-intro.css[1-2]
src/lib/_imports/elements/headings--cms.css[5-9]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`core-styles.h2-as-intro.css` intends to style bare `<h2>` only in main content and exclude portal/React content, but its selector uses an OR list (`:where(:--main-content, :not(:--portal-content))`) and `:--portal-content` maps to `#root`, so the rule scope is effectively much broader than described.

## Issue Context
- `:--portal-content` is defined as `#root`.
- The current selector compiles to `:where(:is([role=main],main),:not(:is(#root))) h2`, which still matches `<h2>` inside `#root` because ancestors like `body` are `:not(#root)`.

## Fix Focus Areas
- src/lib/_imports/core-styles.h2-as-intro.css[19-26]
- src/lib/_imports/tools/selectors.common.css[10-13]

## Suggested change
Update the selector to require main-content **and** ensure that main-content is not inside portal content. For example:

```css
:where(:--main-content):not(:where(:--portal-content) *) {
 & h2 {
   @mixin heading;
   @mixin heading-2;
 }
}
```

Then re-run the CSS build so `dist/core-styles.h2-as-intro.css` reflects the corrected scope.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/lib/_imports/core-styles.h2-as-intro.css Outdated
Move core-styles.h2-as-heading.css and core-styles.h2-as-intro.css into
elements/ as unprefixed partials, matching where headings--cms.css itself
lives and how every other elements/ file is named.

Add two top-level stylesheets that import them and describe their purpose
by migration direction rather than by CSS mechanism:

- core-styles.v3-bridge-for-v2-users.css: imports h2-as-heading.css
- core-styles.v2-bridge-for-v3-users.css: imports h2-as-intro.css

This also lets each absorb future unrelated v2/v3 breaking changes under
the same name, instead of accumulating one top-level file per fix.

Also drops the now-outdated `:not(:--portal-content)` scoping from
h2-as-intro.css (tup-ui no longer loads core-styles.cms.css); a follow-up
PR will remove the same stale scoping from elements/headings--cms.css.
Rename core-styles.v3-bridge-for-v2-users.css and
core-styles.v2-bridge-for-v3-users.css to core-styles.cms.v3-bridge-for-v2-users.css
and core-styles.cms.v2-bridge-for-v3-users.css, since both are specific to
core-styles.cms.css's <h2> treatment, not a general v2/v3 difference.
wesleyboar added a commit that referenced this pull request Aug 6, 2026
…684)

## Overview

Removes the `:not(:--portal-content)` scoping branch from
`elements/headings--cms.css`, per its own long-standing TODO.

<details>

TACC/tup-ui no longer loads `core-styles.cms.css`, so the exclusion it
called out no longer applies.

</details>

## Related

- follow-up from #683

## Changes

- **removed** `:--portal-content` use and definition

## Testing

Skipped. Basic change, multiple places.

> [!TIP]
> I, @wesleyboar, human, verified TUP-UI's portal app does **not** load
`….cms.css`.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Wesley B <wesleyboar@users.noreply.github.com>
Show how to append core-styles.cms.v3-bridge-for-v2-users.css atop
core-styles.cms.css for projects preparing for v3 early.
wesleyboar added a commit to wesleyboar/Core-Styles that referenced this pull request Aug 6, 2026
Show how to append core-styles.cms.v2-bridge-for-v3-users.css atop
core-styles.cms.css for v3 sites whose CMS content still uses <h2> as an
intro paragraph.

The stylesheet itself isn't added here — it'll arrive via the merge of
main after TACC#683 lands, rather than being hand-ported.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant