From 3135f472e2c4221a9348aec27514d3e2947bc9ab Mon Sep 17 00:00:00 2001 From: Martin Brennan Date: Thu, 2 Jan 2025 09:28:23 +1000 Subject: [PATCH] FEATURE: Improve wizard quality and rearrange steps (#30055) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit contains various quality improvements to our site setup wizard, along with some rearrangement of steps to improve the admin setup experience and encourage admins to customize the site early to avoid "all sites look the same" sentiment. #### Step rearrangement * “Your site is ready” from 3 → 4 * “Logos” from 4 → 5 * “Look and feel” from 5 → 3 #### Font selector improvements Changes the wizard font selector dropdown to show a preview of all fonts with a CSS class so you don't have to choose the font to get a preview. Also makes the fonts appear in alphabetical order. #### Preview improvements Placeholder text changed from lorem ipsum to actual topic titles, category names, and post content. This makes it feel more "real". Fixes "undefined" categories. Added a date to the topic timeline. Fixes button rectangles and other UI elements not changing in size when the font changed, leading to cut off text which looked super messy. Also fixed some font color issues. Fixed table header alignment for Latest topic list. #### Homepage style selector improvements Limited the big list of homepage styles to Latest, Hot, Categories with latest topics, and Category boxes based on research into the most common options. #### Preview header Changed the preview header to move the hamburger to the left and add a chat icon #### And more! Changed the background of the wizard to use our branded blob style. --- .../wizard/components/fields/dropdown.gjs | 73 +++++ .../wizard/components/fields/dropdown.hbs | 10 - .../wizard/components/fields/dropdown.js | 33 --- .../fields/image-previews/logo-small.js | 31 ++- .../static/wizard/components/fields/image.hbs | 7 +- .../static/wizard/components/fields/image.js | 8 + .../static/wizard/components/fields/radio.gjs | 21 +- .../styling-preview/-homepage-preview.js | 101 ++++--- .../fields/styling-preview/-preview-base.js | 146 ++++++---- .../fields/styling-preview/index.js | 106 +++++--- .../app/static/wizard/lib/preview.js | 33 ++- .../tests/helpers/select-kit-helper.js | 3 + .../wizard-fields-dropdown-test.gjs | 255 ++++++++++++++++++ .../addon/components/font-selector.js | 14 + .../font-selector/font-selector-row.js | 5 + .../components/homepage-style-selector.js | 11 + .../homepage-style-selector-row.hbs | 6 + .../homepage-style-selector-row.js | 5 + .../addon/components/selected-font.gjs | 10 + app/assets/stylesheets/wizard.scss | 47 +++- app/models/color_scheme.rb | 8 +- app/models/site_setting.rb | 2 +- app/models/theme.rb | 4 + config/locales/client.en.yml | 36 ++- config/locales/server.en.yml | 24 +- lib/stylesheet/importer.rb | 4 +- lib/wizard/builder.rb | 61 +++-- spec/fabricators/topic_fabricator.rb | 2 + spec/lib/wizard/wizard_builder_spec.rb | 6 +- spec/models/color_scheme_spec.rb | 4 +- spec/system/page_objects/pages/wizard.rb | 137 +++++++++- spec/system/wizard_spec.rb | 174 +++++++++--- 32 files changed, 1090 insertions(+), 297 deletions(-) create mode 100644 app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.gjs delete mode 100644 app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.hbs delete mode 100644 app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.js create mode 100644 app/assets/javascripts/discourse/tests/integration/components/wizard-fields-dropdown-test.gjs create mode 100644 app/assets/javascripts/select-kit/addon/components/font-selector.js create mode 100644 app/assets/javascripts/select-kit/addon/components/font-selector/font-selector-row.js create mode 100644 app/assets/javascripts/select-kit/addon/components/homepage-style-selector.js create mode 100644 app/assets/javascripts/select-kit/addon/components/homepage-style-selector/homepage-style-selector-row.hbs create mode 100644 app/assets/javascripts/select-kit/addon/components/homepage-style-selector/homepage-style-selector-row.js create mode 100644 app/assets/javascripts/select-kit/addon/components/selected-font.gjs diff --git a/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.gjs b/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.gjs new file mode 100644 index 00000000000..4a6f16d4c66 --- /dev/null +++ b/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.gjs @@ -0,0 +1,73 @@ +import Component from "@glimmer/component"; +import { hash } from "@ember/helper"; +import { action, set } from "@ember/object"; +import ColorPalettes from "select-kit/components/color-palettes"; +import ComboBox from "select-kit/components/combo-box"; +import FontSelector from "select-kit/components/font-selector"; +import HomepageStyleSelector from "select-kit/components/homepage-style-selector"; + +export default class Dropdown extends Component { + constructor() { + super(...arguments); + + if (this.args.field.id === "color_scheme") { + for (let choice of this.args.field.choices) { + if (choice?.data?.colors) { + set(choice, "colors", choice.data.colors); + } + } + } + + if (this.args.field.id === "body_font") { + for (let choice of this.args.field.choices) { + set(choice, "classNames", `body-font-${choice.id.replace(/_/g, "-")}`); + } + } + + if (this.args.field.id === "heading_font") { + for (let choice of this.args.field.choices) { + set( + choice, + "classNames", + `heading-font-${choice.id.replace(/_/g, "-")}` + ); + } + } + } + + get component() { + switch (this.args.field.id) { + case "color_scheme": + return ColorPalettes; + case "body_font": + case "heading_font": + return FontSelector; + case "homepage_style": + return HomepageStyleSelector; + default: + return ComboBox; + } + } + + keyPress(event) { + event.stopPropagation(); + } + + @action + onChangeValue(value) { + this.set("field.value", value); + } + + +} diff --git a/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.hbs b/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.hbs deleted file mode 100644 index 3fbeeb98de5..00000000000 --- a/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.hbs +++ /dev/null @@ -1,10 +0,0 @@ -{{component - this.component - class="wizard-container__dropdown" - value=this.field.value - content=this.field.choices - nameProperty="label" - tabindex="9" - onChange=(action "onChangeValue") - options=(hash translatedNone=false) -}} \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.js b/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.js deleted file mode 100644 index 9f720578228..00000000000 --- a/app/assets/javascripts/discourse/app/static/wizard/components/fields/dropdown.js +++ /dev/null @@ -1,33 +0,0 @@ -import Component from "@ember/component"; -import { action, set } from "@ember/object"; -import discourseComputed from "discourse-common/utils/decorators"; -import ColorPalettes from "select-kit/components/color-palettes"; -import ComboBox from "select-kit/components/combo-box"; - -export default class Dropdown extends Component { - init() { - super.init(...arguments); - - if (this.field.id === "color_scheme") { - for (let choice of this.field.choices) { - if (choice?.data?.colors) { - set(choice, "colors", choice.data.colors); - } - } - } - } - - @discourseComputed("field.id") - component(id) { - return id === "color_scheme" ? ColorPalettes : ComboBox; - } - - keyPress(e) { - e.stopPropagation(); - } - - @action - onChangeValue(value) { - this.set("field.value", value); - } -} diff --git a/app/assets/javascripts/discourse/app/static/wizard/components/fields/image-previews/logo-small.js b/app/assets/javascripts/discourse/app/static/wizard/components/fields/image-previews/logo-small.js index a91680360f2..537835a85b4 100644 --- a/app/assets/javascripts/discourse/app/static/wizard/components/fields/image-previews/logo-small.js +++ b/app/assets/javascripts/discourse/app/static/wizard/components/fields/image-previews/logo-small.js @@ -1,5 +1,6 @@ import { action } from "@ember/object"; -import { drawHeader, LOREM } from "../../../lib/preview"; +import { i18n } from "discourse-i18n"; +import { drawHeader } from "../../../lib/preview"; import PreviewBaseComponent from "../styling-preview/-preview-base"; export default class LogoSmall extends PreviewBaseComponent { @@ -34,10 +35,10 @@ export default class LogoSmall extends PreviewBaseComponent { const image = this.image; const headerMargin = headerHeight * 0.2; - const maxWidth = headerHeight - headerMargin * 2.0; let imageWidth = image.width; let ratio = 1.0; + if (imageWidth > maxWidth) { ratio = maxWidth / imageWidth; imageWidth = maxWidth; @@ -52,38 +53,42 @@ export default class LogoSmall extends PreviewBaseComponent { ); const afterLogo = headerMargin * 1.7 + imageWidth; - const fontSize = Math.round(headerHeight * 0.4); + const fontSize = Math.round(headerHeight * 0.3); ctx.font = `Bold ${fontSize}px '${headingFont}'`; ctx.fillStyle = colors.primary; - const title = LOREM.substring(0, 27); + const title = i18n("wizard.homepage_preview.topic_titles.what_books"); ctx.fillText( title, - headerMargin + imageWidth, - headerHeight - fontSize * 1.1 + headerMargin + imageWidth + 10, + headerHeight - fontSize * 1.8 ); const category = this.categories()[0]; const badgeSize = height / 13.0; ctx.beginPath(); ctx.fillStyle = category.color; - ctx.rect(afterLogo, headerHeight * 0.7, badgeSize, badgeSize); + ctx.rect(afterLogo + 2, headerHeight * 0.6, badgeSize, badgeSize); ctx.fill(); ctx.font = `Bold ${badgeSize * 1.2}px '${font}'`; ctx.fillStyle = colors.primary; ctx.fillText( - category.displayName, + category.name, afterLogo + badgeSize * 1.5, - headerHeight * 0.7 + badgeSize * 0.9 + headerHeight * 0.6 + badgeSize * 0.9 ); const LINE_HEIGHT = 12; ctx.font = `${LINE_HEIGHT}px '${font}'`; - const lines = LOREM.split("\n"); - for (let i = 0; i < 10; i++) { - const line = height * 0.55 + i * (LINE_HEIGHT * 1.5); - ctx.fillText(lines[i], afterLogo, line); + const opFirstSentenceLines = i18n( + "wizard.homepage_preview.topic_ops.what_books" + ) + .split(".")[0] + .split("\n"); + for (let i = 0; i < 2; i++) { + const line = height * 0.7 + i * (LINE_HEIGHT * 1.5); + ctx.fillText(opFirstSentenceLines[i], afterLogo, line); } } } diff --git a/app/assets/javascripts/discourse/app/static/wizard/components/fields/image.hbs b/app/assets/javascripts/discourse/app/static/wizard/components/fields/image.hbs index 88aa13d801f..de3591c9827 100644 --- a/app/assets/javascripts/discourse/app/static/wizard/components/fields/image.hbs +++ b/app/assets/javascripts/discourse/app/static/wizard/components/fields/image.hbs @@ -1,6 +1,9 @@