@plangrid/structure
Version:
CSS structure library
528 lines (415 loc) • 19.3 kB
Markdown
# structure
- [`npm install @plangrid/structure`](https://www.npmjs.com/package/@plangrid/structure)
- [`main.css`](main.css) is the production bundle
- [unpkg](https://unpkg.com/@plangrid/structure/) for [codepen](https://codepen.io/ryanve/pen/gRamvZ)
- [`CONTRIBUTING.md`](CONTRIBUTING.md)
- [JavaScript API](#javascript-api)
## Usage
- Favor flexbox for layout over other layout techniques
- [Flexbox classes](modules/flexbox.css) use pure [flex properties](https://www.w3.org/TR/css-flexbox-1/) to afford layouts in any direction or [alignment](modules/alignment.css)
- Be aware of [flexbugs](https://github.com/philipwalton/flexbugs#flexbugs) and especially test complex layouts for browser differences
### `flex` [balanced grid](https://codepen.io/ryanve/pen/mmgjXE)
```html
<div class="flex">
<div class="flex-auto">item</div>
<div class="flex-auto">item</div>
<div class="flex-auto">item</div>
</div>
```
### `flex` [wrapping grid](https://codepen.io/ryanve/pen/JNzPMw)
```html
<div class="flex flex-wrap">
<div class="basis-4">grid item</div>
<div class="basis-4">grid item</div>
<div class="basis-4">grid item</div>
<div class="basis-4">grid item</div>
<div class="basis-4">grid item</div>
</div>
```
### `flex` [reversing](https://codepen.io/ryanve/pen/BdJgzp)
```html
<ol class="flex flex-column-reverse p0">
<li class="block p2 flex-auto">1</li>
<li class="block p2 flex-auto">2</li>
<li class="block p2 flex-auto">3</li>
</ol>
```
### `flex` [centering](https://codepen.io/ryanve/pen/RVOYoZ)
```html
<div class="flex items-center justify-center">
<p>I'm centered :)
</div>
```
### [`alignment`](modules/alignment.css)
- [Our alignment classes](modules/alignment.css) are useful for aligning flex items
- Properties include [`align-items`](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items) [`align-content`](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content) [`align-self`](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self) [`justify-content`](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)
- Values include [alignment values](https://www.w3.org/TR/css-align-3/#alignment-values) that are supportable by our browser coverage
- W3C categorizes values as [positional](https://www.w3.org/TR/css-align-3/#positional-values) | [baseline](https://www.w3.org/TR/css-align-3/#baseline-values) | [distribution](https://www.w3.org/TR/css-align-3/#distribution-values)
### [`spacing`](https://github.com/ryanve/spacing/tree/v0.3.0#classes)
```html
<figure class="m0 mb1 p2 pr4">
<figure class="p2 m0 mb1 mb0-last">content</figure>
<figure class="p2 m0 mb1 mb0-last">content</figure>
</figure>
```
#### [Experimental](https://github.com/plangrid/structure/pull/44): [`[data-spacing]`](https://github.com/ryanve/spacing/tree/v0.2.1#data-spacing)
```jsx
<Component data-spacing="mt0 mb2">
```
### [`position`](https://codepen.io/ryanve/pen/PmgBLK)
- `.static`
- `.relative`
- `.absolute`
- `.fixed`
- `.focus-static` for use like `"relative focus-static"` to sink on focus
- `.focus-relative` for use like `"static focus-relative"` to lift on focus
- `.top-auto` `.left-auto` `.right-auto` `.bottom-auto`
- `.top-0` `.left-0` `.right-0` `.bottom-0`
```html
<div class="relative">
<div class="absolute top-0 left-0 right-0 bottom-0">I fill my container</div>
</div>
```
### [`border`](modules/border.css)
- `.border` **Deprecated.** Favor `border-1px border-solid`
- `.border-top` **Deprecated.** Favor `border-1px bt-solid`
- `.border-left` **Deprecated.** Favor `border-1px bl-solid`
- `.border-right` **Deprecated.** Favor `border-1px br-solid`
- `.border-bottom` **Deprecated.** Favor `border-1px bb-solid`
- `.border-1px` is our standard `border-width` for any bordered component
- `.border-none` `.bt-none` `.br-none` `.bb-none` `.bl-none`
- `.border-dashed` `.bt-dashed` `.br-dashed` `.bb-dashed` `.bl-dashed`
- `.border-solid` `.bt-solid` `.br-solid` `.bb-solid` `.bl-solid`
- `.border-hidden` `.bt-hidden` `.br-hidden` `.bb-hidden` `.bl-hidden`
### [`border-radius`](https://plangrid.github.io/structure/#corners)
Round `>=6px` to `12px` and `<6px` to `3px` because `2px` `3px` `12px` are the most current sizes in our design system. Feature specs may be outdated. Please `#truststructure`
- `.rounded` **Deprecated.** Favor `round-medium`
- `.rounded-stack` **Deprecated.** Favor `round-medium sharp-stack`
- `.rounded-shelf` **Deprecated.** Favor `round-medium sharp-shelf`
- `.round-small` for `2px` corners. Use on pills
- `.round-medium` for `3px` corners. Use on buttons, cards...
- `.round-large` for `12px` corners. Use on modals
- `.round-circle` for `50%` corners
- `.sharp-top` zero top corners
- `.sharp-left` zero left corners
- `.sharp-right` zero right corners
- `.sharp-bottom` zero bottom corners
- `.sharp-shelf` zero interior shelf corners
- `.sharp-stack` zero interior stack corners
```html
<nav class="block p2 round-medium sharp-stack m-auto mt0 mb2">
<a class="block p2 round-medium sharp-stack mb1">top</a>
<a class="block p2 round-medium sharp-stack mb1">middle</a>
<a class="block p2 round-medium sharp-stack mb1">bottom</a>
</nav>
```
```html
<div class="width-em height-em round-circle">circle</div>
```
### [`border-width`](https://codepen.io/ryanve/pen/jYygaX)
Melding and welding refer to the union of borders between siblings. `meld` and `weld` do the same job but with opposing techniques. Compose them together to remove any inner borders. `stack` affects vertical union. `shelf` affects horizontal union.
- `.meld-stack` - meld stacked borders into one via `:not(:first-child)`
- `.meld-shelf` - meld shelved borders into one via `:not(:first-child)`
- `.weld-stack` - weld stacked borders into one via `:not(:last-child)`
- `.weld-shelf` - weld shelved borders into one via `:not(:last-child)`
```html
<a class="block p2 border round-medium sharp-stack meld-stack">top</a>
<a class="block p2 border round-medium sharp-stack meld-stack">middle</a>
<a class="block p2 border round-medium sharp-stack meld-stack">bottom</a>
```
```html
<a class="block p2 border round-medium sharp-shelf meld-shelf">left</a>
<a class="block p2 border round-medium sharp-shelf meld-shelf">right</a>
<a class="block p2 border round-medium sharp-shelf meld-shelf">bottom</a>
```
### [`display`](https://codepen.io/ryanve/pen/aWxjpX)
```html
<label class="block">
<input class="inline-block mr1" type="checkbox" checked>
Use functional CSS
</label>
```
### [`visibility`](https://developer.mozilla.org/en-US/docs/Web/CSS/visibility)
- `.vis-visible` default (element box is visible)
- `.vis-hidden` invisible and inaccessible but retains layout
- `.vis-collapse` invisible and inaccessible but retains [flex strut](https://drafts.csswg.org/css-flexbox-1/#visibility-collapse) or [table layout](https://drafts.csswg.org/css-tables-3/#visibility-collapse-rendering) with [careful use](https://developer.mozilla.org/en-US/docs/Web/CSS/visibility#Browser_compatibility)
### [`overflow`](modules/overflow.css)
- `.overflow-visible` or per axis `.ox-visible` `.oy-visible`
- `.overflow-hidden` or per axis `.ox-hidden` `.oy-hidden`
- `.overflow-scroll` or per axis `.ox-scroll` `.oy-scroll`
- `.overflow-auto` or per axis `.ox-auto` `oy-auto`
- `.overflow-dots` sets `text-overflow` to `ellipsis`
- `.wrap-normal` sets `overflow-wrap` to `normal`
- `.wrap-word` sets `overflow-wrap` to `break-word`
```html
<div class="overflow-auto">
I scroll as needed.
</div>
<div class="oy-scroll">
I scroll vertically.
</div>
<div class="overflow-hidden overflow-dots ws-nowrap width-fit">
I truncate normally...
</div>
<div class="overflow-hidden overflow-dots ws-nowrap width-clip width-force">
I truncate specially...
</div>
```
### [`white-space`](https://developer.mozilla.org/en-US/docs/Web/CSS/white-space)
- `.ws-normal`
- `.ws-nowrap`
- `.ws-pre`
- `.ws-pre-wrap`
- `.ws-pre-line`
### [`sizing`](modules/sizing.css)
```html
<div class="max-viewport min-zero width-all height-all">
example
</div>
```
### [`float`](https://developer.mozilla.org/en-US/docs/Web/CSS/float)
We avoid floats where possible due to the abundance of more maintainable techniques such as flexbox for many scenarios. We provide `.float-none`, `.float-left`, `.float-right`, `.clearfix` for transitional use and [special cases](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context).
### [`list-style`](https://developer.mozilla.org/en-US/docs/Web/CSS/list-style)
Use these on `li` or its `ul` or `ol` to affect all children. These only apply when `display` is `list-item`. Avoid `inside` when its children are `block` because [browsers vary in how inside blocks appear](https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-position).
- `.list-disc` sets type to `disc` (initial)
- `.list-circle` sets type to `circle`
- `.list-outside` sets position to `outside` (initial)
- `.list-inside` sets position to `inside`
- `.list-none` sets style to `none`
### [`text-align`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align)
- `.text-left`
- `.text-right`
- `.text-center`
### [`vertical-align`](https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align)
Favor flexbox techniques for layout but know that these are available for finetuning.
- `.align-baseline` default
- `.align-top`
- `.align-middle`
- `.align-bottom`
- `.align-sub`
- `.align-super`
- `.align-ascent` for `text-top`
- `.align-descent` for `text-bottom`
### [`font`](modules/font.css)
- Display fonts are named in t-shirt sizes. [See demo](https://plangrid.github.io/structure/#fonts) and round to the nearest fit :)
- Components may access via [`import structure from "@plangrid/structure"`](#javascript-api)
```js
structure.bond("FontC") // "font-os font-c"
structure.bond("FontB") // "font-os font-b"
structure.bond("FontXXS") // "font-os font-xxs"
structure.bond("FontXS") // "font-os font-xs"
structure.bond("FontS") // "font-os font-s"
structure.bond("FontM") // "font-os font-m"
structure.bond("FontL") // "font-os font-l"
structure.bond("FontXL") // "font-os font-xl"
```
- `.font-c` is `400 12px/1.25` `none`
- `.font-b` is `400 14px/1.5` `none`
- `.font-xxs` is `400 12px/1.25` `uppercase`
- `.font-xs` is `600 16px/1.5` `none`
- `.font-s` is `400 20px/1.25` `none`
- `.font-m` is `400 26px/1.25` `none`
- `.font-l` is `600 32px/1.25` `none`
- `.font-xl` is `600 42px/1` `none`
#### `.font-os`
- `.font-os` Recommended. Equals `.family-os` U `normal normal 400`
- `.family-inherit`
- `.family-os`
#### `font-weight`
- `.weight-inherit`
- `.weight-light`
- `.weight-normal` *legacy alias:* `.unbold`
- `.weight-semibold` *legacy alias:* `.semibold`
- `.weight-bold` *legacy alias:* `.bold`
#### `.font-collapse`
- Collapse whitespace or hide text in a11y technique
- `.font-collapse` = `.size-collapse` U `.line-collapse`
#### `font-size`
- `.size-inherit`
- `.size-14px`
- `.size-16px`
- `.size-20px`
- `.size-26px`
- `.size-32px`
- `.size-42px`
- `.size-body` **at risk**
- `.size-caption` **at risk**
#### `line-height`
- `.line-initial` for `normal` initial
- `.line-inherit` for `inherit`
- `.line-single` is `1` for use on headings or alignments
- `.line-subcompact` is `1.125` for use on headings
- `.line-compact` is `1.25` for use on headings
- `.line-passing` is `1.5` for text. [Passes WCAG guidelines](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-visual-presentation.html)
- `.line-double` is `2` for special cases
### [`text-transform`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform)
Case classes transform the entire element while letter classes only transform the `::first-letter` such that you can compose as needed like `"case-lower letter-upper"` for sentence case.
- `.case-none` CSS is composable
- `.case-lower` css is composable
- `.case-upper` CSS IS COMPOSABLE
- `.case-proper` CSS Is Composable
- `.letter-lower` cSS is composable
- `.letter-upper` CSS is composable
- `.case-lower.letter-upper` Css is composable
- `.case-upper.letter-lower` cSS IS COMPOSABLE
### [`text-decoration`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration)
- `.underline-none` removes underline. You must provide alternative visual affordance.
- `.underline-focus` adds underline on `:focus`
- `.underline-hover` adds underline on `:hover`
- `.underline` adds underline to all states
### [`cursor`](modules/cursor.css)
- `.pointer` set `cursor` to `pointer` unless disabled
### [`pointer-events`](modules/pointer-events.css)
```css
.events-none { pointer-events: none }
.events-auto { pointer-events: auto }
```
### [`appearance`](modules/vendor.css)
- `.appearance-none` sets vendor appearance to `none` for custom styling
### [`resize`](modules/resize.css)
- `.resize-none`
- `.resize-both`
### [`transform`](modules/transform.css)
- `.-tx100` for `translateX(-100%)`
- `.-ty100` for `translateY(-100%)`
- `.tx0` for `translateX(0)`
- `.ty0` for `translateY(0)`
- `.tx100` for `translateX(100%)`
- `.ty100` for `translateY(100%)`
### [`animation`](modules/animation.css)
- `.anim-initial` resets `animation` to its `initial` values
- `.anim-reverse` reverses animation
- `.anim-seed` uses `backwards` fill mode
- `.anim-stay` uses `forwards` fill mode
- `.anim-fill` uses `both` fill mode
- `.anim-paused` pauses animation
- `.anim-infinite` animates for infinite iterations
- `.keyspeeds-spin` duration for spinner **iterating**
- `.keyframes-spin` rotate from `0deg` to `360deg` **iterating**
### [Presets](preset.css)
Presets provide partials for common needs. Presets load early such that other classes may override them.
- `.preset-box` box-model base
- `.preset-input` input base
- `.preset-textarea` textarea base
- `.preset-button` button base
## JavaScript API
We are developing a JavaScript API to help component developers reliably compose classes.
```
npm install @plangrid/structure
```
```js
const structure = require("@plangrid/structure");
```
[`structure`](structure.js) is a frozen [`cader`](https://github.com/ryanve/cader/tree/v0.7.0#cader) instance.
```js
structure.fuse("FontXL") // "family-os weight-semibold size-42px line-single"
structure.fuse("Tap") // "family-os preset-button fill-current pointer"
structure.fuse("Tap FontXL") // Unique fusion of both
structure.bond("FontXL another") // Unique bonding of saved atom(s) and unsaved atom(s)
structure.bond("FontXL m0 mb1") // "family-os weight-semibold size-42px line-single m0 mb1"
```
- `.bond` permits mixing atoms with external classes whereas `.fuse` is strictly atoms that have been saved
- Call `structure.help()` for help
- `.clone` is available for feature work
```js
const feature = structure.clone() // new instance contains saved structure atoms
feature.save({/* ... */}) // can save more atoms if unique from structure atoms
```
### Available atoms
#### [Font](#font) atoms
```js
structure.bond("FontC") // "font-os font-c"
structure.bond("FontB") // "font-os font-b"
structure.bond("FontXXS") // "font-os font-xxs"
structure.bond("FontXS") // "font-os font-xs"
structure.bond("FontS") // "font-os font-s"
structure.bond("FontM") // "font-os font-m"
structure.bond("FontL") // "font-os font-l"
structure.bond("FontXL") // "font-os font-xl"
```
#### [Border](#border) atoms
```js
structure.bond("ShelfMeld") // "sharp-shelf meld-shelf"
structure.bond("ShelfWeld") // "sharp-shelf weld-shelf"
structure.bond("StackMeld") // "sharp-stack meld-stack"
structure.bond("StackWeld") // "sharp-stack weld-stack"
```
#### [Overflow](#overflow) atoms
```js
structure.bond("TruncateBox") // "overflow-hidden overflow-dots ws-nowrap preset-box"
structure.bond("TruncateDIY") // "overflow-hidden overflow-dots ws-nowrap"
structure.bond("TruncateDIY width-fit") // max-width: 100%
structure.bond("PaneX") // "preset-box oy-hidden ox-auto"
structure.bond("PaneY") // "preset-box ox-hidden oy-auto"
structure.bond("PaneX PaneY") // both auto
```
- See [preset.css](preset.css) to see what `.preset-box` does
- `Pane` is meant to provide our standard scrolling behavior. TBD if we will standardize on `auto` or `scroll`
#### Shadow atoms
```js
structure.bond("FlatControl") // "shadow-ring"
structure.bond("RaiseControl") // "shadow-raised shadow-ring"
structure.bond("RaiseStatic") // "shadow-raised"
```
#### Control atoms
- `HF` = heavy frame
- `LF` = light frame
- `WIP` = work in progress
```js
structure.bond("UnderNone") // "underline-none"
structure.bond("UnderSome") // "underline-none underline-hover"
structure.bond("UnderAll") // "underline"
structure.bond("Ask") // structure.bond("FontB line-single preset-box block-table")
structure.bond("Cbox") // "font-os preset-button cbox"
structure.bond("Rdio") // "font-os preset-button rdio"
structure.bond("Field") // "font-os preset-box border-none"
structure.bond("Tactile") // "font-os preset-box block-table"
structure.bond("InputLF") // "font-os preset-input round-medium border"
structure.bond("InputHF") // structure.bond("InputLF frame-basic")
structure.bond("OpdownWIP") // structure.bond("PaneY round-medium RaiseControl")
structure.bond("OptionLF") // "overflow-hidden overflow-dots ws-nowrap preset-box font-os block"
structure.bond("OptionHF") // structure.bond("OptionLF font-b p1")
structure.bond("TapLF") // "font-os preset-button"
structure.bond("TapHF") // "font-os preset-button pointer"
structure.bond("TextareaLF") // "font-os preset-textarea round-medium border"
structure.bond("TextareaHF") // structure.bond("TextareaLF frame-basic")
structure.bond("PutLF") // "font-os preset-input round-medium border sharp-shelf weld-shelf"
structure.bond("PutHF") // structure.bond("PutLF frame-basic")
```
#### Unstable atoms
```js
structure.bond("Checkbox") // "font-os preset-button cbox shadow-raised shadow-ring tone-check"
structure.bond("Radio") // "font-os preset-button rdio shadow-raised shadow-ring tone-check"
```
#### Deprecated atoms
```js
structure.bond("Tap") // => structure.bond("TapLF")
structure.bond("Input") // => structure.bond("InputHF RaiseControl")
structure.bond("Textarea") // => structure.bond("TextareaHF RaiseControl")
structure.bond("Input:validate") // => structure.bond("InputHF RaiseControl tone-validate")
structure.bond("Input:validity") // => structure.bond("InputHF RaiseControl tone-validity")
structure.bond("Input:valid") // => structure.bond("InputHF RaiseControl tone-valid")
structure.bond("Input:invalid") // => structure.bond("InputHF RaiseControl tone-invalid")
structure.bond("Textarea:validate") // => structure.bond("TextareaHF RaiseControl tone-validate")
structure.bond("Textarea:validity") // => structure.bond("TextareaHF RaiseControl tone-validity")
structure.bond("Textarea:valid") // => structure.bond("TextareaHF RaiseControl tone-valid")
structure.bond("Textarea:invalid") // => structure.bond("TextareaHF RaiseControl tone-invalid")
structure.bond("Button:secondary")
structure.bond("Button:primary")
structure.bond("Button:additive")
structure.bond("Button:destructive")
structure.bond("Secondary")
structure.bond("Primary")
structure.bond("Additive")
structure.bond("Destructive")
structure.bond("Button:link")
structure.bond("Button:icon")
```
## Questions?
Ask in our <b>#css</b> slack channel :)
## Developer commands
```
npm install
npm start
npm test
```