Skip to content

Riverlea - add Stream entity - #32127

Merged
colemanw merged 8 commits into
civicrm:masterfrom
ufundo:riverlea-stream-entities
Jul 10, 2025
Merged

Riverlea - add Stream entity#32127
colemanw merged 8 commits into
civicrm:masterfrom
ufundo:riverlea-stream-entities

Conversation

@ufundo

@ufundo ufundo commented Feb 18, 2025

Copy link
Copy Markdown
Contributor

Overview

Move the Stream definitions in Riverlea from hard-coded to a new entity.

This enables a "Previewer" which allows you to switch streams locally, without changing the site settings.

Paves the way for future UI to a) pick a stream based on what it looks like on your site; b) editing and creating custom streams through the UI (AKA "Customiser").

Before

  • available streams are hard-coded in riverlea.php

After

  • streams are provided by a new entity RiverleaStream
  • streams can be viewed with Search Kit, edited with FormBuilder etc
  • external extensions can provide RiverLea streams using managed entity
  • dark mode option can be set at the stream level (though will fallback to the global setting if unset)
  • you can create a stream on one site and then export it using the ManagedEntity export (like you can with SearchKits)
  • you can open the console and type CRM.riverlea.previewer() to open a previewer widget, which allows you to switch between streams on the fly
  • streams can include custom_css, which allows for easy adding fixes. these are then cached via assetbuilder (essentially using the stream name and last modified as key) which overcomes the performance concerns with previous attempt at Customiser
  • streams can include vars defined using php, which could then be validated/updated automatically etc
Screencast.from.2025-02-18.14-27-34.mp4

(note all previewer changes are on the frontend and local to your current session - the site theme setting isn't touched. It does require starting with a Riverlea theme selected)

Work in progress

Need to add upgrader to create the new table on existing installs. I think this goes in the core upgrade step for core extensions?

Would be good to get some feedback on how it's working / overall schema.

Known Limitation

  • Previewer can't handle the civicrm.css override in Thames and Walbrook (it can only switch the var values on the fly). At this stage it's a dev tool, so I think it's reasonable. (I also think the overrides in Thames and Walbrook don't need to be in civicrm.css - they could be moved into the stream specific css file)
  • Asset builder cache buster on river.css will only track changes to the entity, but if you use css_file and modify the file it won't necessarily know. Again, I think this is reasonable. It's not expected to edit css files directly in production - and you (will soon) be able to edit custom_css on the entity if you need to.

Technical Details

  • Use a WebComponent <civi-riverlea-previewer>. I'm not sure how we feel about these but I think it's very nice for a self contained component that can use the API and talk to the browser.

@civibot

civibot Bot commented Feb 18, 2025

Copy link
Copy Markdown

🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷

Introduction for new contributors...
  • If this is your first PR, an admin will greenlight automated testing with the command ok to test or add to whitelist.
  • A series of tests will automatically run. You can see the results at the bottom of this page (if there are any problems, it will include a link to see what went wrong).
  • A demo site will be built where anyone can try out a version of CiviCRM that includes your changes.
  • If this process needs to be repeated, an admin will issue the command test this please to rerun tests and build a new demo site.
  • Before this PR can be merged, it needs to be reviewed. Please keep in mind that reviewers are volunteers, and their response time can vary from a few hours to a few weeks depending on their availability and their knowledge of this particular part of CiviCRM.
  • A great way to speed up this process is to "trade reviews" with someone - find an open PR that you feel able to review, and leave a comment like "I'm reviewing this now, could you please review mine?" (include a link to yours). You don't have to wait for a response to get started (and you don't have to stop at one!) the more you review, the faster this process goes for everyone 😄
  • To ensure that you are credited properly in the final release notes, please add yourself to contributor-key.yml
  • For more information about contributing, see CONTRIBUTING.md.
Quick links for reviewers...

➡️ Online demo of this PR 🔗

@ufundo

ufundo commented Feb 18, 2025

Copy link
Copy Markdown
Contributor Author

@vingle @totten @colemanw would be interested in your feedback on this.

@ufundo

ufundo commented Feb 18, 2025

Copy link
Copy Markdown
Contributor Author

