From 1aa0710fc534467888add1df1e3a1c1f5be6c0d7 Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Wed, 28 Oct 2020 09:11:29 -0400 Subject: [PATCH] Add sl-theme component --- docs/_sidebar.md | 3 +- docs/components/theme.md | 67 +++++++++++++++++++++++++++++++ docs/getting-started/changelog.md | 1 + docs/getting-started/themes.md | 32 +++++++-------- src/components.d.ts | 21 ++++++++++ src/components/theme/theme.scss | 5 +++ src/components/theme/theme.tsx | 27 +++++++++++++ 7 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 docs/components/theme.md create mode 100644 src/components/theme/theme.scss create mode 100644 src/components/theme/theme.tsx diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 21501c31..da14ee03 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -35,6 +35,7 @@ - [Radio](/components/radio.md) - [Range](/components/range.md) - [Rating](/components/rating.md) + - [Responsive Embed](/components/responsive-embed.md) - [Select](/components/select.md) - [Skeleton](/components/skeleton.md) - [Spinner](/components/spinner.md) @@ -50,7 +51,7 @@ - [Animation](/components/animation.md) - [Format Bytes](/components/format-bytes.md) - [Include](/components/include.md) - - [Responsive Embed](/components/responsive-embed.md) + - [Theme](/components/theme.md) - Design Tokens - [Typography](/tokens/typography.md) diff --git a/docs/components/theme.md b/docs/components/theme.md new file mode 100644 index 00000000..921f7820 --- /dev/null +++ b/docs/components/theme.md @@ -0,0 +1,67 @@ +# Theme + +[component-header:sl-theme] + +Themes change the visual appearance of components. + +This component will activate a theme and apply its styles to everything inside. All themes must adhere to [theming guidelines](/getting-started/themes) and expose a class that follows the `sl-theme-{name}` convention. + +To activate a theme, include the necessary stylesheet(s) and wrap your content in an `` element. The theme to use is specified by the `name` prop. + +```html + + + + + +``` + +?> It's important to note that the default "light" theme isn't actually a theme — it's a set of design tokens and base styles that themes can use as a foundation to build upon. As such, it's not possible to opt in to the default theme using this component. + +## Examples + +### Dark Theme + +To use the official dark theme, include its stylesheet per the instructions on the [themes page](/getting-started/themes) and activate it as shown in the example below. All design tokens and components will render accordingly. + +```html preview +
+ + + +
+ + + Dropdown + + Item 1 + Item 2 + Item 3 + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Close + + Open Dialog + + Check me +
+
+
+ + +``` + +[component-metadata:sl-theme] diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md index ccbb2b91..f96ad560 100644 --- a/docs/getting-started/changelog.md +++ b/docs/getting-started/changelog.md @@ -8,6 +8,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis ## Next +- Added `sl-theme` utility and updated theming documentation - Fixed a bug where `sl-menu-item` wouldn't render properly in the dark theme - Improved placeholder contrast in dark theme diff --git a/docs/getting-started/themes.md b/docs/getting-started/themes.md index 301038cd..298c7855 100644 --- a/docs/getting-started/themes.md +++ b/docs/getting-started/themes.md @@ -6,24 +6,20 @@ The default theme is included as part of `shoelace.css` and should always be loa ## Dark Mode -To install the dark theme, add the following to your page. +To install the dark theme, add the following to the `` section of your app. ```html - - - ... - ``` -**Themes must be activated after importing!** You can do this by adding the theme's class name to the element you want the theme to apply to. This is usually ``, but themes can also be applied to container elements, making it possible to use more than one theme on the same page. +**Themes must be activated after importing!** You can do this with the [``](/components/theme.md) component. Only the contents of `` will inherit the theme's styles. ```html Light Mode -
+ Dark Mode -
+
``` ### Detecting the User's Color Scheme Preference @@ -40,13 +36,13 @@ Shoelace avoids using the `prefers-color-scheme` media query because not all app A theme is nothing more than a stylesheet that uses the Shoelace API to customize design tokens and/or components. To create a theme, you will need a decent understanding of CSS, including [CSS Custom Properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) and the [`::part` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/::part). -The recommended way to create a theme is to piggyback on top of the default theme, adjusting design tokens and styling components as necessary to achieve the look you want. This makes your theme lightweight and "future proof", as later versions of Shoelace may introduce new components that your theme won't support. The default theme will account for these so components won't appear to be broken. +The recommended way to create a theme is to piggyback on top of the default theme, adjusting design tokens and styling components as necessary to achieve the look you want. This makes your theme lightweight and "future proof", as upcoming versions of Shoelace may introduce new design tokens and components that your theme won't support initially. The default theme will account for these so components won't appear to be broken. Technically, you can roll your own theme from scratch without using the default theme as a baseline, but that approach isn't recommended. ### Theme Classes -All theme classes should use the `sl-theme-name` convention, where `name` is a lowercase, hyphen-delimited value representing the name of your theme. For example, a theme called "Purple Power" would use the `sl-theme-purple-power` class. +All theme classes must use the `sl-theme-{name}` convention, where `{name}` is a lowercase, hyphen-delimited value representing the name of your theme. For example, a theme called "Purple Power" would use the `sl-theme-purple-power` class. Every selector in a theme must be scoped to the theme's class to ensure interoperability with other themes. @@ -63,11 +59,11 @@ Every selector in a theme must be scoped to the theme's class to ensure interope } ``` -?> Avoid scoping design tokens to `:root`. The default theme does this to provide base styles that will apply to the page even when no `sl-theme-` class is applied. +?> Avoid scoping design tokens to `:root`. You may notice that the default theme does this, but that's because it's not technically a theme — it's a set of design tokens and base styles that themes can use as a foundation to build upon. ### Components -To customize individual components, use the following syntax. +To customize individual components, use the following syntax. Available "parts" can be found in the CSS Parts section of each component's documentation. ```css .sl-theme-purple-power sl-button::part(base) { @@ -75,11 +71,11 @@ To customize individual components, use the following syntax. } ``` -?> Pay special attention to each component's CSS Parts API. You usually need to use a `::part` selector when targeting components! +?> Pay special attention to each component's CSS Parts API. You almost always need to use a `::part` selector when theming components! ## Using a Custom Theme -If a theme adheres to the guidelines above, you can use it by importing the stylesheet and activating it with the theme's class name. +If a theme adheres to the guidelines above, you can use it by importing the stylesheet and activating it with the [``](/components/theme.md) component. ```html @@ -87,12 +83,14 @@ If a theme adheres to the guidelines above, you can use it by importing the styl - - ... + + + ... + ``` -In fact, you can apply a theme's class to any container on the page, not just the body. This lets you use more than one theme on the same page. +If desired, you can import and activate more than one theme on the same page. ## Submitting a Theme diff --git a/src/components.d.ts b/src/components.d.ts index fdaa5f7e..4dff527d 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -1139,6 +1139,12 @@ export namespace Components { */ "value": string; } + interface SlTheme { + /** + * The name of the theme to use. The user is responsible for including the associated stylesheet(s). Supportive themes must adhere to theme guidelines by exposing a class that follows the `sl-theme-{name}` convention. + */ + "name": string; + } interface SlTooltip { /** * The tooltip's content. @@ -1430,6 +1436,12 @@ declare global { prototype: HTMLSlTextareaElement; new (): HTMLSlTextareaElement; }; + interface HTMLSlThemeElement extends Components.SlTheme, HTMLStencilElement { + } + var HTMLSlThemeElement: { + prototype: HTMLSlThemeElement; + new (): HTMLSlThemeElement; + }; interface HTMLSlTooltipElement extends Components.SlTooltip, HTMLStencilElement { } var HTMLSlTooltipElement: { @@ -1477,6 +1489,7 @@ declare global { "sl-tab-panel": HTMLSlTabPanelElement; "sl-tag": HTMLSlTagElement; "sl-textarea": HTMLSlTextareaElement; + "sl-theme": HTMLSlThemeElement; "sl-tooltip": HTMLSlTooltipElement; } } @@ -2628,6 +2641,12 @@ declare namespace LocalJSX { */ "value"?: string; } + interface SlTheme { + /** + * The name of the theme to use. The user is responsible for including the associated stylesheet(s). Supportive themes must adhere to theme guidelines by exposing a class that follows the `sl-theme-{name}` convention. + */ + "name"?: string; + } interface SlTooltip { /** * The tooltip's content. @@ -2726,6 +2745,7 @@ declare namespace LocalJSX { "sl-tab-panel": SlTabPanel; "sl-tag": SlTag; "sl-textarea": SlTextarea; + "sl-theme": SlTheme; "sl-tooltip": SlTooltip; } } @@ -2773,6 +2793,7 @@ declare module "@stencil/core" { "sl-tab-panel": LocalJSX.SlTabPanel & JSXBase.HTMLAttributes; "sl-tag": LocalJSX.SlTag & JSXBase.HTMLAttributes; "sl-textarea": LocalJSX.SlTextarea & JSXBase.HTMLAttributes; + "sl-theme": LocalJSX.SlTheme & JSXBase.HTMLAttributes; "sl-tooltip": LocalJSX.SlTooltip & JSXBase.HTMLAttributes; } } diff --git a/src/components/theme/theme.scss b/src/components/theme/theme.scss new file mode 100644 index 00000000..03be999b --- /dev/null +++ b/src/components/theme/theme.scss @@ -0,0 +1,5 @@ +@import 'component'; + +:host { + display: contents; +} diff --git a/src/components/theme/theme.tsx b/src/components/theme/theme.tsx new file mode 100644 index 00000000..a8d87e30 --- /dev/null +++ b/src/components/theme/theme.tsx @@ -0,0 +1,27 @@ +import { Component, Host, Prop, h } from '@stencil/core'; + +/** + * @since 2.0 + * @status experimental + */ + +@Component({ + tag: 'sl-theme', + styleUrl: 'theme.scss', + shadow: true +}) +export class Theme { + /** + * The name of the theme to use. The user is responsible for including the associated stylesheet(s). Supportive themes + * must adhere to theme guidelines by exposing a class that follows the `sl-theme-{name}` convention. + */ + @Prop() name = ''; + + render() { + return ( + + + + ); + } +}