<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.socialstack.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ablewhite</id>
	<title>SocialStack - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.socialstack.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ablewhite"/>
	<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Special:Contributions/Ablewhite"/>
	<updated>2026-10-16T08:44:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.36.2</generator>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Role_Permits&amp;diff=661</id>
		<title>Role Permits</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Role_Permits&amp;diff=661"/>
		<updated>2024-04-26T16:08:27Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Role permits are a mechanism which allow any content to be visible based on role. This is most frequently used by pages to make multiple variations of a page. The page displayed to the user is ultimately the one which the permission system selected for them. &lt;br /&gt;
&lt;br /&gt;
This is useful for multiple reasons: Firstly, it allows you to use the editor for each role variation of the content. You don&amp;#039;t need to try and be in the context of a given role when making changes to a page, for example. Second, the content for other roles is not present in the source of the page, keeping that content safer if it is, for example, paid for content.&lt;br /&gt;
&lt;br /&gt;
Role permits are not active for content by default. You must make use of them in your [[Permissions|permission rules]] with &amp;quot;HasRolePermit()&amp;quot;. This also means you can use them as part of a more complex permission rule, or invert it if you want your list of roles to represent *excluded* roles:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
!HasRolePermit()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Role_Permits&amp;diff=660</id>
		<title>Role Permits</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Role_Permits&amp;diff=660"/>
		<updated>2024-04-26T16:04:14Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Role permits are a mechanism which allow any content to be visible based on role. This is most frequently used by pages to make multiple variations of a page. The page displayed to the user is ultimately the one which the permission system selected for them. &lt;br /&gt;
&lt;br /&gt;
This is useful for multiple reasons: Firstly, it allows you to use the editor for each role variation of the content. You don&amp;#039;t need to try and be in the context of a given role when making changes to a page, for example. Second, the content for other roles is not present in the source of the page, keeping that content safer if it is, for example, paid for content.&lt;br /&gt;
&lt;br /&gt;
Role permits are not active for content by default. You must make use of them in your [[Permissions|permission rules]] with &amp;quot;HasRolePermits()&amp;quot;. This also means you can use them as part of a more complex permission rule, or invert it if you want your list of roles to represent *excluded* roles:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
!HasRolePermits()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Role_Permits&amp;diff=659</id>
		<title>Role Permits</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Role_Permits&amp;diff=659"/>
		<updated>2024-04-26T16:03:56Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Role permits are a mechanism which allow any content to be visible based on role. This is most frequently used by pages to make multiple variations of a page. The page displayed to the user is ultimately the one which the permission system selected for them. &lt;br /&gt;
&lt;br /&gt;
This is useful for multiple reasons: Firstly, it allows you to use the editor for each role variation of the content. You don&amp;#039;t need to try and be in the context of a given role when making changes to a page, for example. Second, the content for other roles is not present in the source of the page, keeping that content safer if it is, for example, paid for content.&lt;br /&gt;
&lt;br /&gt;
Role permits are not active for content by default. You must make use of them in your [[Permissions|permission rules]] with &amp;quot;HasRolePermit()&amp;quot;. This also means you can use them as part of a more complex permission rule, or invert it if you want your list of roles to represent *excluded* roles:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
!HasRolePermits()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=File_Uploads&amp;diff=542</id>
		<title>File Uploads</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=File_Uploads&amp;diff=542"/>
		<updated>2023-05-26T10:04:06Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: Added section detailing `file-consistency` API&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SocialStack has a mechanism for uploading public or private files. When a file is uploaded, the upload endpoint will return a [[File Refs|file ref]] for the new file, which is then typically the main way to refer to a particular file.&lt;br /&gt;