(Just a note, if testing locally on a pre-existing site you will need to uninstall and then reinstall Riverlea in order to create the DB table)

@vingle

vingle commented Feb 18, 2025

Copy link
Copy Markdown
Contributor

I'm not in a position (skills-wise) to comment on the code changes here - I can't comment on other consequences they might have. I can only really look at this from a product perspective:

Firstly a previewer is definitely really nice - ThemeTest would benefit from that (I spend quantifiable time moving back and forth from Display Setting).

But this is more than that…

At present:

  • the path to creating custom streams is to create a subtheme extension, pointing to RiverLea. It's in the docs and it's a way to make Streams that survive upgrades.
  • from a css designer's perspective that's an appealing approach as it's relatively straightforward (ie low-coding skills) to clone a subtheme extension, then find and replace the name to your Stream name. As a method it survives upgrades to RiverLea (unless you rename all RL's variables, lol). It can then be moved from dev to production site, stored on a git repo, version controlled, offered to the public, etc

With this proposal:

  • a Stream is an entity… where are its files? What if it wants to bundle fonts or images? Would it still be a subtheme extension, but just that it would create a new entity on creation? Delete on uninstall?

And the benefit of all of this change is the previewer? Or Something else ("paves the way for future UI to a) pick a stream based on what it looks like on your site" - ie in a realtime preview?).

Side point: as RiverLea flows towards the big C of Civi Core - maybe it's name makes less and less sense? It's no longer a theme like Greenwich and more Civi's theme engine. So maybe - at least if it becomes an entity in core, its name should be something generic like CRMThemer, or at least more generic like 'river' (as river -> stream, is helpful naming to emphasise the cascade order of css).

@ufundo

ufundo commented Feb 18, 2025

Copy link
Copy Markdown
Contributor Author

Hey @vingle

With this approach I see two ways to make new streams:

  1. "No Code" => use the UI Customiser, hit an export button and get a Managed Entity text file. This can be
    a) copied and pasted into another site
    b) included in an extension
    c) stored in git
    (one day) d) uploaded to a library of community-contributed streams, which are then previewable on your site (without downloading anything)
    It's the same format as used for sharing Search Kits, so relatively familiar to folks who've worked with that.

  2. Code => similar to what you describe, you can basically copy the existing files for one of the existing streams into your own extension, change the minetta to yourstreamname and then you can work with the .css files directly. We could make a template extension to simplify the process. Previously you had to register the theme using hook_civicrm_themes - now you have to register it by creating a MyTheme.mgd.php but the contents are very similar. I can make template extension if you like?

The only advantage implemented in this PR is the previewer.

But it's a fairly small step from here to:

  • a stream-picker UI where you can choose which theme you want to use, with a preview before you activate it - "realtime preview" 👍
  • add snippets for hot-fixes
  • set colours and other vars through the UI
  • copy a stream through the UI, make some edits, flick back and forth between the original and your edited version

@vingle

vingle commented Feb 18, 2025

Copy link
Copy Markdown
Contributor

hit an export button and get a Managed Entity text file

So all of a stream's custom css (variables, darkmode versions) would be stored within the Entity?

If I store it in Git, someone else changes a bunch of variables, can I get that back into my system? Presumably any part of the entity can be edited?

I can make template extension if you like?

That'd be cool. I created an empty SubTheme extension at the end of last year which I think still works - I just made it public: https://github.com/vingle/branch with a Stream called 'Albany'. Might need a tiny bit more testing/docs before becomming a template.

I used the name 'branch' as that seems like a subsidiary water-system from a stream. But obvs branches have other meanings on git so perhaps another name works (I thought about 'estuary', 'tributary', 'source', 'channel', 'canal', 'brook' - branch seems the most accurate, but probably confusing).

set colours and other vars through the UI

That's interesting - maybe overlaps with the oembed stuff… ie for the example of someone creating a 'join newsletter' or 'petition' widget they want to embed on a dozen different sites, each with a different font and bg-colour… then giving each embed some unique class could let you save a unique variable… ie .crm-embed.website1 .afform-directive { --crm-font: "Times New Roman", serif; } and then .crm-embed.website2 .afform-directive { --crm-font: "Courier", monospace; } etc.

