From 160ed62300088e28e48213b8b3d85e2e3e5ed563 Mon Sep 17 00:00:00 2001 From: RomanTsukanov Date: Tue, 10 Oct 2023 10:41:14 +0400 Subject: [PATCH] Describe theme API and fix theme applying instructions (#7102) * Describe theme API and fix theme applying instructions * Trim whitespaces --- docs/manage-default-themes-and-styles.md | 88 ++++++++++++++++-------- docs/sidebar.json | 16 +++-- src/survey.ts | 23 +++++-- src/themes.ts | 52 ++++++++++++++ 4 files changed, 139 insertions(+), 40 deletions(-) diff --git a/docs/manage-default-themes-and-styles.md b/docs/manage-default-themes-and-styles.md index 09b220a9df..39afd326a7 100644 --- a/docs/manage-default-themes-and-styles.md +++ b/docs/manage-default-themes-and-styles.md @@ -12,7 +12,7 @@ SurveyJS Form Library is shipped with several predefined UI themes. You can see ![Themes in SurveyJS Form Library](images/survey-library-themes.png) -To use a theme, you need to reference a SurveyJS style sheet. Refer to the following sections of Get Started help topics for detailed instructions: +To use a theme, you need to reference a SurveyJS style sheet. Refer to the following sections of Get Started help topics for detailed instructions: - [Configure Styles in Angular](https://surveyjs.io/form-library/documentation/get-started-angular#configure-styles) - [Configure Styles in Vue](https://surveyjs.io/form-library/documentation/get-started-vue#configure-styles) @@ -22,25 +22,73 @@ To use a theme, you need to reference a SurveyJS style sheet. Refer to the follo ## Apply a Predefined Theme -Predefined themes are distributed as JSON objects that specify CSS variables and other theme settings. You can find a full list of predefined themes and their variations on GitHub: [survey-core/themes](https://github.com/surveyjs/survey-library/tree/master/src/themes). To apply a predefined theme, import its module or reference its script _after_ `survey-core`. The following code shows how to apply the Layered Dark Panelless theme by importing a module: +Predefined themes are distributed as JSON objects that specify CSS variables and other theme settings. You can find a full list of predefined themes and their variations on GitHub: [survey-core/themes](https://github.com/surveyjs/survey-library/tree/master/src/themes). + +To apply a predefined theme in modular applications, import the theme object from its module and pass the object to `SurveyModel`'s [`applyTheme(theme)`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#applyTheme) method. The following code shows how to apply the Layered Dark Panelless theme: ```js import { Model } from "survey-core"; -import "survey-core/themes/layered-dark-panelless"; +/* + Don't forget to import or reference the Default V2 style sheet + as described in the Get Started with SurveyJS article for your framework +*/ +import { LayeredDarkPanelless } "survey-core/themes/layered-dark-panelless"; + +const surveyJson = { ... }; +const survey = new Model(surveyJson); +survey.applyTheme(LayeredDarkPanelless); ``` -The code below applies the same theme by referencing a script: +In classic script applications, reference a theme script _after_ the `survey-core` script and style sheet. Pass the theme object to the `applyTheme(theme)` method, as shown below: ```html + - + ``` -If you want to add more than one theme, refer to the [Switch Between Themes](#switch-between-themes) section for more information. +```js +const surveyJson = { ... }; +const survey = new Survey.Model(surveyJson); +survey.applyTheme(SurveyTheme.LayeredDarkPanelless); +``` + +## Switch Between Themes + +If you want to add more than one SurveyJS theme to your application, import them or reference their scripts and call `SurveyModel`'s [`applyTheme(theme)`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#applyTheme) method to specify an active theme. For example, the following code imports the Contrast Dark and Contrast Light themes and applies the latter: + +```js +// In modular applications: +import { Model } from "survey-core"; +import { ContrastDark } from "survey-core/themes/contrast-dark"; +import { ContrastLight } from "survey-core/themes/contrast-light"; + +const surveyJson = { ... }; +const survey = new Model(surveyJson); +survey.applyTheme(ContrastLight); +``` + +```html + + + + + + + + + +``` + +```js +const surveyJson = { ... }; +const survey = new Survey.Model(surveyJson); +survey.applyTheme(SurveyTheme.ContrastLight); +``` ## Create a Custom Theme @@ -52,7 +100,7 @@ Theme Editor is integrated into Survey Creator. Open our [all-in-one demo](/crea SurveyJS Theme Export -To apply your custom theme, pass the downloaded JSON object to `SurveyModel`'s `applyTheme()` method: +To apply your custom theme, pass the downloaded JSON object to `SurveyModel`'s [`applyTheme(theme)`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#applyTheme) method: ```js import { Model } from "survey-core"; @@ -60,29 +108,15 @@ const surveyJson = { ... }; const survey = new Model(surveyJson); survey.applyTheme({ - "cssVariables": { - // ... - }, - "themeName": "double", - "colorPalette": "dark", - "isPanelless": true + "cssVariables": { + // ... + }, + "themeName": "doubleborder", + "colorPalette": "dark", + "isPanelless": true }); ``` -## Switch Between Themes - -If you want to add more than one SurveyJS theme to your application, import them using named imports and call `SurveyModel`'s `applyTheme()` method to specify an active theme. For example, the following code imports the Contrast Dark and Contrast Light themes and applies the latter: - -```js -import { Model } from "survey-core"; -import { ContrastLight } from "survey-core/themes/contrast-light"; -import { ContrastDark } from "survey-core/themes/contrast-dark"; - -const surveyJson = { ... }; -const survey = new Model(surveyJson); -survey.applyTheme(ContrastLight) -``` - ## Apply Custom CSS Classes You can apply individual custom CSS classes to all survey elements of a specific type. To do this, define a JavaScript object in which keys specify survey elements and values specify CSS classes. For information on the object structure, refer to the following file on GitHub: [defaultV2Css.ts](https://github.com/surveyjs/survey-library/blob/master/src/defaultCss/defaultV2Css.ts#L13). Assign this object to [`SurveyModel`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model)'s `css` property. diff --git a/docs/sidebar.json b/docs/sidebar.json index d6d4448507..3a61248482 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -233,18 +233,20 @@ "Title": "Panel Dynamic" }, { - "Name": "settings", - "Title": "Global Settings" + "Name": "IAction", + "Title": "IAction" }, { - "Name": "IAction", - "Title": "IAction", - "IsHidden": true + "Name": "ITheme", + "Title": "ITheme" }, { "Name": "ICustomQuestionTypeConfiguration", - "Title": "ICustomQuestionTypeConfiguration", - "IsHidden": true + "Title": "ICustomQuestionTypeConfiguration" + }, + { + "Name": "settings", + "Title": "Global Settings" } ] } diff --git a/src/survey.ts b/src/survey.ts index d189f86b7f..1bb6069546 100644 --- a/src/survey.ts +++ b/src/survey.ts @@ -136,6 +136,10 @@ export class SurveyModel extends SurveyElementCore private navigationBarValue: ActionContainer; onThemeApplying: EventBase = new EventBase(); + /** + * An event that is raised after a [theme](/form-library/documentation/manage-default-themes-and-styles) is [applied](#applyTheme) to the survey. + * @see applyTheme + */ onThemeApplied: EventBase = new EventBase(); //#region Event declarations @@ -3347,7 +3351,7 @@ export class SurveyModel extends SurveyElementCore this.onCurrentPageChanged.fire(this, options); } private notifyQuestionsOnHidingContent(page: PageModel): void { - if(!page) return; + if (!page) return; page.questions.forEach(q => q.onHidingContent()); } private createPageChangeEventOptions(newValue: PageModel, oldValue: PageModel): any { @@ -5690,7 +5694,7 @@ export class SurveyModel extends SurveyElementCore } } private runQuestionsTriggers(name: string, value: any): void { - if(this.isDisplayMode || this.isDesignMode) return; + if (this.isDisplayMode || this.isDesignMode) return; const questions = this.getAllQuestions(); questions.forEach(q => q.runTriggers(name, value)); } @@ -7338,6 +7342,13 @@ export class SurveyModel extends SurveyElementCore this.onPopupVisibleChanged.fire(this, { question, popup, visible }); } + /** + * Applies a specified theme to the survey. + * + * [Themes & Styles](/form-library/documentation/manage-default-themes-and-styles (linkStyle)) + * @param theme An [`ITheme`](/form-library/documentation/api-reference/itheme) object with theme settings. + * @see onThemeApplied + */ public applyTheme(theme: ITheme): void { if (!theme) return; @@ -7396,20 +7407,20 @@ export class SurveyModel extends SurveyElementCore public addScrollEventListener(): void { this.scrollHandler = () => { this.onScroll(); }; this.rootElement.addEventListener("scroll", this.scrollHandler); - if(!!this.rootElement.getElementsByTagName("form")[0]) { + if (!!this.rootElement.getElementsByTagName("form")[0]) { this.rootElement.getElementsByTagName("form")[0].addEventListener("scroll", this.scrollHandler); } - if(!!this.css.rootWrapper) { + if (!!this.css.rootWrapper) { this.rootElement.getElementsByClassName(this.css.rootWrapper)[0]?.addEventListener("scroll", this.scrollHandler); } } public removeScrollEventListener(): void { if (!!this.rootElement && !!this.scrollHandler) { this.rootElement.removeEventListener("scroll", this.scrollHandler); - if(!!this.rootElement.getElementsByTagName("form")[0]) { + if (!!this.rootElement.getElementsByTagName("form")[0]) { this.rootElement.getElementsByTagName("form")[0].removeEventListener("scroll", this.scrollHandler); } - if(!!this.css.rootWrapper) { + if (!!this.css.rootWrapper) { this.rootElement.getElementsByClassName(this.css.rootWrapper)[0]?.removeEventListener("scroll", this.scrollHandler); } } diff --git a/src/themes.ts b/src/themes.ts index 5f302c14e0..e58f3f4198 100644 --- a/src/themes.ts +++ b/src/themes.ts @@ -1,14 +1,66 @@ export type ImageFit = "auto" | "contain" | "cover"; export type ImageAttachment = "fixed" | "scroll"; +/** + * A theme configuration interface. + * + * `ITheme` objects are used to apply predefined themes or create custom themes. Refer to the following help topic for more information: + * + * [Themes & Styles](https://surveyjs.io/form-library/documentation/manage-default-themes-and-styles (linkStyle)) + */ export interface ITheme { + /** + * A theme name. + */ themeName?: string; + /** + * A color palette. + * + * Possible values: + * + * - `"light"` + * - `"dark"` + */ colorPalette?: string; + /** + * A Boolean value that specifies whether survey questions are displayed within panels (`false`) or without them (`true`). + */ isPanelless?: boolean; + /** + * An image to display as survey background. This property accepts a hyperlink or a data URL. + */ backgroundImage?: string; + /** + * A string value that specifies how to resize the [background image](#backgroundImage) to fit it into its container. + * + * Possible values: + * + * - `"auto"` + * - `"contain"` + * - `"cover"` + * + * Refer to the description of the [`background-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-size#values) CSS property values on MDN for detailed information on the possible values. + */ backgroundImageFit?: ImageFit; + /** + * A string value that specifies whether the [background image](#backgroundImage) is fixed in its position or scrolled along with the survey. + * + * Possible values: + * + * - `"fixed"` + * - `"scroll"` + */ backgroundImageAttachment?: ImageAttachment; + /** + * A value from 0 to 1 that specifies how transparent the [background image](#backgroundImage) should be: 0 makes the image completely transparent, and 1 makes it opaque. + */ backgroundOpacity?: number; + /** + * An object with survey header settings. + */ cover?: {[index: string]: any}; + /** + * An object with CSS variables. + */ cssVariables?: { [index: string]: string }; }