&lt;br /&gt;
By default, when uploading an image file, it will automatically be resized into a collection of different sizes for convenience. This works on modern image formats like webp too.&lt;br /&gt;
&lt;br /&gt;
If you need video to be handled as well, you can either install the Api/FFmpeg module and ffmpeg on the target servers (ffmpeg is installed by default on all SocialStack cloud servers), or perform remote transcoding with huddle servers. Transcoding video is a very heavy process but usually mandatory if a CDN is involved in your project due to the file size limits of a CDN, and also end users benefit by being able to skip through the video substantially faster.&lt;br /&gt;
&lt;br /&gt;
= Displaying a file uploader =&lt;br /&gt;
&lt;br /&gt;
Use type=&amp;quot;file&amp;quot; for a file uploader. When the form is submitted, the value will be the [[File Refs|file ref]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import Input from &amp;#039;UI/Input&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Input type=&amp;quot;file&amp;quot; name=&amp;quot;myFile&amp;quot; label=&amp;quot;My File Uploader&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This defaults to storing files in the public file store. If you want them to be private, add the isPrivate prop:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import Input from &amp;#039;UI/Input&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Input type=&amp;quot;file&amp;quot; name=&amp;quot;myFile&amp;quot; label=&amp;quot;My File Uploader&amp;quot; isPrivate /&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Making use of an uploaded file =&lt;br /&gt;
&lt;br /&gt;
== On the frontend ==&lt;br /&gt;
&lt;br /&gt;
An uploaded file is represented as a [[File Refs|file ref]] on the frontend - see the [[File Refs|file ref wiki article]] on how to work with those on the frontend.&lt;br /&gt;
&lt;br /&gt;
== In the API ==&lt;br /&gt;
&lt;br /&gt;
As an upload is a content type, you can subscribe to Upload related events to handle when a new file is uploaded. This is often not the easiest to work with though; more on that in a moment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Events.Upload.AfterCreate.AddEventListener(async (Context context, Upload upload) =&amp;gt; {&lt;br /&gt;
    &lt;br /&gt;
    if(upload == null) {&lt;br /&gt;
        return upload;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Do something with upload here.&lt;br /&gt;
    &lt;br /&gt;
    return upload;&lt;br /&gt;
&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// AfterUpdate, AfterDelete etc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, because this event runs whenever any file is uploaded, there&amp;#039;s no context on why it was uploaded. This is fine if you&amp;#039;re building something like a transcoder which just cares about file type, but not if you&amp;#039;re making something that requires a specific file. Instead, it&amp;#039;s recommended to make a custom endpoint which receives a ref for that situation.&lt;br /&gt;
&lt;br /&gt;
For example, the frontend may have a form like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;Form action=&amp;quot;attendee/from-csv&amp;quot; submitLabel=&amp;quot;Apply&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;Input type=&amp;quot;file&amp;quot; label=&amp;quot;Attendee CSV&amp;quot; name=&amp;quot;csvRef&amp;quot; isPrivate/&amp;gt;&lt;br /&gt;
&amp;lt;/Form&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the file is uploaded and the form is submitted, a JSON payload containing a field called csvRef will get posted to the endpoint, and the payload would look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;csvRef&amp;quot;: &amp;quot;private:42.csv?s=...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From there, a C# asp.net controller method can capture the ref value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[HttpPost(&amp;quot;from-csv&amp;quot;)]&lt;br /&gt;
public async ValueTask FromCsv([FromBody] CsvRefPayload payload)&lt;br /&gt;
{&lt;br /&gt;
    var context = await Request.GetContext();&lt;br /&gt;
    var csvRef = payload.csvRef; // the string&lt;br /&gt;
&lt;br /&gt;
    // Do something fun with the csvRef here! (there&amp;#039;s more on handling refs in the API in the file ref wiki).&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
public class CsvRefPayload&lt;br /&gt;
{&lt;br /&gt;
    public string csvRef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information on using a ref in the API, see the [[File Refs|file ref wiki page]].&lt;br /&gt;
&lt;br /&gt;
= Upload metadata =&lt;br /&gt;
&lt;br /&gt;
== On the frontend ==&lt;br /&gt;
&lt;br /&gt;
File uploads are a content type (called Upload), meaning all the usual conveniences apply: you can list all uploads, use Loop on them and so on - provided the user has permission to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Loop over=&amp;#039;upload&amp;#039;&amp;gt;{anUpload =&amp;gt; &amp;lt;&amp;gt;{anUpload.originalName}&amp;lt;/&amp;gt;}&amp;lt;/Loop&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Or if you want an array of uploads:&lt;br /&gt;
&lt;br /&gt;
webRequest(&amp;#039;upload/list&amp;#039;).then(response =&amp;gt; {&lt;br /&gt;
    // response.json.results&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== In the API ==&lt;br /&gt;
&lt;br /&gt;
As with other content types, either use injection or Services.Get to access the UploadService. From there, you can List/ Update and so on the upload you&amp;#039;re interested in.&lt;br /&gt;
&lt;br /&gt;
= File Consistency =&lt;br /&gt;
&lt;br /&gt;
When uploading images, SocialStack automatically produces resized versions of each image (along with optionally converting to WEBP format), dependent on the uploader configuration.  It is possible however that if configuration settings are subsequently changed, any new image sizes / formats will be unavailable for existing uploads.&lt;br /&gt;
&lt;br /&gt;
To address this, SocialStack provides an API endpoint (&amp;lt;code&amp;gt;/v1/upload/file-consistency&amp;lt;/code&amp;gt;) which can be called to ensure all requested image sizes / formats are available for all image uploads. Please note, the use of a local GPU is highly recommended, as this process can take a substantial amount of time.  Progress can be viewed via messages logged to the SocialStack API window.&lt;br /&gt;
&lt;br /&gt;
== Updating a specific range of images ==&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;/v1/upload/file-consistency?idRange=[from_id]-[to_id]&amp;lt;/code&amp;gt; (e.g. &amp;lt;code&amp;gt;/v1/upload/file-consistency?idRange=1000-1042&amp;lt;/code&amp;gt;) to restrict consistency checks for uploads only within the given ID range.&lt;br /&gt;
&lt;br /&gt;
== Forcing image regeneration ==&lt;br /&gt;
&lt;br /&gt;
By default, SocialStack will leave existing images untouched, simply creating new image sizes / formats only when missing. To force the regeneration of images regardless of whether or not they already exist, use &amp;lt;code&amp;gt;/v1/upload/file-consistency?regenBefore=[iso_date]&amp;lt;/code&amp;gt; (use &amp;lt;code&amp;gt;new Date().toISOString()&amp;lt;/code&amp;gt; to generate a current ISO date).&lt;br /&gt;
&lt;br /&gt;
This will ensure image sizes / formats are recreated, as long as they&amp;#039;re dated before the ISO date specified.&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Impersonation&amp;diff=419</id>
		<title>Impersonation</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Impersonation&amp;diff=419"/>
		<updated>2023-01-11T23:09:58Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you need to switch account, often to debug something, there are two useful endpoints on the API for doing just that. The functionality is only available to admin users and will also refuse any elevation attempts, such as attempting to impersonate a [[Permissions|developer account]] from a [[Permissions|regular admin one]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Starting impersonation =&lt;br /&gt;
&lt;br /&gt;
Send a get request to /v1/user/x/impersonate where x is the user&amp;#039;s ID. This means you can just navigate to it with your browser, or use webRequest like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import webRequest from &amp;#039;UI/Functions/WebRequest&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
function impersonate(userId){&lt;br /&gt;
 &lt;br /&gt;
    return webRequest(&amp;#039;user/&amp;#039; + userId + &amp;#039;/impersonate&amp;#039;).then(response =&amp;gt; {&lt;br /&gt;
        window.location = &amp;#039;/&amp;#039;;&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ending impersonation =&lt;br /&gt;
&lt;br /&gt;
Send a get request to /v1/user/unpersonate&lt;br /&gt;
&lt;br /&gt;
= Identifying if someone is impersonating =&lt;br /&gt;
&lt;br /&gt;
The frontend can identify if someone is currently impersonating via a session value called realUser:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
const { session, setSession } = useSession();&lt;br /&gt;
var { realUser, user } = session;&lt;br /&gt;
&lt;br /&gt;
// If realUser is set and different to user, they are impersonating&lt;br /&gt;
var isImpersonating = realUser &amp;amp;&amp;amp; (user.id != realUser.id);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=26</id>
		<title>Styling</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=26"/>
		<updated>2021-11-09T22:54:16Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: /* Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack uses SASS (https://sass-lang.com/guide). As this is a superset of CSS, any valid CSS can be used, but it&amp;#039;s worth taking the time to get to grips with SASS syntax and the built-in functions it provides, as these can both save time and improve the readability of your styles. Please note, SocialStack uses SCSS syntax rather than the old SASS indented syntax (see https://sass-lang.com/documentation/syntax).&lt;br /&gt;
&lt;br /&gt;
=== Filename conventions ===&lt;br /&gt;
&lt;br /&gt;
All SASS stylesheets within a SocialStack project are combined and included within the resulting site. Changing the order in which these files are combined (and thus potentially affecting the cascade, causing overlapping rules to be overridden or not) can be done by adding a value from 1-100 within the filename itself, e.g. &amp;lt;code&amp;gt;foobar.50.scss&amp;lt;/code&amp;gt; (SCSS files without a value default to a level of 100).&lt;br /&gt;
&lt;br /&gt;
Styles which include definitions which should be available to the entire project (e.g. SASS variables, mixins, etc) should be prefixed with &amp;quot;global.&amp;quot;, e.g. &amp;lt;code&amp;gt;global.variables.scss&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There&amp;#039;s no need to minify your styling as this is handled by the compiler.&lt;br /&gt;
&lt;br /&gt;
=== Theme styling ===&lt;br /&gt;
&lt;br /&gt;
[TODO] Styles can be defined at both the theme and component level - theme styles are global and available throughout the SocialStack site.&lt;br /&gt;
&lt;br /&gt;
=== Component styling ===&lt;br /&gt;
&lt;br /&gt;
Each SocialStack component includes optional styling - for instance, running &amp;lt;code&amp;gt;socialstack generate UI/FooBar&amp;lt;/code&amp;gt; in a SocialStack project folder will create both &amp;lt;code&amp;gt;UI/FooBar/FooBar.js&amp;lt;/code&amp;gt; for the component itself, along with &amp;lt;code&amp;gt;UI/FooBar/FooBar.scss&amp;lt;/code&amp;gt; - this can then be used to define component-specific styling.&lt;br /&gt;
&lt;br /&gt;
=== Responsive styling ===&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack should aim to be responsive and mobile-first (i.e., start with mobile-specific styling and layer other device / resolution overrides on top as necessary). As SocialStack uses the Bootstrap framework by default (https://getbootstrap.com/docs), we can utilise Bootstrap SASS mixins to target specific breakpoints. For instance, the following example will cause the component to show a green background for mobile devices, switching to red when viewed on anything 768px wide or above (defined by the Bootstrap medium or &amp;lt;code&amp;gt;md&amp;lt;/code&amp;gt; breakpoint):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;scss&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
.foobar {&lt;br /&gt;
  background: green;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@include media-breakpoint-up(md) {&lt;br /&gt;
  .foobar {&lt;br /&gt;
    background: red;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This resolves to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
.foobar {&lt;br /&gt;
  background: green;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (min-width: 768px) {&lt;br /&gt;
  .foobar {&lt;br /&gt;
    background: red;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please refer to https://getbootstrap.com/docs/5.1/layout/breakpoints/ for details on which other breakpoints are available.&lt;br /&gt;
&lt;br /&gt;
==== Note ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Defining multiple &amp;lt;code&amp;gt;@media&amp;lt;/code&amp;gt; queries in ascending order is highly recommended in order to avoid unexpected bugs where a &amp;quot;smaller&amp;quot; media query overrides a larger one.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Naming conventions ===&lt;br /&gt;
&lt;br /&gt;
Whilst not strictly enforced, the use of the BEM (Block Element Modifier) methodology (https://en.bem.info/methodology) when naming classes is strongly recommended:&lt;br /&gt;
&lt;br /&gt;
* Targetting styles to a class such as &amp;lt;code&amp;gt;foobar__header--secondary&amp;lt;/code&amp;gt; is way less brittle than using specific HTML elements (e.g. &amp;lt;code&amp;gt;h2&amp;lt;/code&amp;gt;), as changes during development inevitably result in changes to markup&lt;br /&gt;
&lt;br /&gt;
* Descriptive classes defined in this way are both more consistent and descriptive&lt;br /&gt;
&lt;br /&gt;
* Much more obvious which element(s) on the page will be affected&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Taking the following menu design as a guide:&lt;br /&gt;
&lt;br /&gt;
[[File:menu.png||Example design]]&lt;br /&gt;
&lt;br /&gt;
This could be defined with the following markup:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;nav className=&amp;quot;foobar&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul className=&amp;quot;menu&amp;quot;&amp;gt;&lt;br /&gt;
    {/* home */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* calendar */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link menu__link--active&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* video */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* chat */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/nav&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Corresponding styles could then be defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;scss&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
$menu_background: #000;&lt;br /&gt;
$menu_foreground: #fff;&lt;br /&gt;
$menu_foreground_inactive: rgba($menu_foreground, .5);&lt;br /&gt;
$menu_foreground_hover: rgba($menu_foreground, .75);&lt;br /&gt;
$menu_icon_size: 24px;&lt;br /&gt;
&lt;br /&gt;
.foobar {&lt;br /&gt;
  .menu {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
    background-color: $menu_background;&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__item {&lt;br /&gt;
      display: inline-block;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__link {&lt;br /&gt;
      display: flex;&lt;br /&gt;
      align-items: center;&lt;br /&gt;
      justify-content: center;&lt;br /&gt;
      padding: 0 25px;&lt;br /&gt;
      border-bottom: 4px solid transparent;&lt;br /&gt;
&lt;br /&gt;
      &amp;amp;:hover {&lt;br /&gt;
        border-bottom-color: $menu_foreground_hover;&lt;br /&gt;
&lt;br /&gt;
        .menu__icon {&lt;br /&gt;
          color: $menu_foreground_hover;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      &amp;amp;--active {&lt;br /&gt;
        border-bottom-color: $menu_foreground;&lt;br /&gt;
&lt;br /&gt;
        .menu__icon {&lt;br /&gt;
          color: $menu_foreground;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__icon {&lt;br /&gt;
      width: $menu_icon_size;&lt;br /&gt;
      height: $menu_icon_size;&lt;br /&gt;
      color: $menu_foreground_inactive;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Defining variables for values which are used in multiple instances (or which are likely to change) allows for easier editing&lt;br /&gt;
&lt;br /&gt;
* Wrapping all the rules within a parent &amp;lt;code&amp;gt;.foobar&amp;lt;/code&amp;gt; block ensures these styles will only affect elements parented by that class (namely, those within this component)&lt;br /&gt;
&lt;br /&gt;
* Use of &amp;lt;code&amp;gt;&amp;amp;__item&amp;lt;/code&amp;gt; style concatenation reduces repetitive typing of common elements in class names - in the above example, this would resolve to &amp;lt;code&amp;gt;.menu__item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Note that we&amp;#039;re not using &amp;lt;code&amp;gt;&amp;amp;__icon&amp;lt;/code&amp;gt; within the &amp;lt;code&amp;gt;&amp;amp;:hover&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;amp;--active&amp;lt;/code&amp;gt; blocks - this would result in &amp;lt;code&amp;gt;.menu__link--active__icon&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;.menu__link--active .menu__icon&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* While stock CSS doesn&amp;#039;t allow #RGB values to be used within &amp;lt;code&amp;gt;rgba()&amp;lt;/code&amp;gt;, SASS does - here we use &amp;lt;code&amp;gt;rgba($menu_foreground, .5)&amp;lt;/code&amp;gt; which resolves to &amp;lt;code&amp;gt;rgba(255, 255, 255, .5)&amp;lt;/code&amp;gt; in the resulting CSS&lt;br /&gt;
&lt;br /&gt;
* Note that nesting of rules is kept to a minimum - there&amp;#039;s no need to follow the markup structure religiously (e.g. &amp;lt;code&amp;gt;.menu .menu__item .menu__link&amp;lt;/code&amp;gt;), as the classnames are descriptive and unique enough&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=25</id>
		<title>Styling</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=25"/>
		<updated>2021-11-09T22:53:30Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack uses SASS (https://sass-lang.com/guide). As this is a superset of CSS, any valid CSS can be used, but it&amp;#039;s worth taking the time to get to grips with SASS syntax and the built-in functions it provides, as these can both save time and improve the readability of your styles. Please note, SocialStack uses SCSS syntax rather than the old SASS indented syntax (see https://sass-lang.com/documentation/syntax).&lt;br /&gt;
&lt;br /&gt;
=== Filename conventions ===&lt;br /&gt;
&lt;br /&gt;
All SASS stylesheets within a SocialStack project are combined and included within the resulting site. Changing the order in which these files are combined (and thus potentially affecting the cascade, causing overlapping rules to be overridden or not) can be done by adding a value from 1-100 within the filename itself, e.g. &amp;lt;code&amp;gt;foobar.50.scss&amp;lt;/code&amp;gt; (SCSS files without a value default to a level of 100).&lt;br /&gt;
&lt;br /&gt;
Styles which include definitions which should be available to the entire project (e.g. SASS variables, mixins, etc) should be prefixed with &amp;quot;global.&amp;quot;, e.g. &amp;lt;code&amp;gt;global.variables.scss&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There&amp;#039;s no need to minify your styling as this is handled by the compiler.&lt;br /&gt;
&lt;br /&gt;
=== Theme styling ===&lt;br /&gt;
&lt;br /&gt;
[TODO] Styles can be defined at both the theme and component level - theme styles are global and available throughout the SocialStack site.&lt;br /&gt;
&lt;br /&gt;
=== Component styling ===&lt;br /&gt;
&lt;br /&gt;
Each SocialStack component includes optional styling - for instance, running &amp;lt;code&amp;gt;socialstack generate UI/FooBar&amp;lt;/code&amp;gt; in a SocialStack project folder will create both &amp;lt;code&amp;gt;UI/FooBar/FooBar.js&amp;lt;/code&amp;gt; for the component itself, along with &amp;lt;code&amp;gt;UI/FooBar/FooBar.scss&amp;lt;/code&amp;gt; - this can then be used to define component-specific styling.&lt;br /&gt;
&lt;br /&gt;
=== Responsive styling ===&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack should aim to be responsive and mobile-first (i.e., start with mobile-specific styling and layer other device / resolution overrides on top as necessary). As SocialStack uses the Bootstrap framework by default (https://getbootstrap.com/docs), we can utilise Bootstrap SASS mixins to target specific breakpoints. For instance, the following example will cause the component to show a green background for mobile devices, switching to red when viewed on anything 768px wide or above (defined by the Bootstrap medium or &amp;lt;code&amp;gt;md&amp;lt;/code&amp;gt; breakpoint):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;scss&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
.foobar {&lt;br /&gt;
  background: green;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@include media-breakpoint-up(md) {&lt;br /&gt;
  .foobar {&lt;br /&gt;
    background: red;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This resolves to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
.foobar {&lt;br /&gt;
  background: green;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (min-width: 768px) {&lt;br /&gt;
  .foobar {&lt;br /&gt;
    background: red;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please refer to https://getbootstrap.com/docs/5.1/layout/breakpoints/ for details on which other breakpoints are available.&lt;br /&gt;
&lt;br /&gt;
==== Note ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Defining multiple &amp;lt;code&amp;gt;@media&amp;lt;/code&amp;gt; queries in ascending order is highly recommended in order to avoid unexpected bugs where a &amp;quot;smaller&amp;quot; media query overrides a larger one.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Naming conventions ===&lt;br /&gt;
&lt;br /&gt;
Whilst not strictly enforced, the use of the BEM (Block Element Modifier) methodology (https://en.bem.info/methodology) when naming classes is strongly recommended:&lt;br /&gt;
&lt;br /&gt;
* Targetting styles to a class such as &amp;lt;code&amp;gt;foobar__header--secondary&amp;lt;/code&amp;gt; is way less brittle than using specific HTML elements (e.g. &amp;lt;code&amp;gt;h2&amp;lt;/code&amp;gt;), as changes during development inevitably result in changes to markup&lt;br /&gt;
&lt;br /&gt;
* Descriptive classes defined in this way are both more consistent and descriptive&lt;br /&gt;
&lt;br /&gt;
* Much more obvious which element(s) on the page will be affected&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Taking the following menu design as a guide:&lt;br /&gt;
&lt;br /&gt;
[[File:menu.png||Example design]]&lt;br /&gt;
&lt;br /&gt;
This could be defined with the following markup:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nav className=&amp;quot;foobar&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul className=&amp;quot;menu&amp;quot;&amp;gt;&lt;br /&gt;
    {/* home */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* calendar */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link menu__link--active&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* video */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* chat */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/nav&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Corresponding styles could then be defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$menu_background: #000;&lt;br /&gt;
$menu_foreground: #fff;&lt;br /&gt;
$menu_foreground_inactive: rgba($menu_foreground, .5);&lt;br /&gt;
$menu_foreground_hover: rgba($menu_foreground, .75);&lt;br /&gt;
$menu_icon_size: 24px;&lt;br /&gt;
&lt;br /&gt;
.foobar {&lt;br /&gt;
  .menu {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
    background-color: $menu_background;&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__item {&lt;br /&gt;
      display: inline-block;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__link {&lt;br /&gt;
      display: flex;&lt;br /&gt;
      align-items: center;&lt;br /&gt;
      justify-content: center;&lt;br /&gt;
      padding: 0 25px;&lt;br /&gt;
      border-bottom: 4px solid transparent;&lt;br /&gt;
&lt;br /&gt;
      &amp;amp;:hover {&lt;br /&gt;
        border-bottom-color: $menu_foreground_hover;&lt;br /&gt;
&lt;br /&gt;
        .menu__icon {&lt;br /&gt;
          color: $menu_foreground_hover;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      &amp;amp;--active {&lt;br /&gt;
        border-bottom-color: $menu_foreground;&lt;br /&gt;
&lt;br /&gt;
        .menu__icon {&lt;br /&gt;
          color: $menu_foreground;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__icon {&lt;br /&gt;
      width: $menu_icon_size;&lt;br /&gt;
      height: $menu_icon_size;&lt;br /&gt;
      color: $menu_foreground_inactive;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Defining variables for values which are used in multiple instances (or which are likely to change) allows for easier editing&lt;br /&gt;
&lt;br /&gt;
* Wrapping all the rules within a parent &amp;lt;code&amp;gt;.foobar&amp;lt;/code&amp;gt; block ensures these styles will only affect elements parented by that class (namely, those within this component)&lt;br /&gt;
&lt;br /&gt;
* Use of &amp;lt;code&amp;gt;&amp;amp;__item&amp;lt;/code&amp;gt; style concatenation reduces repetitive typing of common elements in class names - in the above example, this would resolve to &amp;lt;code&amp;gt;.menu__item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Note that we&amp;#039;re not using &amp;lt;code&amp;gt;&amp;amp;__icon&amp;lt;/code&amp;gt; within the &amp;lt;code&amp;gt;&amp;amp;:hover&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;amp;--active&amp;lt;/code&amp;gt; blocks - this would result in &amp;lt;code&amp;gt;.menu__link--active__icon&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;.menu__link--active .menu__icon&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* While stock CSS doesn&amp;#039;t allow #RGB values to be used within &amp;lt;code&amp;gt;rgba()&amp;lt;/code&amp;gt;, SASS does - here we use &amp;lt;code&amp;gt;rgba($menu_foreground, .5)&amp;lt;/code&amp;gt; which resolves to &amp;lt;code&amp;gt;rgba(255, 255, 255, .5)&amp;lt;/code&amp;gt; in the resulting CSS&lt;br /&gt;
&lt;br /&gt;
* Note that nesting of rules is kept to a minimum - there&amp;#039;s no need to follow the markup structure religiously (e.g. &amp;lt;code&amp;gt;.menu .menu__item .menu__link&amp;lt;/code&amp;gt;), as the classnames are descriptive and unique enough&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=24</id>
		<title>Styling</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=24"/>
		<updated>2021-11-09T22:26:42Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: Introduction to styling in SocialStack&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack uses SASS (https://sass-lang.com/guide). As this is a superset of CSS, any valid CSS can be used, but it&amp;#039;s worth taking the time to get to grips with SASS syntax and the built-in functions it provides, as these can both save time and improve the readability of your styles. Please note, SocialStack uses SCSS syntax rather than the old SASS indented syntax (see https://sass-lang.com/documentation/syntax).&lt;br /&gt;
&lt;br /&gt;
=== Filename conventions ===&lt;br /&gt;
&lt;br /&gt;
All SASS stylesheets within a SocialStack project are combined and included within the resulting site. Changing the order in which these files are combined (and thus potentially affecting the cascade, causing overlapping rules to be overridden or not) can be done by adding a value from 1-100 within the filename itself, e.g. &amp;lt;code&amp;gt;foobar.50.scss&amp;lt;/code&amp;gt; (SCSS files without a value default to a level of 100).&lt;br /&gt;
&lt;br /&gt;
Styles which include definitions which should be available to the entire project (e.g. SASS variables, mixins, etc) should be prefixed with &amp;quot;global.&amp;quot;, e.g. &amp;lt;code&amp;gt;global.variables.scss&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There&amp;#039;s no need to minify your styling as this is handled by the compiler.&lt;br /&gt;
&lt;br /&gt;
=== Theme styling ===&lt;br /&gt;
&lt;br /&gt;
[TODO] Styles can be defined at both the theme and component level - theme styles are global and available throughout the SocialStack site.&lt;br /&gt;
&lt;br /&gt;
=== Component styling ===&lt;br /&gt;
&lt;br /&gt;
Each SocialStack component includes optional styling - for instance, running &amp;lt;code&amp;gt;socialstack generate UI/FooBar&amp;lt;/code&amp;gt; in a SocialStack project folder will create both &amp;lt;code&amp;gt;UI/FooBar/FooBar.js&amp;lt;/code&amp;gt; for the component itself, along with &amp;lt;code&amp;gt;UI/FooBar/FooBar.scss&amp;lt;/code&amp;gt; - this can then be used to define component-specific styling.&lt;br /&gt;
&lt;br /&gt;
=== Responsive styling ===&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack should aim to be responsive and mobile-first (i.e., start with mobile-specific styling and layer other device / resolution overrides on top as necessary). As SocialStack uses the Bootstrap framework by default (https://getbootstrap.com/docs), we can utilise Bootstrap SASS mixins to target specific breakpoints. For instance, the following example will cause the component to show a green background for mobile devices, switching to red when viewed on anything 768px wide or above (defined by the Bootstrap medium or &amp;lt;code&amp;gt;md&amp;lt;/code&amp;gt; breakpoint):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.foobar {&lt;br /&gt;
  background: green;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@include media-breakpoint-up(md) {&lt;br /&gt;
  .foobar {&lt;br /&gt;
    background: red;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This resolves to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.foobar {&lt;br /&gt;
  background: green;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (min-width: 768px) {&lt;br /&gt;
  .foobar {&lt;br /&gt;
    background: red;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please refer to https://getbootstrap.com/docs/5.1/layout/breakpoints/ for details on which other breakpoints are available.&lt;br /&gt;
&lt;br /&gt;
==== Note ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Defining multiple &amp;lt;code&amp;gt;@media&amp;lt;/code&amp;gt; queries in ascending order is highly recommended in order to avoid unexpected bugs where a &amp;quot;smaller&amp;quot; media query overrides a larger one.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Naming conventions ===&lt;br /&gt;
&lt;br /&gt;
Whilst not strictly enforced, the use of the BEM (Block Element Modifier) methodology (https://en.bem.info/methodology) when naming classes is strongly recommended:&lt;br /&gt;
&lt;br /&gt;
* Targetting styles to a class such as &amp;lt;code&amp;gt;foobar__header--secondary&amp;lt;/code&amp;gt; is way less brittle than using specific HTML elements (e.g. &amp;lt;code&amp;gt;h2&amp;lt;/code&amp;gt;), as changes during development inevitably result in changes to markup&lt;br /&gt;
&lt;br /&gt;
* Descriptive classes defined in this way are both more consistent and descriptive&lt;br /&gt;
&lt;br /&gt;
* Much more obvious which element(s) on the page will be affected&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Taking the following menu design as a guide:&lt;br /&gt;
&lt;br /&gt;
[[File:menu.png||Example design]]&lt;br /&gt;
&lt;br /&gt;
This could be defined with the following markup:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nav className=&amp;quot;foobar&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;ul className=&amp;quot;menu&amp;quot;&amp;gt;&lt;br /&gt;
    {/* home */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* calendar */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link menu__link--active&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* video */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {/* chat */}&lt;br /&gt;
    &amp;lt;li className=&amp;quot;menu__item&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;#&amp;quot; className=&amp;quot;menu__link&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;svg className=&amp;quot;menu__icon&amp;quot; ... /&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/nav&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Corresponding styles could then be defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$menu_background: #000;&lt;br /&gt;
$menu_foreground: #fff;&lt;br /&gt;
$menu_foreground_inactive: rgba($menu_foreground, .5);&lt;br /&gt;
$menu_foreground_hover: rgba($menu_foreground, .75);&lt;br /&gt;
$menu_icon_size: 24px;&lt;br /&gt;
&lt;br /&gt;
.foobar {&lt;br /&gt;
  .menu {&lt;br /&gt;
    list-style: none;&lt;br /&gt;
    padding: 0;&lt;br /&gt;
    background-color: $menu_background;&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__item {&lt;br /&gt;
      display: inline-block;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__link {&lt;br /&gt;
      display: flex;&lt;br /&gt;
      align-items: center;&lt;br /&gt;
      justify-content: center;&lt;br /&gt;
      padding: 0 25px;&lt;br /&gt;
      border-bottom: 4px solid transparent;&lt;br /&gt;
&lt;br /&gt;
      &amp;amp;:hover {&lt;br /&gt;
        border-bottom-color: $menu_foreground_hover;&lt;br /&gt;
&lt;br /&gt;
        .menu__icon {&lt;br /&gt;
          color: $menu_foreground_hover;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      &amp;amp;--active {&lt;br /&gt;
        border-bottom-color: $menu_foreground;&lt;br /&gt;
&lt;br /&gt;
        .menu__icon {&lt;br /&gt;
          color: $menu_foreground;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;__icon {&lt;br /&gt;
      width: $menu_icon_size;&lt;br /&gt;
      height: $menu_icon_size;&lt;br /&gt;
      color: $menu_foreground_inactive;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Defining variables for values which are used in multiple instances (or which are likely to change) allows for easier editing&lt;br /&gt;
&lt;br /&gt;
* Wrapping all the rules within a parent &amp;lt;code&amp;gt;.foobar&amp;lt;/code&amp;gt; block ensures these styles will only affect elements parented by that class (namely, those within this component)&lt;br /&gt;
&lt;br /&gt;
* Use of &amp;lt;code&amp;gt;&amp;amp;__item&amp;lt;/code&amp;gt; style concatenation reduces repetitive typing of common elements in class names - in the above example, this would resolve to &amp;lt;code&amp;gt;.menu__item&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Note that we&amp;#039;re not using &amp;lt;code&amp;gt;&amp;amp;__icon&amp;lt;/code&amp;gt; within the &amp;lt;code&amp;gt;&amp;amp;:hover&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;amp;--active&amp;lt;/code&amp;gt; blocks - this would result in &amp;lt;code&amp;gt;.menu__link--active__icon&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;.menu__link--active .menu__icon&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* While stock CSS doesn&amp;#039;t allow #RGB values to be used within &amp;lt;code&amp;gt;rgba()&amp;lt;/code&amp;gt;, SASS does - here we use &amp;lt;code&amp;gt;rgba($menu_foreground, .5)&amp;lt;/code&amp;gt; which resolves to &amp;lt;code&amp;gt;rgba(255, 255, 255, .5)&amp;lt;/code&amp;gt; in the resulting CSS&lt;br /&gt;
&lt;br /&gt;
* Note that nesting of rules is kept to a minimum - there&amp;#039;s no need to follow the markup structure religiously (e.g. &amp;lt;code&amp;gt;.menu .menu__item .menu__link&amp;lt;/code&amp;gt;), as the classnames are descriptive and unique enough&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=23</id>
		<title>Styling</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=Styling&amp;diff=23"/>
		<updated>2021-11-09T21:45:15Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: Created page with &amp;quot;Introduction  All styling within SocialStack uses SASS (https://sass-lang.com/guide). As this is a superset of CSS, any valid CSS can be used, but it&amp;#039;s worth taking the time t...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Introduction&lt;br /&gt;
&lt;br /&gt;
All styling within SocialStack uses SASS (https://sass-lang.com/guide). As this is a superset of CSS, any valid CSS can be used, but it&amp;#039;s worth taking the time to get to grips with SASS syntax and the built-in functions it provides, as these can both save time and improve the readability of your styles. Please note, SocialStack uses SCSS syntax rather than the old SASS indented syntax (see https://sass-lang.com/documentation/syntax).&lt;br /&gt;
&lt;br /&gt;
Filename conventions&lt;br /&gt;
&lt;br /&gt;
All SASS stylesheets within a SocialStack project are combined and included within the resulting site. Changing the order in which these files are combined (and thus potentially affecting the cascade, causing overlapping rules to be overridden or not) can be done by adding a value from 1-100 within the filename itself, e.g. foobar.50.scss (SCSS files without a value default to a level of 100).&lt;br /&gt;
&lt;br /&gt;
Styles which include definitions which should be available to the entire project (e.g. SASS variables, mixins, etc) should be prefixed with &amp;quot;global.&amp;quot;, e.g. global.variables.scss.&lt;br /&gt;
&lt;br /&gt;
There&amp;#039;s no need to minify your styling as this is handled by the compiler.&lt;br /&gt;
&lt;br /&gt;
Theme styling&lt;br /&gt;
&lt;br /&gt;
[TODO] Styles can be defined at both the theme and component level - theme styles are global and available throughout the SocialStack site.&lt;br /&gt;
&lt;br /&gt;
Component styling&lt;br /&gt;
&lt;br /&gt;
Each SocialStack component includes optional styling - for instance, running socialstack generate UI/FooBar in a SocialStack project folder will create both UI/FooBar/FooBar.js for the component itself, along with UI/FooBar/FooBar.scss - this can then be used to define component-specific styling.&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=File:Menu.png&amp;diff=22</id>
		<title>File:Menu.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=File:Menu.png&amp;diff=22"/>
		<updated>2021-11-09T21:00:03Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example menu design&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=File:Info.png&amp;diff=9</id>
		<title>File:Info.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=File:Info.png&amp;diff=9"/>
		<updated>2021-11-09T15:11:20Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Information icon&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
	<entry>
		<id>https://wiki.socialstack.dev/index.php?title=File:Warning.png&amp;diff=8</id>
		<title>File:Warning.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.socialstack.dev/index.php?title=File:Warning.png&amp;diff=8"/>
		<updated>2021-11-09T15:10:49Z</updated>

		<summary type="html">&lt;p&gt;Ablewhite: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;warning icon&lt;/div&gt;</summary>
		<author><name>Ablewhite</name></author>
	</entry>
</feed>