@ufundo

ufundo commented Feb 18, 2025

Copy link
Copy Markdown
Contributor Author

If I store it in Git, someone else changes a bunch of variables, can I get that back into my system? Presumably any part of the entity can be edited?

The standard way managed entities work is you a file version (which can be checked in to git). Then you have a database (database) version. These start in sync.

If you make edits to the database version (using the UI), you then have the option to a) export them - ie make the same changes to the file version; b) revert the database changes, go back to the file version.

If you make edits to the file version they will generally be synced to your database version (unless that has local changes - which you might not want to lose. In that case you have the option to revert to the file version to get the latest changes from the file.)

template extension

https://lab.civicrm.org/ufundo/river_rea/-/tree/dev . I called it river_rea which is obviously way too close to River Lea 🤦

estuary', 'tributary', 'source', 'channel', 'canal', 'brook' - branch

My thinking was that we don't need to create another hierarchy, and we should use stream for all the variations within River Lea. A stream = River Lea Theme = super easy to maintain theme.

(I've started seeing it the other way round, the stream is the little drops of ink you add to the river at the beginning, and then the river takes that and spreads it all over the UI :))

'petition' widget they want to embed on a dozen different sites, e

I think this approach would lend itself to adding a url parameter ie. https://mycivi.com/contribution-page?stream=my_blue_stream and https://mycivi.com/contribution-page?stream=my_green_stream which then loads the appropriate vars on that page (without having to add css classes programmatically, which would be hard I think).

@vingle

vingle commented Feb 18, 2025 via email

Copy link
Copy Markdown
Contributor

@ufundo

ufundo commented Feb 18, 2025

Copy link
Copy Markdown
Contributor Author

Further possibility with this kind of model: automating contrast checks between vars we know need to contrast. IE messages in the editor like "your crm-c-primary and crm-c-primary-text currently have contrast rating 5:1 which meets AA but you should increase for AAA"

@vingle

vingle commented Feb 19, 2025

Copy link
Copy Markdown
Contributor

automating contrast checks

Sold!

@ufundo

ufundo commented Feb 28, 2025

Copy link
Copy Markdown
Contributor Author

https://lab.civicrm.org/extensions/deptfordcreek/-/merge_requests/1 demonstrates the change in what "external streams" would look like before/after the core change.

The "external stream" could also put all it's var in the Managed file, and not have any separate css files.

@ufundo

ufundo commented Feb 28, 2025

Copy link
Copy Markdown
Contributor Author

I think we need thel change to _riverlea_is_active in this PR whether or not we go the entity route, so I've made a separate PR for it: #32263

@ufundo
ufundo force-pushed the riverlea-stream-entities branch 2 times, most recently from d6bfa48 to 26d4898 Compare March 12, 2025 08:35
@ufundo ufundo changed the title Riverlea - add Stream entity and previewer Riverlea - add Stream entity Mar 12, 2025
@ufundo

ufundo commented Mar 12, 2025

Copy link
Copy Markdown
Contributor Author

I've narrowed this down to just the entity plumbing.

Listing, Previewing + Editing are separated to #32344

@ufundo
ufundo marked this pull request as ready for review March 12, 2025 08:57
@ufundo

ufundo commented Apr 4, 2025

Copy link
Copy Markdown
Contributor Author

retest this please

@ufundo
ufundo force-pushed the riverlea-stream-entities branch from 26d4898 to dee729c Compare April 8, 2025 19:28
@colemanw

colemanw commented May 5, 2025

Copy link
Copy Markdown
Member

@ufundo some test failures here...

@ufundo
ufundo force-pushed the riverlea-stream-entities branch 3 times, most recently from 89fbaa6 to 9cdac76 Compare May 19, 2025 20:12
@ufundo

ufundo commented May 19, 2025

Copy link
Copy Markdown
Contributor Author

tests should pass now @colemanw

( a static/non-static function got dropped in rebasing somehow 😬 )

Comment thread ext/riverlea/CRM/riverlea/Upgrader.php Outdated
*/
class CRM_riverlea_Upgrader extends \CRM_Extension_Upgrader_Base {

// By convention, functions that look like "function upgrade_NNNN()" are

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ufundo Looks like an upgrader is needed to add the new sql table (and all this boilerplate clutter can be deleted too).

I recently updated the docs about how to do so: https://docs.civicrm.org/dev/en/latest/step-by-step/create-entity/#5b-add-upgrade-step-for-extensions-used-in-production

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah thanks that's what I was after!

'input_type' => 'Select',
'description' => ts('Extension that provides this stream.'),
'default' => NULL,
// @todo why not work?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think because the civicrm_extension table is slightly odd.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's kind of immaterial for now... for the time being this will always be provided by a *.mgd.php and it won't make sense to edit it.

@colemanw colemanw May 20, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ufundo which part doesn't work? The FK index in SQL? Or the join in Api4?
If the former, it's now possible to declare an EntityRef without the FK index like so:

'entity_reference' => [
'entity' => 'SearchDisplay',
'key' => 'id',
// Core tables get created before extension tables, so a FK constraint
// can't be added to this column.
'fk' => FALSE,
],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still doesn't work in SearchKit / Formbuilder. I can't a) join Stream records to Extension records, b) in-place edit that field, c) add an afform filter.

