Skip to content

Commit

Permalink
Merge branch 'v4'
Browse files Browse the repository at this point in the history
# Conflicts:
#	package-lock.json
#	package.json
#	src/modules/controls.scss
#	src/version.scss
  • Loading branch information
joelfillmore committed Oct 9, 2024
2 parents 68a0fb1 + e22e9d7 commit c6b754b
Show file tree
Hide file tree
Showing 95 changed files with 15,193 additions and 20,606 deletions.
7 changes: 3 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ output/
docs/styles.css.map

# scratch / testing sass files
scratch.scss
scratch.css
scratch.html

/scratch/scratch.css
/scratch/scratch.scss
/scratch/index.html
250 changes: 184 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,118 +1,222 @@
# px-styles

This is a simple SCSS framework that provides basic site setup and some common functionality for web projects. The goal is to create a simple to understand boilerplate coupled with a consistent approach to styling that encourages reuse and best practices while maintaing flexibility.
## V4

## Useful Links
### Breaking Changes

- Repository: [https://github.com/thinkpixellab/px-styles](https://github.com/thinkpixellab/px-styles)
- API Documentation: [https://thinkpixellab.github.io/px-styles](https://thinkpixellab.github.io/px-styles)
- NPM Package: [https://www.npmjs.com/package/@thinkpixellab-public/px-styles](https://www.npmjs.com/package/@thinkpixellab-public/px-styles)
This isn't a complete list, but here are some notable changes when upgrading to V4.

## Install
- The config syntax now uses use dots instead of colons with get / config so `get('colors:accent')` is now `get('colors.accent')`.
- The clr function now prefers percentages instead of a level so `clr(accent, -5)` is now `clr(accent, -50%)`.

#### Install the package
### Todo / Considerations

First, add the package to the project using npm.
- Would it make sense to rename `config` as `set` so that it matches the `get` function naming?
- Need to refine the color / theme tagging system. The syntax is different for colors vs. site variables.
- Controls mixins still need some cleanup and need to figure out how to handle site-vars.
- Need to make a decision on whether to use color-mix with site-vars (or make it an option?).
- Add the ability to load px-styles with a complete config object and a way to export a configuration object (this is all on the assumption that loading this way would be faster...not sure if that's actually true so probably good to investigate first).

## Installation / Usage

Add the package to your project using npm.

```
npm install @thinkpixellab-public/px-styles --save
```

#### Create a Shared Loader / Configuration File
## Load the Module

#### Basic utils (no configuration)

A typical setup might consist of the following:
Each of these basic utility mixins or functions is completely standalone and requires no shared configuration. This is the most lightweight version of px-styles and is adequate for many scenarios.

```
@use '@thinkpixellab-public/px-styles/utils' as *
```

##### px-styles.scss
#### Site configuration

By convention px-styles is configured in a file in the project root called `px-styles.scss`. By placing this file in a known location all packages that use px-styles can access the same configuration by importing / using the same configuration.
If you want to access the site-configured utilities y9ou can load the default package which includes the basic utility functions and the site-configured utilitis. It does not include a handful of less commonly used modules (e.g. controls, boilerplate, etc.) on the assumption that those can be loaded as needed (to reduce overall loading times).

Configuring px-styles consists of setting any desired configuration using the `config()` mixin and then filling in any missing configuration with a call to the `init()` mixin.
Here's a basic loader:

```scss
// ----------------------------------------------------------------------------
// px-styles.scss
// Github: https://github.com/thinkpixellab/px-styles
// Docs: https://thinkpixellab.github.io/px-styles/
// ----------------------------------------------------------------------------
// forwards come first
@forward '@thinkpixellab-public/px-styles';

// now import it (so we can configure it)
@use '@thinkpixellab-public/px-styles' as *;

// add configuration as needed (this is optional)
@include config('colors.accent', #5157bd);
@include config('colors.selection', clr('accent', -10%));
@include config('controls.border-radius', 0.5em);

// call init() to set missing defaults, etc.
@include init();
```

Note: it might seem a little out of order to call init() (and loading defaults) after configuration, but we do this to avoid situations where local configuration accidentally relies on unintended usage of px-styles defaults. A good example of this would be the lines that configure `colors.accent` followed by `colors.selection` (which relies on colors.accent). If these were done in the opposite order they would fail (and rightly so since `colors.selection` is based on `colors.accent`). But if the library had been initialized with defaults, then the calls wouldn't fail but the selection color would be based on the wrong color (the px-styles default instead of the custom version).

#### Modules

// forward and use
You can Load individual modules after loading the configured library.

```
// load the module
@use '@thinkpixellab-public/px-styles/src/modules/boilerplate' as *;
```

### Create a Shared Loader / Configuration File

If you have multiple components or files that need to access a shared configuration, it often makes sense to create a shared loader / configuration file.

#### px.scss

```scss
@forward '@thinkpixellab-public/px-styles';
@use '@thinkpixellab-public/px-styles' as *;

// site config
@include config('colors:accent', #00dc82);
@include config('colors:page-bg', #011e26);
@include config('colors:page-fg', white);
@include config('colors.accent', #5157bd);
@include config('colors.selection', clr('accent', -10%));
@include config('controls.border-radius', 0.5em);

// initialize and load defaults (required)
@include init();
```

##### include.scss
#### my-component.scss

```scss

// load configured-styles
@use 'px' as *;

// load other custom modules if needed
@use '@thinkpixellab-public/px-styles/src/modules/controls' as *;

.my-class { ... }
```

Optionally, you could also create a utils only loader to make loading utils seem a bit cleaner (so you don't have to include the long package name every time). This might also encourage loading the simpler utils which require no configuration or config parsing.

The config file can be imported directly but most projects benefit from having a single non-emitting .scss file that, in addition to px-styles config, includes other shared project-specific variables, functions and mixins. This file can be included in any other component or scss file knowing that all shared scss will be available. By convention we call this file `include.scss`.
#### px-utils.scss

```scss
// ----------------------------------------------------------------------------
// include.scss
// ----------------------------------------------------------------------------
@forward '@thinkpixellab-public/px-styles/utils';
```

// forward and use
@forward '/px-styles.scss';
@use '/px-styles.scss' as *;
#### my-simple-component.scss

// shared site stuff
@mixin my-mixin() { ... }
$my-var: 123;
```scss
@use 'px-utils' as *;
```

##### global.scss
### Providing Configuration for px-vue

## Defauls, Config, Variables, etc.

There are so many potential sources for any given value that tt seems worth mentioning some guiding principles about where the value should come from and when and how convenient defaults should be provided (and then where those defaults come from).

- **hardcoded values** should be used when the value is absolute and unchanging.
- **SCSS variables** make sense when a hardcoded value would suffice but we're trying to keep the code DRY. See the node about module configuration below for a small exception to this.
- **mixin or function parameters** should be exposed when the value changes on each use (this is probably pretty obvious).
- **site / module "config" values** make sense when the value can/should be configured at the site level and is expected to be constant at runtime.
- **CSS variables** (or custom properties) make sense when the value might change during runtime (either in code or based on DOM location) or when we want to otherwise expose some kind of CSS accessible configuration. There is some runtime cost to this flexibility as well as potential complexity in the CSS itself. Also, CSS variables are difficult to work with inside of a framework because the only way to manipulate them is with calc() functions (e.g. it's not possible to multiply two css variables except using calc()).

This convention is outside of the scope of px-styles but worth noting. We typically place an css that needs to be generated for the entire site in a file called global.scss. This would include all site / page setup and boilerplate as well any shared styles. A typical file might look like this:
That all seems pretty straightforward, but the devil is in the details. In real world usage, things can be a bit muddier so let's address some common scenarios where there may be some ambiguity.

#### General Thoughts About Config and Defaults

A major purpose of a CSS framework like pxstyles is to simplify syntax and produce more consistent / better tested output but that needs to be balanced with flexibility.

That said, multple levels of defaults can also become a bit unruly and it can become difficult to know where a value is ultimately coming from.

A common pattern might be something like:

```scss
// ----------------------------------------------------------------------------
// global.scss
// ----------------------------------------------------------------------------
/* pxstyles */

@use 'include.scss' as *;
// this will set a value in config for default-background only if no has been configured already
@include default('default-background', orange);

// basic site setup
@include boilerplate();
@mixin dark-background($color: null) {
// lookup the site configured background
$color: if-null($color, get('default-background'));

// other global css
.button {
@include button();
background: darken($color, 10%);
}
```

### Pattern for Multiple Configurations
/* user code (no config) */

@use '@thinkpixellab-public/px-styles' as *;
@include dark-background(); // outputs dark orange
@include dark-background(green); // outputs dark green

/* user code (with config) */

All of the configuration settings for px-styles exist within a single map. Because of that, two distinct "instances" of px-styles can be loaded within the same context using the following pattern:
$site-config: (
'default-background': purple,
);

@use '@thinkpixellab-public/px-styles' as * with (
$-config: $site-config
);

@include dark-background(); // outputs dark purple
@include dark-background(green); // outputs dark green
```

This seems pretty useful, but even with just a couple of layers of redirection it can get pretty confusing to figure out where the value is coming from. And some examples might get even more complex. Imagine now that we're using the `dark-background()` mixin inside of a button mixin. The button mixin has it's own background configuration.

```scss
@use '@thinkpixellab-public/px-styles' as px-one;
@use '@thinkpixellab-public/px-styles' as px-two;
/* pxstyles */

// give each version a distinct map
px-one.$config: ();
px-two.$config: ();
@mixin button($accent: null) {
$accent: if-null($accent, get('button.accent'));

@include px-one.config('colors:accent', blue);
@include px-one.init();
.px-one-class {
color: px-one.accent();
background-color: $accent;
&:active {
@include dark-background($accent);
}
}

// px-two test
@include px-two.config('colors:accent', green);
@include px-two.init();
.px-two-class {
color: px-two.accent();
/* user code (with config for button accent) */

$site-config: (
'button.background': blue,
);

@use '@thinkpixellab-public/px-styles' as * with (
$-config: $site-config
);

.button {
@include button(); // background will be blue / darker blue (when active)
}
```

## API Documentation
I don't think we should go deeper than this.

#### Config in Utils vs. Site vs. Modules

In a hope to simplify the configuration of a pretty complex library, we rely on a single map that stores all config values. This can be initialized with a simple map object or maniuplated using mixins and function in `/src/site/config.scss`.

This is stated above, but worth mentioning again that the library is organized by whether the code relies on that config map. The `utils` module is configuration free. Functions and mixins may have smart defaults for parameters but there is no concept of a shared configuration. All functionaly is standalone. The `site` module relies on a shared config object. Other modules like `controls` and `typography` rely on the configured `site` module and also expose their own config.

#### Module Configuration

#### Mixin Parameter Defaults

#### Controls Mixins / Managing Opinionated Styles

#### Components and CSS Variables

#### CSS Variables in Config

No work has been done to guarantee that site/

### API Documentation

API Documentation can be found in the docs folder. Just open `index.html` in a browser (it should run fine from the local file system). All of the documentation is generated dynamically using sassdoc and output to a json file (which the page uses as a data source).

Expand Down Expand Up @@ -156,7 +260,7 @@ Domain specific functions include:
- `fs($name)` - gets a font-size from the type ramp
- `sp($n)` - gets a spacing value derived from the common spacer value
- `rems($px)` - convert px value to rems based on the sites base font-size
- `clr($name, $shade, $alpha)` - retrieves a common named color and optionally produce a shade of
- `color($name, $shade, $alpha)` - retrieves a common named color and optionally produce a shade of
that color
- `gray($scaler)` // gets a derived a gray value
- `shadow($level)` // creates a box shadow
Expand All @@ -181,7 +285,7 @@ Sample code that retrieves a bunch of common values:

&:hover {
// set the color called accent but one level darker
color: clr(accent, -1);
color: color(accent, -1);
}
}
```
Expand Down Expand Up @@ -238,3 +342,17 @@ Here is a sample scratch file that will load px-styles from local source:
- ~~Rename defaults() => init()~~
- ~~Make sanitize a module and optionally called by the boilerplate mixin~~
- ~~Bem helpers?~~

## BREAKING CHANGES

- Css maps now use periods as a separator instead of colons (so `button.background` instead of `button:backround`)
- Any settings related to controls are now just the name of the component (e.g. `controls:button:background` is now just `button:background`)
-

This is a simple SCSS framework that provides basic site setup and some common functionality for web projects. The goal is to create a simple to understand boilerplate coupled with a consistent approach to styling that encourages reuse and best practices while maintaing flexibility.

## Useful Links

- Repository: [https://github.com/thinkpixellab/px-styles](https://github.com/thinkpixellab/px-styles)
- API Documentation: [https://thinkpixellab.github.io/px-styles](https://thinkpixellab.github.io/px-styles)
- NPM Package: [https://www.npmjs.com/package/@thinkpixellab-public/px-styles](https://www.npmjs.com/package/@thinkpixellab-public/px-styles)
33 changes: 33 additions & 0 deletions all.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// ----------------------------------------------------------------------------
// DESCRIPTION
// ----------------------------------------------------------------------------
//
// Load this file in your main Sass file to include all the utilities, mixins, and modules. There is
// essentially no tree-shaking in Sass, so you will get everything in this package. In complex sites
// it probably makes sense to be more strategic about loading.
//
// In many cases you'll want to load index.scss instead of this file (which don't include modules or
// controls but just utils and common site aware mixins and functions).
//
// USAGE: @use '@thinkpixellab-public/px-styles/all' as *;

// ----------------------------------------------------------------------------
// FORWARDS
// ----------------------------------------------------------------------------

// Reusable utils (functions, mixins) that have no dependency on site configuration settings
@forward 'src/utils';

// Mixins / functions that have configuration settings / site awareness
@forward 'src/site';

// Standalone modules (depends on both utils and site)
@forward 'src/modules/atoms';
@forward 'src/modules/boilerplate';
@forward 'src/modules/highlightjs';
@forward 'src/modules/reading';
@forward 'src/modules/sanitize';
@forward 'src/modules/controls';

// Initializer (must run init() to set up site)
@forward 'src/init';
Loading

0 comments on commit c6b754b

Please sign in to comment.