DEV: makes discourse-styleguide core (styleguide) (#10847)

This plugin is only useful for developers, however, making it core allows us to centralize any component modification in one commit.

This integration also adds a new site_setting: `styleguide_admin_only` which allows to enable a styleguide on a live site while restricting visibility to admins only.

By default, styleguide is disabled.
This commit is contained in:
Joffrey JAFFEUX
2020-10-07 14:48:38 +02:00
committed by GitHub
parent 9c0892c47c
commit 82031aaf16
71 changed files with 1921 additions and 1 deletions
+1
View File
@@ -53,6 +53,7 @@ bootsnap-compile-cache/
!/plugins/discourse-nginx-performance-report
!/plugins/discourse-narrative-bot
!/plugins/discourse-presence
!/plugins/styleguide
!/plugins/discourse-local-dates
/plugins/*/auto_generated/
+1 -1
View File
@@ -63,7 +63,7 @@ class Plugin::Metadata
"discourse-solved",
"discourse-spoiler-alert",
"discourse-user-notes",
"discourse-styleguide",
"styleguide",
"discourse-tooltips",
"discourse-translator",
"discourse-user-card-badges",
+6
View File
@@ -0,0 +1,6 @@
# styleguide
Adds a URL of `/styleguide` to discourse that renders widgets in various
configurations to aid in styling.
![Screenshot](screenshot.png)
@@ -0,0 +1,14 @@
# frozen_string_literal: true
module Styleguide
class StyleguideController < ApplicationController
requires_plugin Styleguide::PLUGIN_NAME
skip_before_action :check_xhr
def index
ensure_admin if SiteSetting.styleguide_admin_only
render 'default/empty'
end
end
end
@@ -0,0 +1,4 @@
export default Ember.Component.extend({
tagName: "section",
classNameBindings: [":color-example"],
});
@@ -0,0 +1,4 @@
export default Ember.Component.extend({
tagName: "section",
classNames: ["styleguide-example"],
});
@@ -0,0 +1,21 @@
import { later } from "@ember/runloop";
export default Ember.Component.extend({
tagName: "section",
classNames: ["styleguide-icons"],
iconIDs: [],
didInsertElement() {
this._super(...arguments);
later(() => {
let IDs = $("#svg-sprites symbol")
.map(function () {
return this.id;
})
.get();
this.set("iconIDs", IDs);
}, 2000);
},
});
@@ -0,0 +1,3 @@
export default Ember.Component.extend({
tagName: "",
});
@@ -0,0 +1,10 @@
import { cookAsync } from "discourse/lib/text";
export default Ember.Component.extend({
didInsertElement() {
this._super(...arguments);
const contents = $(this.element).html();
cookAsync(contents).then((cooked) => $(this.element).html(cooked.string));
},
});
@@ -0,0 +1,18 @@
import computed from "discourse-common/utils/decorators";
export default Ember.Component.extend({
tagName: "section",
classNameBindings: [":styleguide-section", "sectionClass"],
didReceiveAttrs() {
this._super(...arguments);
window.scrollTo(0, 0);
},
@computed("section")
sectionClass(section) {
if (section) {
return `${section.id}-examples`;
}
},
});
@@ -0,0 +1,5 @@
export default Ember.Controller.extend({
actions: {
dummy() {},
},
});
@@ -0,0 +1,3 @@
export default Ember.Controller.extend({
sections: null,
});
@@ -0,0 +1,5 @@
import I18n from "I18n";
export default Ember.Helper.helper(function (params) {
return I18n.t(`styleguide.sections.${params[0].replace(/\-/g, "_")}.title`);
});
@@ -0,0 +1,269 @@
import NavItem from "discourse/models/nav-item";
let topicId = 2000000;
let userId = 1000000;
let _data;
export function createData(store) {
if (_data) {
return _data;
}
let categories = [
{
id: 1234,
name: "Fruit",
description_excerpt: "All about various kinds of fruit",
color: "ff0",
slug: "fruit",
},
{
id: 2345,
name: "Vegetables",
description_excerpt: "Full of delicious vitamins",
color: "f00",
slug: "vegetables",
},
{
id: 3456,
name: "Beverages",
description_excerpt: "Thirsty?",
color: "99f",
slug: "beverages",
read_restricted: true,
},
].map((c) => store.createRecord("category", c));
let createUser = (attrs) => {
userId++;
let userData = {
id: userId,
username: `user_${userId}`,
name: "John Doe",
avatar_template: "/images/avatar.png",
website: "discourse.com",
website_name: "My Website is Discourse",
location: "Toronto",
suspend_reason: "Some reason",
displayGroups: [{ name: "Group 1" }, { name: "Group 2" }],
created_at: moment().subtract(10, "days"),
last_posted_at: moment().subtract(3, "days"),
last_seen_at: moment().subtract(1, "days"),
profile_view_count: 378,
invited_by: {
username: "user_2",
},
trustLevel: { name: "Dummy" },
publicUserFields: [
{
field: {
dasherized_name: "puf_1",
name: "Public User Field 1",
},
value: "Some value 1",
},
{
field: {
dasherized_name: "puf_2",
name: "Public User Field 2",
},
value: "Some value 2",
},
],
};
Object.assign(userData, attrs || {});
return store.createRecord("user", userData);
};
// This bg image is public domain: http://hubblesite.org/image/3999/gallery
let user = createUser({
profile_background: "/plugins/styleguide/images/hubble-orion-nebula-bg.jpg",
has_profile_background: true,
});
let createTopic = (attrs) => {
topicId++;
return store.createRecord(
"topic",
$.extend(
{
id: topicId,
title: `Example Topic Title ${topicId}`,
fancyTitle: `Example Topic Title ${topicId}`,
slug: `example-topic-title-${topicId}`,
posts_count: ((topicId * 1234) % 100) + 1,
views: ((topicId * 123) % 1000) + 1,
like_count: topicId % 3,
created_at: `2017-03-${topicId}`,
invisible: false,
posters: [
{ extras: "latest", user },
{ user: createUser() },
{ user: createUser() },
{ user: createUser() },
{ user: createUser() },
],
},
attrs || {}
)
);
};
let topic = createTopic();
topic.set("category", categories[0]);
topic.get("details").setProperties({
can_create_post: true,
suggested_topics: [topic, topic, topic],
});
let invisibleTopic = createTopic({ invisible: true });
let closedTopic = createTopic({ closed: true });
closedTopic.set("category", categories[1]);
let archivedTopic = createTopic({ archived: true });
let pinnedTopic = createTopic({ pinned: true });
pinnedTopic.set("clearPin", () => pinnedTopic.set("pinned", "unpinned"));
pinnedTopic.set("rePin", () => pinnedTopic.set("pinned", "pinned"));
pinnedTopic.set("category", categories[2]);
let unpinnedTopic = createTopic({ unpinned: true });
let warningTopic = createTopic({ is_warning: true });
const bunchOfTopics = [
topic,
invisibleTopic,
closedTopic,
archivedTopic,
pinnedTopic,
unpinnedTopic,
warningTopic,
];
let sentence =
"Donec viverra lacus id sapien aliquam, tempus tincidunt urna porttitor.";
let cooked = `<p>Lorem ipsum dolor sit amet, et nec quis viderer prompta, ex omnium ponderum insolens eos, sed discere invenire principes in. Fuisset constituto per ad. Est no scripta propriae facilisis, viderer impedit deserunt in mel. Quot debet facilisis ne vix, nam in detracto tacimates. At quidam petentium vulputate pro. Alia iudico repudiandae ad vel, erat omnis epicuri eos id. Et illum dolor graeci vel, quo feugiat consulatu ei.</p>
<p>Case everti equidem ius ea, ubique veritus vim id. Eros omnium conclusionemque qui te, usu error alienum imperdiet ut, ex ius meis adipisci. Libris reprehendunt eos ex, mea at nisl suavitate. Altera virtute democritum pro cu, melius latine in ius.</p>`;
let transformedPost = {
id: 1234,
cooked,
created_at: moment().subtract(3, "days"),
user_id: user.get("id"),
username: user.get("username"),
avatar_template: user.get("avatar_template"),
showLike: true,
canToggleLike: true,
canFlag: true,
canEdit: false,
canCreatePost: true,
canBookmark: true,
canManage: true,
canDelete: true,
createdByUsername: user.get("username"),
createdByAvatarTemplate: user.get("avatar_template"),
lastPostUsername: user.get("username"),
lastPostAvatarTemplate: user.get("avatar_template"),
topicReplyCount: 123,
topicViews: 3456,
participantCount: 10,
topicLikeCount: 14,
topicLinkLength: 5,
topicPostsCount: 4,
participants: [createUser(), createUser(), createUser(), createUser()],
topicLinks: [
{
title: "Evil Trout",
url: "https://eviltrout.com",
domain: "eviltrout.com",
clicks: 1024,
},
{
title: "Cool Site",
url: "http://coolsite.example.com",
domain: "coolsite.example.com",
clicks: 512,
},
],
};
_data = {
options: [
{ id: 1, name: "Orange" },
{ id: 2, name: "Blue" },
{ id: 3, name: "Red" },
{ id: 4, name: "Yellow" },
],
categories,
buttonSizes: [
{ class: "btn-large", text: "large" },
{ class: "btn-default", text: "default" },
],
buttonStates: [
{ class: "btn-hover", text: "hover" },
{ class: "btn-active", text: "active" },
{ disabled: true, text: "disabled" },
],
navItems: ["latest", "categories", "top"].map((name) => {
let item = NavItem.fromText(name);
item.set("href", "#");
if (name === "categories") {
item.set("styleGuideActive", true);
}
return item;
}),
topic,
invisibleTopic,
closedTopic,
archivedTopic,
pinnedTopic,
unpinnedTopic,
warningTopic,
topics: bunchOfTopics,
sentence,
short_sentence: "Lorem ipsum dolor sit amet.",
soon: moment().add(2, "days"),
transformedPost,
user,
userWithUnread: createUser({
unread_notifications: 3,
unread_private_messages: 7,
}),
lorem: cooked,
topicTimerUpdateDate: "2017-10-18 18:00",
categoryNames: categories.map((c) => c.name),
groups: [
{ name: "staff", id: 1, automatic: false },
{ name: "lounge", id: 2, automatic: true },
{ name: "admin", id: 3, automatic: false },
],
selectedGroups: [1, 2],
settings: "bold|italic|strike|underline",
colors: "f49|c89|564897",
};
return _data;
}
@@ -0,0 +1,72 @@
let _allCategories = null;
let _sectionsById = {};
let _notes = {};
export const CATEGORIES = ["atoms", "molecules", "organisms"];
export function sectionById(id) {
// prime cache
allCategories();
return _sectionsById[id];
}
function sortSections(a, b) {
let result = a.priority - b.priority;
if (result === 0) {
return a.id < b.id ? -1 : 1;
}
return result;
}
export function allCategories() {
if (_allCategories) {
return _allCategories;
}
let categories = {};
let paths = CATEGORIES.join("|");
// Find a list of sections based on what templates are available
Object.keys(Ember.TEMPLATES).forEach((e) => {
let regexp = new RegExp(`styleguide\/(${paths})\/(\\d+)?\\-?([^\\/]+)$`);
let matches = e.match(regexp);
if (matches) {
let section = {
id: matches[3],
priority: parseInt(matches[2] || "100", 10),
category: matches[1],
templateName: e.replace(/^.*styleguide\//, ""),
};
if (!categories[section.category]) {
categories[section.category] = [];
}
categories[section.category].push(section);
_sectionsById[section.id] = section;
}
// Look for notes
regexp = new RegExp(`components\/notes\/(\\d+)?\\-?([^\\/]+)$`);
matches = e.match(regexp);
if (matches) {
_notes[matches[2]] = e.replace(/^.*notes\//, "");
}
});
_allCategories = [];
CATEGORIES.forEach((c) => {
let sections = categories[c];
if (sections) {
_allCategories.push({
id: c,
sections: sections.sort(sortSections),
});
}
});
return _allCategories;
}
export function findNote(section) {
return _notes[section.id];
}
@@ -0,0 +1,28 @@
import {
sectionById,
findNote,
} from "discourse/plugins/styleguide/discourse/lib/styleguide";
import { createData } from "discourse/plugins/styleguide/discourse/lib/dummy-data";
export default Ember.Route.extend({
model(params) {
return sectionById(params.section);
},
setupController(controller, section) {
let note = findNote(section);
controller.setProperties({
section,
note,
dummy: createData(this.store),
});
},
renderTemplate(controller, section) {
this.render("styleguide.show");
this.render(`styleguide/${section.templateName}`, {
into: "styleguide.show",
});
},
});
@@ -0,0 +1,11 @@
import { allCategories } from "discourse/plugins/styleguide/discourse/lib/styleguide";
export default Ember.Route.extend({
model() {
return allCategories();
},
setupController(controller, categories) {
controller.set("categories", categories);
},
});
@@ -0,0 +1,11 @@
export default function () {
const { disabled_plugins = [] } = this.site;
if (disabled_plugins.indexOf("styleguide") !== -1) {
return;
}
this.route("styleguide", function () {
this.route("show", { path: ":category/:section" });
});
}
@@ -0,0 +1,2 @@
<div class="color-bg {{color}}"></div>
<div class="color-name">${{color}}</div>
@@ -0,0 +1,3 @@
<div class="example-title">{{title}}</div>
<section class="rendered">{{yield}}</section>
<div class="clearfix"></div>
@@ -0,0 +1,6 @@
{{#each iconIDs as |id|}}
<div class="styleguide-icon">
{{ d-icon id }}
<span>{{id}}</span>
</div>
{{/each}}
@@ -0,0 +1,3 @@
{{#link-to "styleguide.show" section.category section.id}}
{{section-title section.id}}
{{/link-to}}
@@ -0,0 +1,11 @@
<h1 class="section-title">
{{#if section}}
{{section-title section.id}}
{{else}}
{{i18n title}}
{{/if}}
</h1>
<div class="styleguide-section-contents">
{{yield}}
</div>
@@ -0,0 +1,15 @@
<section class="styleguide">
<section class="styleguide-menu">
{{#each categories as |c|}}
<ul>
<li class="styleguide-heading">{{i18n (concat "styleguide.categories." c.id)}}</li>
{{#each c.sections as |s|}}
<li>{{styleguide-link section=s}}</li>
{{/each}}
</ul>
{{/each}}
</section>
<section class="styleguide-contents">
{{outlet}}
</section>
</section>
@@ -0,0 +1,27 @@
{{#styleguide-example title="h1"}}
<h1>{{i18n "styleguide.sections.typography.example"}}</h1>
{{/styleguide-example}}
{{#styleguide-example title="h2"}}
<h2>{{i18n "styleguide.sections.typography.example"}}</h2>
{{/styleguide-example}}
{{#styleguide-example title="h3"}}
<h3>{{i18n "styleguide.sections.typography.example"}}</h3>
{{/styleguide-example}}
{{#styleguide-example title="h4"}}
<h4>{{i18n "styleguide.sections.typography.example"}}</h4>
{{/styleguide-example}}
{{#styleguide-example title="h5"}}
<h5>{{i18n "styleguide.sections.typography.example"}}</h5>
{{/styleguide-example}}
{{#styleguide-example title="h6"}}
<h6>{{i18n "styleguide.sections.typography.example"}}</h6>
{{/styleguide-example}}
{{#styleguide-example title="p"}}
<p>{{i18n "styleguide.sections.typography.paragraph"}}</p>
{{/styleguide-example}}
@@ -0,0 +1,99 @@
<div class="section-description">
<p>
Discourse users can select from 4 different text sizes in their user settings, by default these are:
<pre>
Smaller: 14px
Normal: 15px <span>(default)</span>
Larger: 17px
Largest: 19px
</pre>
</p>
<p>
If you'd like to increase the font size of your entire Discourse community, you can override the font-size of the HTML element. You can also provide different font sizes for the user text size settings defined above. The example below increases all text size options by 1px.
<pre>
html {
<span class="hljs-attribute">font-size</span>: 16px; <span>// default font-size </span>
&.text-size-smaller {
<span class="hljs-attribute">font-size</span>: 15px;
}
&.text-size-larger {
<span class="hljs-attribute">font-size</span>: 18px;
}
&.text-size-largest {
<span class="hljs-attribute">font-size</span>: 20px;
}
}
</pre>
</p>
<p>
If you want to scale the fonts of a specific element, you can use Discourse's font scaling variables. Using the variable system ensures you're using a consistent set of font-sizes throughout your community.
<p>
Changing the font-size of a parent element will proportionately scale the font sizes of all its children.
</p>
<pre>
.parent {
<span class="hljs-attribute">font-size</span>: $font-up-3;
<span>// Increases the relative font-size of this element and its children by 3 steps in the scale</span>
.child {
<span>// If this is set to $font-down-3 in Discourse's default CSS,
the parent font-size increase above would make this equivilant to $font-0
($font-down-3 + $font-up-3 = $font-0)</span>
}
}
</pre>
</p>
</div>
{{#styleguide-example title="$font-up-6, 2.296em"}}
<p class="font-up-6">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-up-5, 2em"}}
<p class="font-up-5">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-up-4, 1.7511em"}}
<p class="font-up-4">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-up-3, 1.5157em"}}
<p class="font-up-3">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-up-2, 1.3195em"}}
<p class="font-up-2">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-up-1, 1.1487em"}}
<p class="font-up-1">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-0, 1em — base font"}}
<p class="font-0">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-down-1, 0.8706em"}}
<p class="font-down-1">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-down-2, 0.7579em"}}
<p class="font-down-2">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-down-3, 0.6599em"}}
<p class="font-down-3">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-down-4, 0.5745em"}}
<p class="font-down-4">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-down-5, 0.5em"}}
<p class="font-down-5">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
{{#styleguide-example title="$font-down-6, 0.4355em"}}
<p class="font-down-6">{{i18n "styleguide.sections.typography.example"}}</p>
{{/styleguide-example}}
@@ -0,0 +1,91 @@
{{#styleguide-example title=".btn-icon - sizes"}}
{{#each dummy.buttonSizes as |bs|}}
{{d-button icon="times" translatedTitle=bs.text class=bs.class disabled=bs.disabled}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-icon - states"}}
{{#each dummy.buttonStates as |bs|}}
{{d-button icon="times" translatedTitle=bs.text class=bs.class disabled=bs.disabled}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-text - sizes"}}
{{#each dummy.buttonSizes as |bs|}}
{{d-button translatedLabel=bs.text class=bs.class disabled=bs.disabled}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-text - states"}}
{{#each dummy.buttonStates as |bs|}}
{{d-button translatedLabel=bs.text class=bs.class disabled=bs.disabled}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-default .btn-icon-text - sizes"}}
{{#each dummy.buttonSizes as |bs|}}
{{d-button icon="plus" translatedLabel=bs.text class=bs.class disabled=bs.disabled}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-default .btn-icon-text - states"}}
{{#each dummy.buttonStates as |bs|}}
{{d-button icon="plus" translatedLabel=bs.text class=bs.class disabled=bs.disabled}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-primary .btn-icon-text"}}
{{#each dummy.buttonSizes as |bs|}}
{{d-button
class=(concat "btn-primary " bs.class)
icon="plus"
translatedLabel=bs.text
disabled=bs.disabled
}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-primary .btn-icon-text - states"}}
{{#each dummy.buttonStates as |bs|}}
{{d-button
class=(concat "btn-primary " bs.class)
icon="plus"
translatedLabel=bs.text
disabled=bs.disabled
}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-danger .btn-icon-text - sizes"}}
{{#each dummy.buttonSizes as |bs|}}
{{d-button
class=(concat "btn-danger " bs.class)
icon="trash-alt"
translatedLabel=bs.text
disabled=bs.disabled
}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-danger .btn-icon-text - states"}}
{{#each dummy.buttonStates as |bs|}}
{{d-button
class=(concat "btn-danger " bs.class)
icon="trash-alt"
translatedLabel=bs.text
disabled=bs.disabled
}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-flat - sizes"}}
{{#each dummy.buttonSizes as |bs|}}
{{flat-button icon="trash-alt" disabled=bs.disabled transaltedTitle=bs.title}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title=".btn-flat - states"}}
{{#each dummy.buttonStates as |bs|}}
{{flat-button icon="trash-alt" disabled=bs.disabled transaltedTitle=bs.title}}
{{/each}}
{{/styleguide-example}}
@@ -0,0 +1,70 @@
{{#styleguide-example title="$primary"}}
<section class="color-row">
{{color-example color="primary-very-low"}}
{{color-example color="primary-low"}}
{{color-example color="primary-low-mid"}}
</section>
<section class="color-row">
{{color-example color="primary-medium"}}
{{color-example color="primary-high"}}
{{color-example color="primary"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$secondary"}}
<section class="color-row">
{{color-example color="secondary-low"}}
{{color-example color="secondary-medium"}}
{{color-example color="secondary-high"}}
{{color-example color="secondary"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$tertiary"}}
<section class="color-row">
{{color-example color="tertiary-low"}}
{{color-example color="tertiary-medium"}}
{{color-example color="tertiary-high"}}
{{color-example color="tertiary"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$quaternary"}}
<section class="color-row">
{{color-example color="quaternary-low"}}
{{color-example color="quaternary"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$highlight"}}
<section class="color-row">
{{color-example color="highlight-low"}}
{{color-example color="highlight-medium"}}
{{color-example color="highlight"}}
{{color-example color="highlight-high"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$danger"}}
<section class="color-row">
{{color-example color="danger-low"}}
{{color-example color="danger-low-mid"}}
{{color-example color="danger-medium"}}
{{color-example color="danger"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$success"}}
<section class="color-row">
{{color-example color="success-low"}}
{{color-example color="success-medium"}}
{{color-example color="success"}}
</section>
{{/styleguide-example}}
{{#styleguide-example title="$love"}}
<section class="color-row">
{{color-example color="love-low"}}
{{color-example color="love"}}
</section>
{{/styleguide-example}}
@@ -0,0 +1,15 @@
<div class="section-description">
<p>Discourse uses a free set of SVG icons from Font Awesome (<a href="https://fontawesome.com/icons?d=gallery&m=free">{{i18n "styleguide.sections.icons.full_list"}}</a>).</p>
<p>Plugins and themes can add SVG icons to the SVG spritesheet, or replace existing icons entirely.</p>
<p>
<ul>
<li><a href="https://meta.discourse.org/t/introducing-font-awesome-5-and-svg-icons/101643">How to use SVG icons in your plugin or theme</a></li>
<li><a href="https://meta.discourse.org/t/replace-discourses-default-svg-icons-with-custom-icons-in-a-theme/115736/1">How to replace Discourse's default icons in a theme</a></li>
</ul>
</p>
<p>By default, all icons have the <pre class="pre-inline">.d-icon</pre> class applied along with a class containing the name of the icon (e.g., <pre class="pre-inline">.d-icon-link</pre>)</p>
</div>
{{#styleguide-example title="d-icon - all available icons"}}
{{styleguide-icons}}
{{/styleguide-example}}
@@ -0,0 +1,15 @@
{{#styleguide-example title="text-field"}}
{{text-field placeholder="Placeholder"}}
{{/styleguide-example}}
{{#styleguide-example title="password"}}
{{password-field type="password" placeholder="Placeholder"}}
{{/styleguide-example}}
{{#styleguide-example title="text-field search"}}
{{text-field type="search" placeholder="Placeholder"}}
{{/styleguide-example}}
{{#styleguide-example title="textarea"}}
{{textarea placeholder="Placeholder"}}
{{/styleguide-example}}
@@ -0,0 +1,7 @@
{{#styleguide-example title="spinner - small"}}
<div class="spinner small"></div>
{{/styleguide-example}}
{{#styleguide-example title="spinner - regular"}}
<div class="spinner"></div>
{{/styleguide-example}}
@@ -0,0 +1,15 @@
{{#styleguide-example title="time-input"}}
{{time-input}}
{{/styleguide-example}}
{{#styleguide-example title="date-input"}}
{{date-input}}
{{/styleguide-example}}
{{#styleguide-example title="date-time-input"}}
{{date-time-input}}
{{/styleguide-example}}
{{#styleguide-example title="date-time-input-range"}}
{{date-time-input-range}}
{{/styleguide-example}}
@@ -0,0 +1,84 @@
{{#styleguide-example title="combo-box"}}
{{combo-box content=dummy.options}}
{{/styleguide-example}}
{{#styleguide-example title="filterable combo-box"}}
{{combo-box content=dummy.categoryNames filterable=true}}
{{/styleguide-example}}
{{#styleguide-example title="combo-box with a default state"}}
{{combo-box content=dummy.options none="category.none"}}
{{/styleguide-example}}
{{#styleguide-example title="combo-box clearable"}}
{{combo-box content=dummy.options none="category.none" clearable=true}}
{{/styleguide-example}}
{{#styleguide-example title="topic-notifications-options"}}
{{topic-notifications-options topic=dummy.topic}}
{{/styleguide-example}}
{{#styleguide-example title="topic-notifications-button"}}
<div id="#topic-footer-buttons">
{{topic-notifications-button topic=dummy.topic}}
</div>
{{/styleguide-example}}
{{#styleguide-example title="topic-footer-mobile-dropdown"}}
{{topic-footer-mobile-dropdown topic=dummy.topic}}
{{/styleguide-example}}
{{#styleguide-example title="category-chooser"}}
{{category-chooser}}
{{/styleguide-example}}
{{#styleguide-example title="pinned-button"}}
{{pinned-button topic=dummy.pinnedTopic}}
{{/styleguide-example}}
{{#styleguide-example title="pinned-options"}}
{{pinned-options topic=dummy.pinnedTopic}}
{{/styleguide-example}}
{{#styleguide-example title="categories-admin-dropdown"}}
{{categories-admin-dropdown}}
{{/styleguide-example}}
{{#styleguide-example title="category-notifications-button"}}
{{category-notifications-button category=dummy.categories.[0]}}
{{/styleguide-example}}
{{#styleguide-example title="notifications-button"}}
{{notifications-button i18nPrefix="groups.notifications" value=1}}
{{/styleguide-example}}
{{#styleguide-example title="dropdown-select-box"}}
{{dropdown-select-box content=dummy.options}}
{{/styleguide-example}}
{{#styleguide-example title="future-date-input-selector"}}
{{future-date-input-selector
minimumResultsForSearch=-1
statusType="open"
input=dummy.topicTimerUpdateDate
includeWeekend=true
includeForever=true
none="topic.auto_update_input.none"
}}
{{/styleguide-example}}
{{#styleguide-example title="multi-select"}}
{{multi-select none="test.none" content=dummy.options}}
{{/styleguide-example}}
{{#styleguide-example title="admin-group-selector"}}
{{admin-group-selector selected=dummy.selectedGroups content=dummy.groups}}
{{/styleguide-example}}
{{#styleguide-example title="list-setting"}}
{{list-setting settingValue=dummy.settings}}
{{/styleguide-example}}
{{#styleguide-example title="list-setting with colors"}}
{{list-setting settingValue=dummy.colors nameProperty="color"}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="topic-link"}}
{{topic-link dummy.topic}}
{{/styleguide-example}}
@@ -0,0 +1,27 @@
{{#styleguide-example title="invisible"}}
{{topic-status topic=dummy.invisibleTopic}}
{{/styleguide-example}}
{{#styleguide-example title="closed"}}
{{topic-status topic=dummy.closedTopic}}
{{/styleguide-example}}
{{#styleguide-example title="pinned"}}
{{topic-status topic=dummy.pinnedTopic}}
{{/styleguide-example}}
{{#styleguide-example title="unpinned"}}
{{topic-status topic=dummy.unpinnedTopic}}
{{/styleguide-example}}
{{#styleguide-example title="archived"}}
{{topic-status topic=dummy.archivedTopic}}
{{/styleguide-example}}
{{#styleguide-example title="warning"}}
{{topic-status topic=dummy.warningTopic}}
{{/styleguide-example}}
{{#styleguide-example title="no status"}}
{{topic-status topic=dummy.topic}}
{{/styleguide-example}}
@@ -0,0 +1,5 @@
{{#styleguide-section title="styleguide.title"}}
<div class="description">
{{i18n "styleguide.welcome"}}
</div>
{{/styleguide-section}}
@@ -0,0 +1,9 @@
{{#styleguide-example title="category-breadcrumbs"}}
{{bread-crumbs categories=dummy.categories showTags=false}}
{{/styleguide-example}}
{{#if siteSettings.tagging_enabled}}
{{#styleguide-example title="category-breadcrumbs - tags"}}
{{bread-crumbs categories=dummy.categories showTags=true}}
{{/styleguide-example}}
{{/if}}
@@ -0,0 +1,23 @@
{{#styleguide-example title="category-badge - bullet"}}
{{#each dummy.categories as |c|}}
{{category-badge c categoryStyle="bullet"}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title="category-badge - bar"}}
{{#each dummy.categories as |c|}}
{{category-badge c categoryStyle="bar"}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title="category-badge - box"}}
{{#each dummy.categories as |c|}}
{{category-badge c categoryStyle="box"}}
{{/each}}
{{/styleguide-example}}
{{#styleguide-example title="category-badge - none"}}
{{#each dummy.categories as |c|}}
{{category-badge c categoryStyle="none"}}
{{/each}}
{{/styleguide-example}}
@@ -0,0 +1,23 @@
{{#styleguide-example title="footer-message - default"}}
{{footer-message education=dummy.sentence message=dummy.short_sentence}}
{{/styleguide-example}}
{{#styleguide-example title="footer-message - latest"}}
{{footer-message
education=dummy.sentence
message=dummy.short_sentence
latest=true
canCreateTopicOnCategory=true
createTopic=(action "dummy")
}}
{{/styleguide-example}}
{{#styleguide-example title="footer-message - top"}}
{{footer-message
education=dummy.sentence
message=dummy.short_sentence
top=true
changePeriod=(action "dummy")
}}
{{/styleguide-example}}
@@ -0,0 +1,13 @@
{{#styleguide-example title="header-icons"}}
{{mount-widget widget="header-icons"}}
{{/styleguide-example}}
{{#styleguide-example title="header-icons - user"}}
{{mount-widget widget="header-icons" args=(hash user=dummy.user)}}
{{/styleguide-example}}
{{#styleguide-example title="header-icons - notifications"}}
{{mount-widget
widget="header-icons"
args=(hash user=dummy.userWithUnread flagCount=5)}}
{{/styleguide-example}}
@@ -0,0 +1,11 @@
{{#styleguide-example title="navigation-bar"}}
{{navigation-bar navItems=dummy.navItems filterMode="latest"}}
{{/styleguide-example}}
{{#styleguide-example title=".user-main .nav-pills"}}
{{#mobile-nav class="main-nav" desktopClass="nav nav-pills user-nav" currentPath=currentPath}}
{{#each dummy.navItems as |ni|}}
<li><a href={{ni.href}} class={{if ni.styleGuideActive "active"}}>{{ni.displayName}}</a></li>
{{/each}}
{{/mobile-nav}}
{{/styleguide-example}}
@@ -0,0 +1,17 @@
{{#styleguide-example title=".nav-stacked" class="half-size"}}
{{#mobile-nav class="preferences-nav" desktopClass="preferences-list action-list nav-stacked" currentPath=application.currentPath}}
{{#each dummy.navItems as |ni|}}
<li><a href={{ni.href}} class={{if ni.styleGuideActive "active"}}>{{ni.displayName}}</a></li>
{{/each}}
{{/mobile-nav}}
{{/styleguide-example}}
{{#styleguide-example title=".user-navigation .nav-stacked" class="half-size"}}
{{#d-section class="user-navigation"}}
{{#mobile-nav class="preferences-nav" desktopClass="preferences-list action-list nav-stacked" currentPath=application.currentPath}}
{{#each dummy.navItems as |ni|}}
<li><a href={{ni.href}} class={{if ni.styleGuideActive "active"}}>{{ni.displayName}}</a></li>
{{/each}}
{{/mobile-nav}}
{{/d-section}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="post-menu"}}
{{mount-widget widget="post-menu" args=dummy.transformedPost}}
{{/styleguide-example}}
@@ -0,0 +1,4 @@
{{#styleguide-example title="signup-cta"}}
{{signup-cta}}
{{/styleguide-example}}
@@ -0,0 +1,27 @@
{{#styleguide-example title="topic list item"}}
<table class="topic-list">
<tbody>
{{topic-list-item topic=dummy.topic showPosters=true}}
</tbody>
</table>
{{/styleguide-example}}
{{#styleguide-example title="topic list item - hide category"}}
<table class="topic-list">
<tbody>
{{topic-list-item topic=dummy.topic hideCategory=true showPosters=true}}
</tbody>
</table>
{{/styleguide-example}}
{{#styleguide-example title="topic list item - show likes"}}
<table class="topic-list">
<tbody>
{{topic-list-item topic=dummy.topic showLikes=true showPosters=true}}
</tbody>
</table>
{{/styleguide-example}}
{{#styleguide-example title="topic list item - latest" class="half-size"}}
{{latest-topic-list-item topic=dummy.topic}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="topic-notifications-button"}}
{{topic-notifications-button topic=dummy.topic}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="topic-timer-info"}}
{{topic-timer-info statusType="reminder" executeAt=dummy.soon}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="post"}}
{{mount-widget widget="post" args=dummy.transformedPost}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="topic-map"}}
{{mount-widget widget="topic-map" args=dummy.transformedPost}}
{{/styleguide-example}}
@@ -0,0 +1,11 @@
{{#styleguide-example title="topic-footer-buttons - logged in"}}
{{topic-footer-buttons
canInviteTo=true
topic=dummy.topic}}
{{/styleguide-example}}
{{#styleguide-example title="topic-footer-buttons - anonymous"}}
<div id="topic-footer-buttons">
{{d-button icon="reply" class="btn-primary pull-right" label="topic.reply.title"}}
</div>
{{/styleguide-example}}
@@ -0,0 +1,7 @@
{{#styleguide-example title="topic-list"}}
{{topic-list topics=dummy.topics showPosters=true}}
{{/styleguide-example}}
{{#styleguide-example title="topic-list - hide posters"}}
{{topic-list topics=dummy.topics showPosters=false}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="categories-only"}}
{{categories-only categories=dummy.categories}}
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="latest-topic-list" class="half-size"}}
{{latest-topic-list topics=dummy.topics}}
{{/styleguide-example}}
@@ -0,0 +1,10 @@
{{#styleguide-example title="d-modal"}}
{{#d-modal closeModal=(action "dummy") modalStyle="inline-modal" title=(i18n "styleguide.sections.modal.header")}}
{{#d-modal-body}}
{{html-safe dummy.lorem}}
{{/d-modal-body}}
<div class="modal-footer">
{{i18n "styleguide.sections.modal.footer"}}
</div>
{{/d-modal}}
{{/styleguide-example}}
@@ -0,0 +1,12 @@
{{#styleguide-example title="navigation"}}
<div class="list-controls">
<div class="container">
{{#d-section class="navigation-container"}}
{{bread-crumbs categories=dummy.categories}}
{{navigation-bar navItems=dummy.navItems filterMode="latest"}}
{{categories-admin-dropdown}}
{{create-topic-button canCreateTopic=true}}
{{/d-section}}
</div>
</div>
{{/styleguide-example}}
@@ -0,0 +1,3 @@
{{#styleguide-example title="suggested-topics"}}
{{suggested-topics topic=dummy.topic}}
{{/styleguide-example}}
@@ -0,0 +1,253 @@
{{#styleguide-example title=".user-main .about.collapsed-info.no-background"}}
{{#d-section class="user-main"}}
<section class="collapsed-info about no-background">
<div class="profile-image"></div>
<div class="details">
<div class="primary">
{{bound-avatar dummy.user "huge"}}
<section class="controls">
<ul>
<li>
<a class="btn btn-primary">
{{d-icon "envelope"}}
{{i18n "user.private_message"}}
</a>
</li>
<li><a href={{dummy.user.adminPath}} class="btn">{{d-icon "wrench"}}{{i18n "admin.user.show_admin_profile"}}</a></li>
<li><a href="#" class="btn">{{d-icon "angle-double-down"}}{{i18n "user.expand_profile"}}</a></li>
</ul>
</section>
<div class="primary-textual">
<h1 class="username">{{dummy.user.username}} {{d-icon "shield-alt"}}</h1>
<h2 class="full-name">{{dummy.user.name}}</h2>
<h3>{{dummy.user.title}}</h3>
</div>
</div>
<div style="clear: both"></div>
</div>
</section>
{{/d-section}}
{{/styleguide-example}}
{{#styleguide-example title=".user-main .about.collapsed-info.has-background"}}
{{#d-section class="user-main"}}
<section class="collapsed-info about has-background" style={{dummy.user.profileBackground}}>
<div class="profile-image"></div>
<div class="details">
<div class="primary">
{{bound-avatar dummy.user "huge"}}
<section class="controls">
<ul>
<li>
<a class="btn btn-primary">
{{d-icon "envelope"}}
{{i18n "user.private_message"}}
</a>
</li>
<li><a href={{dummy.user.adminPath}} class="btn">{{d-icon "wrench"}}{{i18n "admin.user.show_admin_profile"}}</a></li>
<li><a href="#" class="btn">{{d-icon "angle-double-down"}}{{i18n "user.expand_profile"}}</a></li>
</ul>
</section>
<div class="primary-textual">
<h1 class="username">{{dummy.user.username}} {{d-icon "shield-alt"}}</h1>
<h2 class="full-name">{{dummy.user.name}}</h2>
<h3>{{dummy.user.title}}</h3>
</div>
</div>
<div style="clear: both"></div>
</div>
</section>
{{/d-section}}
{{/styleguide-example}}
{{#styleguide-example title=".user-main .about.no-background"}}
{{#d-section class="user-main"}}
<section class="about no-background">
<div class="staff-counters">
<div><span class="helpful-flags">{{dummy.user.number_of_flags_given}}</span>&nbsp;{{i18n "user.staff_counters.flags_given"}}</div>
<div>
<a href="#">
<span class="flagged-posts">{{dummy.user.number_of_flagged_posts}}</span>&nbsp;{{i18n "user.staff_counters.flagged_posts"}}
</a>
</div>
<div>
<a href="#">
<span class="deleted-posts">{{dummy.user.number_of_deleted_posts}}</span>&nbsp;{{i18n "user.staff_counters.deleted_posts"}}
</a>
</div>
<div><span class="suspensions">{{dummy.user.number_of_suspensions}}</span>&nbsp;{{i18n "user.staff_counters.suspensions"}}</div>
<div><span class="warnings-received">{{dummy.user.warnings_received_count}}</span>&nbsp;{{i18n "user.staff_counters.warnings_received"}}</div>
</div>
<div class="profile-image"></div>
<div class="details">
<div class="primary">
{{bound-avatar dummy.user "huge"}}
<section class="controls">
<ul>
<li>
<a class="btn btn-primary">
{{d-icon "envelope"}}
{{i18n "user.private_message"}}
</a>
</li>
<li><a href={{dummy.user.adminPath}} class="btn">{{d-icon "wrench"}}{{i18n "admin.user.show_admin_profile"}}</a></li>
</ul>
</section>
<div class="primary-textual">
<h1 class="username">{{dummy.user.username}} {{d-icon "shield-alt"}}</h1>
<h2 class="full-name">{{dummy.user.name}}</h2>
<h3>{{dummy.user.title}}</h3>
<h3>
{{d-icon "map-marker-alt"}} {{dummy.user.location}}
{{d-icon "globe"}}
<a href={{dummy.user.website}} rel="nofollow noopener noreferrer" target="_blank">{{dummy.user.website_name}}</a>
</h3>
<div class="bio">
<div class="suspended">
{{d-icon "ban"}}
<b>{{i18n "user.suspended_notice" date=dummy.user.suspendedTillDate}}</b><br>
<b>{{i18n "user.suspended_reason"}}</b> {{dummy.user.suspend_reason}}
</div>
{{html-safe dummy.user.bio_cooked}}
</div>
<div class="public-user-fields">
{{#each dummy.user.publicUserFields as |uf|}}
{{#if uf.value}}
<div class="public-user-field {{uf.field.dasherized_name}}">
<span class="user-field-name">{{uf.field.name}}</span>:
<span class="user-field-value">{{uf.value}}</span>
</div>
{{/if}}
{{/each}}
</div>
</div>
</div>
<div style="clear: both"></div>
</div>
<div class="secondary">
<dl>
<dt>{{i18n "user.created"}}</dt><dd>{{bound-date dummy.user.created_at}}</dd>
<dt>{{i18n "user.last_posted"}}</dt><dd>{{bound-date dummy.user.last_posted_at}}</dd>
<dt>{{i18n "user.last_seen"}}</dt><dd>{{bound-date dummy.user.last_seen_at}}</dd>
<dt>{{i18n "views"}}</dt><dd>{{dummy.user.profile_view_count}}</dd>
<dt class="invited-by">{{i18n "user.invited_by"}}</dt><dd class="invited-by"><a href="#">{{dummy.user.invited_by.username}}</a></dd>
<dt class="trust-level">{{i18n "user.trust_level"}}</dt><dd class="trust-level">{{dummy.user.trustLevel.name}}</dd>
<dt>{{i18n "user.email.title"}}</dt>
<dd title={{dummy.user.email}}>
{{d-button icon="far-envelope" label="admin.users.check_email.text" class="btn-primary"}}
</dd>
<dt class="groups">{{i18n "groups.title" count=dummy.user.displayGroups.length}}</dt>
<dd class="groups">
{{#each dummy.user.displayGroups as |group|}}
<span><a href="#" class="group-link">{{group.name}}</a></span>
{{/each}}
</dd>
{{d-button icon="exclamation-triangle" label="user.admin_delete" class="btn-danger"}}
</dl>
</div>
</section>
{{/d-section}}
{{/styleguide-example}}
{{#styleguide-example title=".user-main .about.has-background"}}
{{#d-section class="user-main"}}
<section class="about has-background" style={{dummy.user.profileBackground}}>
<div class="staff-counters">
<div><span class="helpful-flags">{{dummy.user.number_of_flags_given}}</span>&nbsp;{{i18n "user.staff_counters.flags_given"}}</div>
<div>
<a href="#">
<span class="flagged-posts">{{dummy.user.number_of_flagged_posts}}</span>&nbsp;{{i18n "user.staff_counters.flagged_posts"}}
</a>
</div>
<div>
<a href="#">
<span class="deleted-posts">{{dummy.user.number_of_deleted_posts}}</span>&nbsp;{{i18n "user.staff_counters.deleted_posts"}}
</a>
</div>
<div><span class="suspensions">{{dummy.user.number_of_suspensions}}</span>&nbsp;{{i18n "user.staff_counters.suspensions"}}</div>
<div><span class="warnings-received">{{dummy.user.warnings_received_count}}</span>&nbsp;{{i18n "user.staff_counters.warnings_received"}}</div>
</div>
<div class="profile-image"></div>
<div class="details">
<div class="primary">
{{bound-avatar dummy.user "huge"}}
<section class="controls">
<ul>
<li>
<a class="btn btn-primary">
{{d-icon "envelope"}}
{{i18n "user.private_message"}}
</a>
</li>
<li><a href={{dummy.user.adminPath}} class="btn">{{d-icon "wrench"}}{{i18n "admin.user.show_admin_profile"}}</a></li>
</ul>
</section>
<div class="primary-textual">
<h1 class="username">{{dummy.user.username}} {{d-icon "shield-alt"}}</h1>
<h2 class="full-name">{{dummy.user.name}}</h2>
<h3>{{dummy.user.title}}</h3>
<h3>
{{d-icon "map-marker-alt"}} {{dummy.user.location}}
{{d-icon "globe"}}
<a href={{dummy.user.website}} rel="nofollow noopener noreferrer" target="_blank">{{dummy.user.website_name}}</a>
</h3>
<div class="bio">
<div class="suspended">
{{d-icon "ban"}}
<b>{{i18n "user.suspended_notice" date=dummy.user.suspendedTillDate}}</b><br>
<b>{{i18n "user.suspended_reason"}}</b> {{dummy.user.suspend_reason}}
</div>
{{html-safe dummy.user.bio_cooked}}
</div>
<div class="public-user-fields">
{{#each dummy.user.publicUserFields as |uf|}}
{{#if uf.value}}
<div class="public-user-field {{uf.field.dasherized_name}}">
<span class="user-field-name">{{uf.field.name}}</span>:
<span class="user-field-value">{{uf.value}}</span>
</div>
{{/if}}
{{/each}}
</div>
</div>
</div>
<div style="clear: both"></div>
</div>
<div class="secondary">
<dl>
<dt>{{i18n "user.created"}}</dt><dd>{{bound-date dummy.user.created_at}}</dd>
<dt>{{i18n "user.last_posted"}}</dt><dd>{{bound-date dummy.user.last_posted_at}}</dd>
<dt>{{i18n "user.last_seen"}}</dt><dd>{{bound-date dummy.user.last_seen_at}}</dd>
<dt>{{i18n "views"}}</dt><dd>{{dummy.user.profile_view_count}}</dd>
<dt class="invited-by">{{i18n "user.invited_by"}}</dt><dd class="invited-by"><a href="#">{{dummy.user.invited_by.username}}</a></dd>
<dt class="trust-level">{{i18n "user.trust_level"}}</dt><dd class="trust-level">{{dummy.user.trustLevel.name}}</dd>
<dt>{{i18n "user.email.title"}}</dt>
<dd title={{dummy.user.email}}>
{{d-button icon="far-envelope" label="admin.users.check_email.text" class="btn-primary"}}
</dd>
<dt class="groups">{{i18n "groups.title" count=dummy.user.displayGroups.length}}</dt>
<dd class="groups">
{{#each dummy.user.displayGroups as |group|}}
<span><a href="#" class="group-link">{{group.name}}</a></span>
{{/each}}
</dd>
{{d-button icon="exclamation-triangle" label="user.admin_delete" class="btn-danger"}}
</dl>
</div>
</section>
{{/d-section}}
{{/styleguide-example}}
@@ -0,0 +1,9 @@
{{#styleguide-section section=section}}
{{#if note}}
<div class="styleguide-note">
{{component (concat "notes/" note)}}
</div>
{{/if}}
{{outlet}}
{{/styleguide-section}}
@@ -0,0 +1,89 @@
.color-row {
.primary-very-low {
background-color: var(--primary-very-low, $primary-very-low);
}
.primary-low {
background-color: var(--primary-low, $primary-low);
}
.primary-low-mid {
background-color: var(--primary-low-mid, $primary-low-mid);
}
.primary-medium {
background-color: var(--primary-medium, $primary-medium);
}
.primary-high {
background-color: var(--primary-high, $primary-high);
}
.primary {
background-color: var(--primary, $primary);
}
.secondary-low {
background-color: var(--secondary-low, $secondary-low);
}
.secondary-medium {
background-color: var(--secondary-medium, $secondary-medium);
}
.secondary-high {
background-color: var(--secondary-high, $secondary-high);
}
.secondary {
background-color: var(--secondary, $secondary);
}
.tertiary-low {
background-color: var(--tertiary-low, $tertiary-low);
}
.tertiary-medium {
background-color: var(--tertiary-medium, $tertiary-medium);
}
.tertiary-high {
background-color: var(--tertiary-high, $tertiary-high);
}
.tertiary {
background-color: var(--tertiary, $tertiary);
}
.quaternary-low {
background-color: var(--quaternary-low, $quaternary-low);
}
.quaternary {
background-color: var(--quaternary, $quaternary);
}
.highlight-low {
background-color: var(--highlight-low, $highlight-low);
}
.highlight-medium {
background-color: var(--highlight-medium, $highlight-medium);
}
.highlight-high {
background-color: var(--highlight-high, $highlight-high);
}
.highlight {
background-color: var(--highlight, $highlight);
}
.danger-low {
background-color: var(--danger-low, $danger-low);
}
.danger-low-mid {
background-color: var(--danger-low-mid, $danger-low-mid);
}
.danger-medium {
background-color: var(--danger-medium, $danger-medium);
}
.danger {
background-color: var(--danger, $danger);
}
.success-low {
background-color: var(--success-low, $success-low);
}
.success-medium {
background-color: var(--success-medium, $success-medium);
}
.success {
background-color: var(--success, $success);
}
.love-low {
background-color: var(--love-low, $love-low);
}
.love {
background-color: var(--love, $love);
}
}
@@ -0,0 +1,166 @@
@import "colors";
@import "typography";
.styleguide {
display: flex;
.styleguide-note {
padding: 1em;
background-color: var(--tertiary, $tertiary);
margin-bottom: 1em;
}
.styleguide-menu {
flex: 1 0 0;
ul {
list-style: none;
margin-bottom: 2em;
li.styleguide-heading {
color: var(--primary-medium, $primary-medium);
text-transform: uppercase;
font-size: 14px;
}
li {
margin-bottom: 0.25em;
a {
color: var(--primary, $primary);
font-size: 14px;
}
a.active {
font-weight: bold;
}
}
}
}
.styleguide-contents {
flex: 4 0 0;
font-size: 14px;
}
.styleguide-section {
.section-title {
font-size: $font-up-6;
font-weight: normal;
margin-bottom: 1em;
}
.section-description {
margin-bottom: 2em;
}
.description {
margin: 1em 0;
}
.half-size {
width: 50%;
}
.styleguide-example {
.example-title {
color: var(--primary-medium, $primary-medium);
font-size: 0.8em;
border-bottom: 1px solid var(--primary-low, $primary-low);
margin-bottom: 0.8em;
}
.rendered {
width: 100%;
}
margin-bottom: 2em;
}
}
.color-row {
display: flex;
.color-example {
flex: 1;
display: flex;
flex-direction: column;
height: 120px;
margin: 0.5em 0.5em 0.5em 0;
.color-bg {
flex: 4;
}
.color-name {
flex: 1;
display: flex;
align-items: center;
padding: 0.25em 0.5em;
background-color: black;
color: white;
}
}
}
pre {
background: var(--primary-very-low, $primary-very-low);
white-space: pre-wrap;
&.pre-inline {
display: inline-block;
margin: 0;
vertical-align: bottom;
}
span {
color: var(--primary-medium, $primary-medium);
&.hljs-attribute {
color: teal;
}
}
}
p.reason {
display: inline;
color: var(--primary-medium, $primary-medium);
margin: 0 0 0 10px;
}
}
.buttons-examples {
button {
margin-right: 0.5em;
margin-bottom: 0.5em;
}
}
.icons-examples,
.topic-statuses-examples .d-icon {
margin-right: 0.5em;
margin-bottom: 0.5em;
}
.dropdowns-examples {
.select-kit.is-hidden {
display: inline-block;
}
}
.styleguide-icons {
display: grid;
grid-template-columns: 150px 150px 150px 150px 150px;
grid-gap: 10px;
.styleguide-icon {
background-color: var(--primary-low, $primary-low);
margin: 3px;
text-align: center;
padding: 10px;
overflow: hidden;
svg {
display: block;
font-size: 3em;
margin: 5px auto;
}
span {
font-size: $font-down-1;
}
}
}
@@ -0,0 +1,43 @@
p[class*="font-"] {
margin-top: 0;
}
.font-up-6 {
font-size: $font-up-6;
}
.font-up-5 {
font-size: $font-up-5;
}
.font-up-4 {
font-size: $font-up-4;
}
.font-up-3 {
font-size: $font-up-3;
}
.font-up-2 {
font-size: $font-up-2;
}
.font-up-1 {
font-size: $font-up-1;
}
.font-0 {
font-size: $font-0;
}
.font-down-1 {
font-size: $font-down-1;
}
.font-down-2 {
font-size: $font-down-2;
}
.font-down-3 {
font-size: $font-down-3;
}
.font-down-4 {
font-size: $font-down-4;
}
.font-down-5 {
font-size: $font-down-5;
}
.font-down-6 {
font-size: $font-down-6;
}
@@ -0,0 +1,81 @@
en:
js:
styleguide:
title: "Styleguide"
welcome: "To get started, choose a section from the menu on the left."
categories:
atoms: Atoms
molecules: Molecules
organisms: Organisms
sections:
typography:
title: "Typography"
example: "Welcome to Discourse"
paragraph: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
date_time_inputs:
title: "Date/Time inputs"
font_scale:
title: "Font System"
colors:
title: "Colors"
icons:
title: "Icons"
full_list: "See the full list of Font Awesome Icons"
input_fields:
title: "Input Fields"
buttons:
title: "Buttons"
dropdowns:
title: "Dropdowns"
categories:
title: "Categories"
bread_crumbs:
title: "Bread Crumbs"
navigation:
title: "Navigation"
navigation_bar:
title: "Navigation Bar"
navigation_stacked:
title: "Navigation Stacked"
categories_list:
title: "Categories List"
topic_link:
title: "Topic Link"
topic_list_item:
title: "Topic List Item"
topic_statuses:
title: "Topic Statuses"
topic_list:
title: "Topic List"
latest_topic_list:
title: "Latest Topic List"
footer_message:
title: "Footer Message"
signup_cta:
title: "Signup CTA"
topic_timer_info:
title: "Topic Timers"
topic_footer_buttons:
title: "Topic Footer Buttons"
topic_notifications:
title: "Topic Notifications"
post:
title: "Post"
topic_map:
title: "Topic Map"
suggested_topics:
title: "Suggested Topics"
post_menu:
title: "Post Menu"
modal:
title: "Modal"
header: "Modal Title"
footer: "Modal Footer"
user_about:
title: "User About Box"
header_icons:
title: "Header Icons"
spinners:
title: "Spinners"
@@ -0,0 +1,4 @@
en:
site_settings:
styleguide_enabled: "Enable a `/styleguide` path to aid in styling of Discourse"
styleguide_admin_only: "Limits visibility of the styleguide to admins"
+6
View File
@@ -0,0 +1,6 @@
# frozen_string_literal: true
Styleguide::Engine.routes.draw do
get "/" => 'styleguide#index'
get "/:category/:section" => 'styleguide#index'
end
+5
View File
@@ -0,0 +1,5 @@
plugins:
styleguide_enabled:
default: false
styleguide_admin_only:
default: true
@@ -0,0 +1,10 @@
# frozen_string_literal: true
module ::Styleguide
PLUGIN_NAME = "styleguide"
class Engine < ::Rails::Engine
engine_name Styleguide::PLUGIN_NAME
isolate_namespace Styleguide
end
end
+15
View File
@@ -0,0 +1,15 @@
# frozen_string_literal: true
# name: styleguide
# about: Preview how Widgets are Styled in Discourse
# version: 0.2
# author: Robin Ward
register_asset "stylesheets/styleguide.scss"
enabled_site_setting :styleguide_enabled
load File.expand_path('../lib/styleguide/engine.rb', __FILE__)
Discourse::Application.routes.append do
mount ::Styleguide::Engine, at: '/styleguide'
end
Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

@@ -0,0 +1,65 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'SiteSetting.styleguide_admin_only' do
before do
SiteSetting.styleguide_enabled = true
end
context 'styleguide is admin only' do
before do
SiteSetting.styleguide_admin_only = true
end
context 'user is admin' do
before do
sign_in(Fabricate(:admin))
end
it 'shows the styleguide' do
get '/styleguide'
expect(response.status).to eq(200)
end
end
context 'user is not admin' do
before do
sign_in(Fabricate(:user))
end
it 'doesnt allow access' do
get '/styleguide'
expect(response.status).to eq(403)
end
end
end
end
describe 'SiteSetting.styleguide_enabled' do
before do
sign_in(Fabricate(:admin))
end
context 'style is enabled' do
before do
SiteSetting.styleguide_enabled = true
end
it 'shows the styleguide' do
get '/styleguide'
expect(response.status).to eq(200)
end
end
context 'styleguide is disabled' do
before do
SiteSetting.styleguide_enabled = false
end
it 'returns a page not found' do
get '/styleguide'
expect(response.status).to eq(404)
end
end
end