I think maybe it's because file is not the primary key on civicrm_extension ? But we need to use a machine name (rather than id) because this is typically set in a managed record ( https://github.com/civicrm/civicrm-core/pull/32127/files#r2104616568 ).

I think for now it is fine to not have the entity_reference for now?

'label' => E::ts('Hackney Brook'),
'description' => 'named after the Hackney Brook, a tributary of the River Lea that ran through Finsbury Park',
'is_reserved' => TRUE,
'extension' => 'riverlea',

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where extension is set

@ufundo
ufundo force-pushed the riverlea-stream-entities branch from 8be0500 to fbac906 Compare June 11, 2025 15:54
@ufundo
ufundo force-pushed the riverlea-stream-entities branch from fbac906 to e9b567e Compare June 11, 2025 17:20
@ufundo

ufundo commented Jun 11, 2025

Copy link
Copy Markdown
Contributor Author

Did a more thorough pass of the README.

One change (maybe controversial) is to remove use of "subtheme" as I think it a source of confusion. It suggests that the streams are subthemes of the Riverlea theme. But for a user, there is no theme they can select called Riverlea. Riverlea is an extension, and each of the streams is a theme that you can select as your site theme. I think Stream = Riverlea Theme
works well.

Comment thread ext/riverlea/README.md Outdated
@vingle

vingle commented Jun 11, 2025

Copy link
Copy Markdown
Contributor

Did a more thorough pass of the README.

Looks great - thanks! Just two comments above.

One change (maybe controversial) is to remove use of "subtheme" as I think it a source of confusion. It suggests that the streams are subthemes of the Riverlea theme. But for a user, there is no theme they can select called Riverlea. Riverlea is an extension, and each of the streams is a theme that you can select as your site theme. I think Stream = Riverlea Theme
works well.

The architecture before was using Civi's subtheme functions - but I'm assuming this PR ends that? I was going to suggest mentioning sub-themes once at the start to help people, but it's true there's no loadable RiverLea theme so maybe it's better they use the new term.

@aydun

aydun commented Jun 11, 2025

Copy link
Copy Markdown
Contributor

The architecture before was using Civi's subtheme functions - but I'm assuming this PR ends that? I was going to suggest mentioning sub-themes once at the start to help people, but it's true there's no loadable RiverLea theme so maybe it's better they use the new term.

On the topic of sub-thingies ... does this let us create a "sub-stream": a stream that inherits from another stream and applies overrides? This is different to modifying a full clone to create a new stream.

"No Code" => use the UI Customiser, hit an export button and get a Managed Entity text file. This can be

There could be 2 versions of this:

  1. the Managed Entity file is the entire definition - the original stream provided a useful starting and now I'm on my own.
  2. the Managed Entity file specifies the name of the parent stream with only the variables that are different - I want all the improvements as the parent stream develops, but overlaid with my tweaks.

@vingle

vingle commented Jun 12, 2025

Copy link
Copy Markdown
Contributor

does this let us create a "sub-stream": a stream that inherits from another stream and applies overrides?

