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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 1921 additions and 1 deletions

1
.gitignore vendored
View File

@ -53,6 +53,7 @@ bootsnap-compile-cache/
!/plugins/discourse-nginx-performance-report !/plugins/discourse-nginx-performance-report
!/plugins/discourse-narrative-bot !/plugins/discourse-narrative-bot
!/plugins/discourse-presence !/plugins/discourse-presence
!/plugins/styleguide
!/plugins/discourse-local-dates !/plugins/discourse-local-dates
/plugins/*/auto_generated/ /plugins/*/auto_generated/

View File

@ -63,7 +63,7 @@ class Plugin::Metadata
"discourse-solved", "discourse-solved",
"discourse-spoiler-alert", "discourse-spoiler-alert",
"discourse-user-notes", "discourse-user-notes",
"discourse-styleguide", "styleguide",
"discourse-tooltips", "discourse-tooltips",
"discourse-translator", "discourse-translator",
"discourse-user-card-badges", "discourse-user-card-badges",

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)

View File

@ -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

View File

@ -0,0 +1,4 @@
export default Ember.Component.extend({
tagName: "section",
classNameBindings: [":color-example"],
});

View File

@ -0,0 +1,4 @@
export default Ember.Component.extend({
tagName: "section",
classNames: ["styleguide-example"],
});

View File

@ -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);
},
});

View File

@ -0,0 +1,3 @@
export default Ember.Component.extend({
tagName: "",
});

View File

@ -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));
},
});

View File

@ -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`;
}
},
});

View File

@ -0,0 +1,5 @@
export default Ember.Controller.extend({
actions: {
dummy() {},
},
});

View File

@ -0,0 +1,3 @@
export default Ember.Controller.extend({
sections: null,
});

View File

@ -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`);
});

View File

@ -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;
}

View File

@ -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];
}

View File

@ -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",
});
},
});

View File

@ -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);
},
});

View File

@ -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" });
});
}

View File

@ -0,0 +1,2 @@
<div class="color-bg {{color}}"></div>
<div class="color-name">${{color}}</div>

View File

@ -0,0 +1,3 @@
<div class="example-title">{{title}}</div>
<section class="rendered">{{yield}}</section>
<div class="clearfix"></div>

View File

@ -0,0 +1,6 @@
{{#each iconIDs as |id|}}
<div class="styleguide-icon">
{{ d-icon id }}
<span>{{id}}</span>
</div>
{{/each}}

View File

@ -0,0 +1,3 @@
{{#link-to "styleguide.show" section.category section.id}}
{{section-title section.id}}
{{/link-to}}

View File

@ -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>

View File

@ -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>

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="topic-link"}}
{{topic-link dummy.topic}}
{{/styleguide-example}}

View File

@ -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}}

View File

@ -0,0 +1,5 @@
{{#styleguide-section title="styleguide.title"}}
<div class="description">
{{i18n "styleguide.welcome"}}
</div>
{{/styleguide-section}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -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}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="post-menu"}}
{{mount-widget widget="post-menu" args=dummy.transformedPost}}
{{/styleguide-example}}

View File

@ -0,0 +1,4 @@
{{#styleguide-example title="signup-cta"}}
{{signup-cta}}
{{/styleguide-example}}

View File

@ -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}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="topic-notifications-button"}}
{{topic-notifications-button topic=dummy.topic}}
{{/styleguide-example}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="topic-timer-info"}}
{{topic-timer-info statusType="reminder" executeAt=dummy.soon}}
{{/styleguide-example}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="post"}}
{{mount-widget widget="post" args=dummy.transformedPost}}
{{/styleguide-example}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="topic-map"}}
{{mount-widget widget="topic-map" args=dummy.transformedPost}}
{{/styleguide-example}}

View File

@ -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}}

View File

@ -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}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="categories-only"}}
{{categories-only categories=dummy.categories}}
{{/styleguide-example}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="latest-topic-list" class="half-size"}}
{{latest-topic-list topics=dummy.topics}}
{{/styleguide-example}}

View File

@ -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}}

View File

@ -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}}

View File

@ -0,0 +1,3 @@
{{#styleguide-example title="suggested-topics"}}
{{suggested-topics topic=dummy.topic}}
{{/styleguide-example}}

View File

@ -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}}

View File

@ -0,0 +1,9 @@
{{#styleguide-section section=section}}
{{#if note}}
<div class="styleguide-note">
{{component (concat "notes/" note)}}
</div>
{{/if}}
{{outlet}}
{{/styleguide-section}}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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"

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
Styleguide::Engine.routes.draw do
get "/" => 'styleguide#index'
get "/:category/:section" => 'styleguide#index'
end

View File

@ -0,0 +1,5 @@
plugins:
styleguide_enabled:
default: false
styleguide_admin_only:
default: true

View File

@ -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

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

View File

@ -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