Add sl-theme component

pull/261/head
Cory LaViska 2020-10-28 09:11:29 -04:00
rodzic 264356afce
commit 1aa0710fc5
7 zmienionych plików z 138 dodań i 18 usunięć

Wyświetl plik

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

Wyświetl plik

@ -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 `<sl-theme>` element. The theme to use is specified by the `name` prop.
```html
<link rel="stylesheet" href="your-theme.css">
<sl-theme name="dark">
<!-- Everything inside will use the dark theme -->
</sl-theme>
```
?> 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
<div class="theme-overview">
<sl-theme name="dark">
<!-- Design tokens used inside <sl-theme> will reflect the theme's colors -->
<div style="background-color: var(--sl-color-gray-10); padding: var(--sl-spacing-xx-large);">
<!-- These are just some sample components to demonstrate -->
<sl-dropdown>
<sl-button slot="trigger" caret>Dropdown</sl-button>
<sl-menu>
<sl-menu-item>Item 1</sl-menu-item>
<sl-menu-item>Item 2</sl-menu-item>
<sl-menu-item>Item 3</sl-menu-item>
</sl-menu>
</sl-dropdown>
<sl-dialog label="Dialog">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<sl-button slot="footer" type="primary">Close</sl-button>
</sl-dialog>
<sl-button>Open Dialog</sl-button>
<sl-checkbox>Check me</sl-checkbox>
</div>
</sl-theme>
</div>
<script>
(() => {
const container = document.querySelector('.theme-overview');
const dialog = container.querySelector('sl-dialog');
const openButton = dialog.nextElementSibling;
const closeButton = dialog.querySelector('sl-button[slot="footer"]');
openButton.addEventListener('click', () => dialog.show());
closeButton.addEventListener('click', () => dialog.hide());
})();
</script>
```
[component-metadata:sl-theme]

Wyświetl plik

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

Wyświetl plik

@ -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 `<head>` section of your app.
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@%VERSION%/themes/dark.css">
<body class="sl-theme-dark">
...
</body>
```
**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 `<body>`, 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 [`<sl-theme>`](/components/theme.md) component. Only the contents of `<sl-theme>` will inherit the theme's styles.
```html
<sl-button>Light Mode</sl-button>
<div class="sl-theme-dark">
<sl-theme name="dark">
<sl-button>Dark Mode</sl-button>
</div>
</sl-theme>
```
### 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 [`<sl-theme>`](/components/theme.md) component.
```html
<head>
@ -87,12 +83,14 @@ If a theme adheres to the guidelines above, you can use it by importing the styl
<link rel="stylesheet" href="path/to/purple-power.css">
</head>
<body class="sl-theme-purple-power">
...
<body>
<sl-theme name="purple-power">
...
</sl-theme>
</body>
```
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

21
src/components.d.ts vendored
Wyświetl plik

@ -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<HTMLSlTabPanelElement>;
"sl-tag": LocalJSX.SlTag & JSXBase.HTMLAttributes<HTMLSlTagElement>;
"sl-textarea": LocalJSX.SlTextarea & JSXBase.HTMLAttributes<HTMLSlTextareaElement>;
"sl-theme": LocalJSX.SlTheme & JSXBase.HTMLAttributes<HTMLSlThemeElement>;
"sl-tooltip": LocalJSX.SlTooltip & JSXBase.HTMLAttributes<HTMLSlTooltipElement>;
}
}

Wyświetl plik

@ -0,0 +1,5 @@
@import 'component';
:host {
display: contents;
}

Wyświetl plik

@ -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 (
<Host class={`sl-theme-${this.name}`}>
<slot />
</Host>
);
}
}