That's what the goal is with the Customiser (still a draft), forking an existing core stream (a brook?!). I don't think that's available with this PR tho - right @ufundo? Streams created as new entities via the API will still inherit directly from Minetta? Or can that be changed to other Streams with this?

But - I agree with the principle should be to only store in a new stream/sub-stream the minimum that's changed.

The customiser UI will also only expose a limited number of variables - one of the roadmap jobs with RL is how to simplify it to allow fewer variables to have more impact. Most people don't want to understand how five different background colours work with each other across Civi; that's RL implementing Greenwich+Shoreditch faithfully; most people expect to have one bg colour that cascades to other background regions with tints automatically.

@ufundo

ufundo commented Jun 16, 2025

Copy link
Copy Markdown
Contributor Author

Good questions.

The architecture before was using Civi's subtheme functions - but I'm assuming this PR ends that?

It still uses the same search_order cascade, which is the sense that the streams could be called "sub themes" of _riverlea_core_. But a) AFAIK nothing outside of riverlea uses the term "sub-theme" for the cascade, that's a Riverlea-ism; b) it's under the hood, and not that relevant to user experience of picking a stream.

On the topic of sub-thingies ... does this let us create a "sub-stream": a stream that inherits from another stream and applies overrides? This is different to modifying a full clone to create a new stream.
There could be 2 versions of this:

the Managed Entity file is the entire definition - the original stream provided a useful starting and now I'm on my own.
the Managed Entity file specifies the name of the parent stream with only the variables that are different - I want all the improvements as the parent stream develops, but overlaid with my tweaks.

the principle should be to only store in a new stream/sub-stream the minimum that's changed.

So at the moment I have been working on the copy-and-edit approach. There's no direct support for this. I actually started with a parent_id to set streams as parents/children of other streams - but on working on the Customiser I got the sense this is actually not that helpful. I think it complicates more than it benefits, and that flat is better than nested here, because

  • inheritance leaves a tangled trail for stream editors:

    • "why are these icons in this one particular place "purple?! oh it's because the primary colour theme colour is set purple in parent theme, I've overridden that in my child theme to blue, but the parent theme had a slightly different shade of purple for primary-icons."
    • "oh I can really easily change some small thing about this stream.. arghhh! I didnt realise this would affect a child theme I made a long time ago for some very small specific purpose"
  • inheritance makes life difficult for automatic upgraders. part of the rationale of using a Stream entity is that it is possible to write upgraders if there are structural changes (e.g. to variable names). The names used for this variable changed in this release => no worries we can write an upgrader to update the definitions of existing streams. Upgraders are generally much safer and more straightforward if you can look at each record in isolation "if a stream has this combo of 3 variables, xyz needs to change". But when you have inheritance it's very hard to say if a stream (including all its parents) has this combo of 3 variables. You can't assume updating each stream can be done record by record, without worrying about the order.

  • inheritance makes upstream development harder "I want all the improvements as the parent stream develops, but overlaid with my tweaks." would be ideal. But in practice it's hard to avoid clashes between my improvements upstream and your tweaks. If everyone starts making sub-themes of Walbrook, I think in reality it would quickly become too scary to make any changes to Walbrook itself, for fear of how it would cascade.

  • The focus of Riverlea development going forward should be stuff that improves ALL streams My sense is that the next stages of Riverlea are improving the core cascades, with things that benefit all streams - the starter ones and the ones other folks make. There might be some little flourishes in Minetta etc... but you shouldn't miss out on much with the copy-and-amend model. Key stuff like assuring accessibility should be implemented across all streams, rather than a stream at a time (= key motivator for Riverlea)

  • Streams should be SIMPLE - my sense is most streams should have a small set of variables (like, 20?) which then cascade automatically to provide a consistent experience throughout the UI. It may be you copy 18 of those variables from Thames to get the starting look, and then change 2 or 3. Maybe you set 20 directly. At any rate I think folks should be able to style CiviCRM WITHOUT having to get to grips with dozens and dozens of variables, and how these interact with dozens more in the parent stream, and the parent of the parent etc

  • As a general rule, reconciling layers of multi-dimensional config is hard. "only store in a new stream the minimum that's changed" is a nice principle, but from that principle stems git.... We don't want to create git for civicrm themes...

