A Reactive Design System: Svelte meets System UI
npm install @studiobear/designspek
#### A Reactive Design System: Svelte meets System UI
---
!designspec brotli !GitHub package.json version !GitHub
> _Notice: Unstable API and under heavy development_
Underlying Elements
Svelte is a UI development framework for creating boilerplate-free components that compile down to fast, virtual-DOM-free vanilla JS that is truly reactive.
System UI is an evolving standard for creating consistent, interoperable UIs. It is the underlying foundation to many UI-themeing libraries such as Styled System, Rebass, ThemeUI, and more.
- Styled System: Styled System is a collection of utility functions for forming style props based on a global theme object defining typographic and layout properties.
- Goober: a less than 1kb CSS-in-JS implementation (toting in comparison ~16/11kb respectively of styled-components/emotion. In this library, Goober's css function is used to parse and apply the style props formed by Styled System.
- Typography.js: Typography is difficult and the nuances of applying good typography exasperate the already-brittle system of themes and CSS. TypographyJS works as a seperate themeing layer that can be integrated with Styled System to apply such typographic nuances to the greater theme.
``bash
yarn add @studiobear/designspek
// or
npm i @studiobear/designspek
`
Themes are implementations of a design specification in the form of a Javascript object.
Example Theme Object:
`jsx`
export default {
spaces: [0, 2, 4, 8, 12, 18, 24, 32],
colors: {
text: '#333',
background: '#fff',
primary: '#639',
secondary: '#ff6347',
},
fonts: {
body: 'system-ui, sans-serif',
heading: 'system-ui, sans-serif',
monospace: 'Menlo, monospace',
},
fontWeights: {
body: 400,
heading: 700,
bold: 700,
},
lineHeights: {
body: 1.5,
heading: 1.125,
},
fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
}
`jsx
// Box.svelte
`
That's all! Your are ready to use all css property names + shorthand props as attribute on your component! See https://styled-system.com/api, the currently implemented API, for more documentation.
`jsx
// App.svelte
bg="theme.color.primary" color="color.secondary"
textAlign="center"
>
Resize me to see my responsive padding in action
$3
1. The attribute name will get mapped to the css property name. You can specify it either in camelCase
(textAlign) or kebab-case (text-align).
So, if you know css by heart, you already know 99% of your component's props.2. if the value is preceeded by an
_, then`jsx
$: linkStyle = {
color: theme.colors.primary,
_hover: {
color: theme.colors.secondary,
},
}
`3. if the value is an array then
designspek will create a media query for each breakpoint and will resolve the separate values just as described before.
padding: [0, "space.m", "space.l"]:- will create
padding: 0; (raw value) for theme.breakpoints[0]
- will create padding: 1rem; (space.m) for theme.breakpoints[1]
- will create padding: 2rem; (space.l) for theme.breakpoints[2]Currently available shorthand properties:
For commonly used css properties there are shortcuts to make your code _even less_ verbose.
Example:
my={1} => margin-top: 1rem; margin-bottom: 1rem;As with all other properties you can use the responsive Array notation as well!
`jsx
`API
While similar to other CSS-in-JS solutions, Designspek has been customized towards Svelte which is a compiler and does not use a virtual DOM.
> API is unstable and experimental. Main detractor of stability is the course of finding an SSR best-practice for Svelte.
$3
-
@params {Object} styles: An object of styles. Style keys are CSS in camelCase or use shorthand attributes.
- @params {Object optional} theme: Theme store subscription or raw theme object. Optional if no reactive updating required.
- @params {Boolean optional} ssr: Returns a raw CSS string instead of classname.
- @returns {string}: Returns classname connected to style injected into header or, if ssr, returns raw CSS string._Note:
ssr option is an exploration into server-side rendering options with Svelte and Sapper. Since it is for applying styles inline to elements, it may break inheritance and create unexpected side effects. Best used for critical elements seen on first load. This is a backup method to using extractCSS._`jsx
Static Heading
Reactive Heading
// Notice, uses style tag as raw css is output
SSR Heading
`$3
-
@params {Object} theme: Theme object. If contains a _styles_ property (theme.styles), parses and injects styles into header. For general global styles like styling Markdown.
- @returns {string}: Returns Global Style as string`jsx
`$3
-
@params {Object} theme: Theme store subscription.
- @params {boolean optional} active: Setting to true allows string of styles to be returned from Style library.
- @returns {''||string}: Returns nothing. If active = true, returns stored component styles as pre-parsed $3
-
@return nothingIn attempt to mitigate style inheritance issues, when components are mounted and JS is loaded, CSS-in-JS can take over, so SSR style element is removed from head.
$3
-
@params {Object} theme: Theme raw object.
- @params {Object} typographyThem: Typography theme object.
- @returns {Object} newTheme: Merged themes with typography sensitive elements included.TypographyJS themes allow injecting fonts and pre-styled typography declartions into the design specification. Typography should be applied before extracting modes and binding to Svelte store.
In main theme file:
`js
import { typography, fontLink } from '@studiobear/designspek'
import kirkhamTheme from 'typography-theme-kirkham'import mainTheme from './theme' //Raw theme object
const basic = typography(mainTheme, kirkhamTheme)
`$3
-
@params {Object} theme: Theme store subscription or raw object.
- @returns {string}: Parsed Google font stringIn main theme file:
`js
import kirkhamTheme from 'typography-theme-kirkham'
const googleFonts = fontLink(kirkhamTheme)
`In top Svelte component:
`jsx
`---
Roadmap to v1
- [ ] Stabilize SSR: SSR works for simple sites, but depth of components and increase quantity of
styled() calls results in race conditions and missed critical styles. Either find a way to prioritize critical style elemnts or explore alternatives such as pre-processing/pre-compiling options.
- [ ] Typescript: At the foundational level, design specifications define and work with a multitude of types; e.g., _numbers_(m: 0), _strings_(m: 'sm') and _arrays_(margin: ['sm', 'none', 'lg']). Ergo, static typings are a basic requirement for sane evolution.
- [ ] Optimize theme integration: The current direction is exploratory and naively pulls together multiple libraries as a proof-of-concept. However, in doing so, styles are looped a multiple of times to:
- get/convert mapped custom shorthand attributes
- integrate theme variables via Styled-System
- then finally parsed into CSS with Goober.
- [ ] Theme Aliases: The current mash-up breaks the built in Styled-System aliasing for things like color. Previously, 'primary' was all that's needed, but full object path of 'theme.colors.primary' is currently required. Aliases for spacing such as ['s','m','l'] instead of [0,1,2]` will make it the specification implementation more idiomatic.---
This library was initially inspired by svelte-styled-system(@manuschillerdev). At time of discovery, svelte-styled-system was annotated as a proof-of-concept for bringing in the concepts of styled-system and doing it in as small of a package as possible. _Designspek_ vears away from this by choosing to make design specificiations first class citizens at the cost of size efficiency.