How to add settings to your Discourse theme

Should the name of a theme setting be (globally) unique? In other words, could things break if I don’t prefix my setting names with something like my theme name?

1 Like

In JavaScript and hbs templates, there is no way this can happen. The settings variable that you use to access your theme settings is local to your theme and only contains your theme settings. In hbs templates, the settings of each theme are namespaced with their theme’s primary key in the database, so conflicts are impossible.

I’m not 100% sure about SCSS though, I think they don’t conflict, but I’ll need to test/confirm this.

4 Likes

4 posts were split to a new topic: Hide flag actions for current user when they’re flagged or the flagger

When I use a list in settings, I get the values as:

value1,value2,value3|value1,value2,value3

Is it possible to modify this output by declaring a different list_type? I’d like to use values from a list in Scss, but I think I could only de-structure the list if the output is formatted as

value1 value2 value3,
value1 value2 value3;

I think you can create custom SCSS functions to transform settings values into whatever format you want. E.g., in your case I think all you need is a string replace function that replaces commas with whitespace and pipes with commas? Here is an implementation of a string replace function in SCSS: Str-replace Function | CSS-Tricks

5 Likes

Thanks for the hint, @Osama :slight_smile:

In the end it wasn’t as straightforward as I would have thought. I used a function to split strings into lists, iterating twice over the list from theme settings and creating a nested list that can be used with the @rule.

nested-list.scss
@function str-to-list($string, $separator, $startAt: 1) {
  $item: str-slice($string, $startAt);
  $list: ();
  $index: str-index($item, $separator);
  @if $index == null {
    $list: ($item);
  } @else {
    $list: (str-slice($item, 1, $index - 1));
    $list: join($list, str-to-list($item, $separator, $startAt: $index + 1));
  }
  @return $list;
}

@function nested-list($componentList) {
  $list: str-to-list($componentList, "|");
  $nested-list: ();
  @each $item in $list {
    $item: str-to-list("#{$item}", ";");
    $nested-list: append($nested-list, $item);
  }
  @return $nested-list;
}
common.scss
@import "nested-list";

$myList: nested-list($list-from-settings);

@each $item1, $item2, $item3 in $myList {
  [..do sth with the deconstructed items..]
}

Working on this, I learned that all values from theme settings are provided as strings in Sass variables, regardless of the type that is declared in the settings file. Wouldn’t it make sense to provide numbers as numbers?

1 Like

@Osama hi, this might be because of the fact that have zero experience writting plugins or anything really that is not the most basic HTML/CSS but I want to do something with a theme I’m working on that I think should be extremely simple but can’t figure out where to start:

Basically, right now in the theme I’m making by default the background of user cards is white.

But even though I prefer it that way and think its the ‘ideal’ look for the theme, I do understand how it might take away from the the self-expression of users’ custom backgrounds. So I want it to have it instead by default, to work as normal (showing the users custom image) and that when the user toggles the setting, the css rule I made would be applied:

.user-card .card-content, .group-card .card-content {
    background: #fff;
}

Does this make sense? Is there any kind of documentation you can point me to? Because I feel I’m missing something to write the .yml and can’t tell what exactly so I can’t Google it :cold_sweat:

I misinterpreted the handlebar usage, see @nolo’s correction below: How to add settings to your Discourse theme - #56 by nolo


I think what you want are sections 1 and the very end of section 5 in the first post. You’ll need a boolean setting and you’ll need to wrap your CSS override in a handlebar conditional.

So in your theme’s settings.yaml you’ll need something like this:

hide_user_card_backgrounds: false

Then your CSS will look like this:

{{#if (theme-setting 'hide_user_card_backgrounds')}}
.user-card .card-content, .group-card .card-content {
    background: #fff;
}
{{/if}}
1 Like

@Simon_Manning thanks for your answer!

The bit about the syntax of settings.yaml I get from the OP, I get the logic behind it.

And I also get the logic on the conditional statement you wrote, I just don’t know exactly where that second bit of code is meant to go (I assume not in common.scss, right?). And if I should do anything else besides entering those two bits of code to get this to work :sweat:

Sorry if this seems super basic, I barely know what I’m doing, ha.

Handlebars is for templating html and you couldn’t just wrap CSS in a handlebar block helper.

To use a boolean in your style declarations you declare it in settings.yml:

hide_user_card_background:
  type: bool
  default: false

Then just refer to it in any Scss stylesheet:

@if $hide_user_card_background == 'true' {
  .user-card .card-content, .group-card .card-content {
    background: #fff;
  }
}
7 Likes

@nolo this works perfectly, thanks so much. Even though it works I do get an error message just after updating to the latest version of the theme:

Error: Undefined variable: “$hide-user-card-background”. on line 157 of common.scss >> @if $hide_user_card_background == ‘true’ { ----^

But I guess this is fine as in the OP it says:

In CSS, you’ll get a variable created for every setting of your theme and each variable will have the same name as the setting it represents.

So Discourse gives me the error because it doesn’t find the variable declared in the SCSS but it does exist because it was ‘created’ by setting.yml … ?

3 Likes

I’ve seen this happen before, there might be a bug in there somewhere.

Also, I’m not sure how much it matters… but I think the variable should be $hide-user-card-background (with hyphens replacing the underscores)

6 Likes

Yes, I also get errors sometimes related to variables with hyphens. Though I think it was never about variables from theme settings (and there actually seems to be no distinction between using hyphens and underscores in the stylesheets), but when declaring variables with hyphens as assets. E.g. $paint-brush as asset produced an error, but $paintBrush was fine.

3 Likes

Is it possible to access settings from another theme or component. e.g. if you have the category icons theme component installed, can you access information about the icons defined in its settings in a different custom theme component?

2 Likes

I’m afraid there is not a supported way to access the settings of another theme/component.

4 Likes

Hi!

I am in the process of making a new theme-component and have a few questions.

Is it possible to divide the settings into sections, e.g. with horizontal lines in between?

And is it possible to integrate some kind of heading?

3 Likes

No, neither of those things are possible at the moment. Having sections with titles does seem like it could be useful for themes with many settings though, good suggestion.

5 Likes

Thank you for your reply!

Yes, that’s the reason why I asked. I have a lot of settings. :grinning_face_with_smiling_eyes: :upside_down_face: :see_no_evil:

1 Like

I don’t know if this is the right topic to ask this, but I want to check if a setting is set or not, but not with a boolean.

I know how I can check it with

@if $circle == true {
    border-radius: $size / 2;
  }

But how do I check if it’s true with either the value px or %? Or is it possible to check if not null?
For example:

@if $circle IS NOT NULL {
    border-radius: $size / 2;
  }

Is this possible?


EDIT:

Is this right?

@if $circle not & {
    border-radius: $size / 2;
  }

I don’t know if and when this will be happen, but I have now over 100 settings and the list is very long now.
Since there’s still no way to handle this I have another idea:
Is it possible to have a theme-component (or a plugin) which will call my component in tabs like the whole admin menu is build?

I know where I can find everything but maybe I will release the component but then the user gets a shock! :smile:

No seriously, I’m looking for a way to accomplish this but I honestly don’t know all the possibilities of discourse.

Maybe someone has a better idea?

@awesomerobot
I know you are a pro, can you please have a look at this?