Notwithstanding the above:

  • Nothing about this change stops you from hooking into hook_civicrm_managed directly, as previously described in the README. (Though I think that doesn't actually work that well at the moment, because of the dynamic variable loading in order to respect dark mode settings.)
  • It would still be very much possible to add inheritance between streams in the future.

most people expect to have one bg colour that cascades to other background regions with tints automatically

100% this.

@ufundo

ufundo commented Jun 16, 2025

Copy link
Copy Markdown
Contributor Author

Streams created as new entities via the API will still inherit directly from Minetta? Or can that be changed to other Streams with this

With the customiser, you can create a blank stream (which will then inherit from core, and look like Minetta), or you can copy an existing stream (Walbrook or Hackney or one you made) and then tweak it.

@ufundo

ufundo commented Jun 16, 2025

Copy link
Copy Markdown
Contributor Author

Just remembering @vingle 's presentation on Riverlea...

To put it in those terms, I see it as:

  • Riverlea core is the fresh layer of plaster
  • your stream is the wallpaper.

By all means start from an existing wallpaper design when coming up with a new one. But we shouldn't get into the business of layering different wallpapers with semi-transparent bits on top of each other.

@ufundo

ufundo commented Jun 16, 2025

Copy link
Copy Markdown
Contributor Author

And maybe an initial disclaimer? "Creating and supporting your own stream is at your own risk; this is new functionality within Civi and we can't guarantee the way this works won't change."

Added a note to the intro of Customising to say it's early days (as this applies to adding vars to parent theme too).

I also added a snippet for if you want to override one or two vars directly (this is an alternate approach that may work in the short term for some simple use cases)

@ufundo

ufundo commented Jun 16, 2025

Copy link
Copy Markdown
Contributor Author

One use case I can see for inheritance:

I have my "org theme" which has 20 vars set. But then I want to do a dozen "campaign themes" which use 19 vars but set the primary colour differently.

If I want to make a change to the button-roundness across the board, how?

I think it's relevantly different that I am the maintainer of the parent and child themes... they are a cluster. But it would be nice to avoid having to change that button-roundness var on every one of my dozen campaign themes.

One way this can be handled with the structure in this PR is:

  • put the basic 20 vars in my_ext/stream/main.css
  • set css_file / file_prefix to point at that file for all of my campaign themes
  • set the campaign-specific vars in the stream vars directly

That way all streams use the same css file source, but can tweak at the entity level. You can update the css file once and it will affect all the campaign streams.

In this sense there's a bit of inheritance built in within each stream, which can be leveraged for this sort of thing.

@ufundo

ufundo commented Jun 16, 2025

Copy link
Copy Markdown
Contributor Author

Further drawback of inheritance... you end up with versioned dependency issues.

I'm hoping that people will share nice streams they have made for others to use. This is much easier if the stream definition is self-contained -- NOT "my porpoise stream is a sub-stream of Rich's dolphin stream, but you need to make sure you have dolphin version at least 1.2a but it doesn't work with v2".

Comment thread ext/riverlea/README.md
Exploring the _variables.css file will give you idea of how much can be overwritten.
### 2. Add a custom CSS snippet in an extension

You can override variables by listening to `hook_civicrm_alterBundle`:

@vingle vingle Jun 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm,

As this isn't something I've ever done (this is an existing function, not something you added with this pr, right?)… if you add a snippet in an extension - how does someone else find out that an extension has added a css snippet making all my buttons purple, and how do they turn it off?

I'm happy to tell themers that they can stick :root {--crm-c-primary: green; } in a theme css file and it will apply front end or backend if they want a quick fix. If it breaks other things it's quick to find where it's loading via an Inspector.

But I can picture extension devs potentially doing unpredictable things here to make their own extension look like they want it (increase padding between buttons, e.g.). Inspector won't reveal where this comes from - how many themers are going to be comfortable (or know that's what they should do) debugging an odd colour / spacing issue via API explorer? They'd just be forced to turn off RiverLea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is existing functionality, and it's a bit quick and dirty.

I was imagining it for my_client_extension rather than adding to my_feature_extension.

TBH you could do it in my_feature_extension if you are careful about scoping, ie something like:

.my-feature-container {
  --crm-button-spacing: 1rem;
}

Maybe adding a health warning here or an example like the above would help? We can't stop extension authors enqueing buggy css, so I think "here's some advice" is better than nothing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't stop extension authors enqueing buggy css, so I think "here's some advice" is better than nothing.

But we can also not advise them how to do it - and just remove this new bit?
Otherwise we're just saying 'there's this other thing you can do, but don't do it!'.
(my concern is that most people who agencies give the job of fixing css are looking for files to edit - not the dbse.)

Perhaps there could be info that an advantage of CSS variables for extension developers is you can make small extension specific changes without writing css but by changing the variables within the scope of your extension. E.g.

<div class="a-large-button">
  <button>Name</button
</div>

<style>
.a-large-button { 
    --crm-btn-padding-inline: 1rem;
    --crm-btn-height: 3rem;
 }
</style>

But this is more of a docs discussion…

@vingle

vingle commented Jun 16, 2025

Copy link
Copy Markdown
Contributor

Really good points here @ufundo. 100% agree if the tldr is 'lets try to avoid sub-streams unless the sub-stream and stream are from the same dev.

I think the question has a front-end / back-end divide more than anything. Back-end - most people I'm guessing will settle on a stream, with minor tweaks, unless they're doing something like Nook or One Click and want their own unique UI (or have unique accessibility needs like @aydun's current Finsbury Park fork - which I guess could be a sub-stream of Hackney).

But front-end, I could picture an agency who tends to build front-end sites using Framework Z (hopefully not a really css framework). Their Civi pages need to integrate so they make a stream that does 90% of the integration work which they ship with all their Civis. But every site they build has it's own design so they need to sub-theme their stream.

Still I can see why that creates a cascade of risks, literally - so perhaps we either shout 'only do this at your own risk' or we leave this for a future development - at least within the customiser. I guess it would just mean you would treat a sub-stream as a core stream in the Customiser UI?

@ufundo

ufundo commented Jun 17, 2025

Copy link
Copy Markdown
Contributor Author

build front-end sites using Framework Z... so they make a stream that does 90% of the integration work which they ship with all their Civi

I think if its a frontend theme used outside of Civi, then that could integrate with Riverlea using vars etc WITHOUT being a stream (more along the lines of option 1). It's a more manual integration... but if you are a shop building something more bespoke then I think that's reasonable. But I don't think streams themselves should be over-engineered for this kind of use case (and I think you could probably make it work in a way that allows you to overlay tweaks using streams - i.e. a combo of Option 1 and 3).

I guess it would just mean you would treat a sub-stream as a core stream in the Customiser UI?

There's an is_reserved flag on streams. The UI doesn't let you edit those. That's the only difference between "core" streams and any others atm.

@vingle

vingle commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

Jenkins test this please

@colemanw

colemanw commented Jul 3, 2025

Copy link
Copy Markdown
Member

Looks to me like discussion has simmered down on this PR and we're at a point of fine-tuning that could be addressed in followups. I say we merge this & continue those discussions via chat or gitlab or followup PRs.

@colemanw colemanw added the merge ready PR will be merged after a few days if there are no objections label Jul 3, 2025
@ufundo

ufundo commented Jul 10, 2025

Copy link
Copy Markdown
Contributor Author

Shall we merge? That gives us some alpha testing and some beta testing.

@colemanw
colemanw merged commit f9b2dd4 into civicrm:master Jul 10, 2025
@vingle

vingle commented Jul 14, 2025

Copy link
Copy Markdown
Contributor

I'm guessing this fatal error is linked to this?

[14-Jul-2025 14:41:15 Europe/London] Uncaught PHP Exception Error: "Class "CRM_riverlea_DAO_RiverleaStream" not found" at ~/Sites/localhost/dru-civi/vendor/civicrm/civicrm-core/Civi/Api4/Generic/AbstractEntity.php line 101

It won't let me access /civicrm/upgrade?reset=1 to run the dbse update I guess this depends on (?). cc @ufundo

Update: deleting templates_c fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

master merge ready PR will be merged after a few days if there are no objections

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants