Skip to content

Commit c63ce59

Browse files
shawnbotJackson Flint-Gonzaleslaurenajong
authored
Release 2.4.0 (#92)
* 2.4.0 * fix(heroku): build with NODE_ENV=production * Add CSS utilities listing (#88) * 2.2.0 * Add CodePen edit links to examples (#50) * add CodePen links to all live examples * simplify * reposition CodePen link w/pencil icon * nix .relative from example container * rewrap codepen link in template conditional * add margin to prevent overlap of kbd elements when stacked (#48) * add margin to prevent overlap of kbd elements when stacked * additional example to illustrate wrap behavior * remove old kbd component, move into the markdown file * move data stories text out of code example * use spacing between kbd elements and update implementation suggestions Co-authored-by: Shawn Allen <[email protected]> * fix additional instances of kbd margins * update docs to use mix of space and margin utilities * apply spacing Co-authored-by: Shawn Allen <[email protected]> * docs: add subtitle and see_also links to title template * chore(docs): make css usage docs a directory * fix(docs): make color swatches inline-flex * fix(docs): add bg-white to TOC * feat(docs): add global "utilites" data * feat(docs): add get_path template filter * feat(docs): add CSS utilities page * docs(utilities): add more utility listings * docs(utilities): update intro para Co-authored-by: Jackson Flint-Gonzales <[email protected]> * Lint CSS; add expiring-todo-comments rules for JS + CSS (#55) * chore(deps): install eslint-plugin-unicorn * chore(lint): update deprecation comments to unicorn style * chore(lint): enable unicorn/expiring-todo-comments * chore(css): add todo comments for focus tweaks * chore(lint): install and set up stylelint * chore(lint): fix up stylelint errors * chore(deps): install semver * lint(css): tweak expiring todo comment version ranges (">=" instead of "^") * lint(css): add local/expiring-todo-comments rule * lint(js): fix up todo version comments * chore(deps): upgrade to [email protected] * chore(lint): stylelint --fix * feat(tokens): add colors.grey.focus * chore(lint): set allowWarningComments: true * chore(lint): whitespace * fix(lint): only shellcheck scripts/*.sh * Lint markdown (#56) * lint(markdown): install markdownlilnt-cli * lint(markdown): add "lint-docs" npm script, et al * lint(markdown): add markdownlint config, custom frontmatter rule * lint(docs): lint whitespace, headings * lint(ci): add markdownlint problem matcher * chore(lint): test markdownlint problem matcher * chore(lint): add some lines to bad markdown * lint(markdown): tweak frontmatter error output * lint(markdown): add no-empty rule, tag our rules as "local" * lint(markdown): fix up resources landing page (placeholder) * chore(lint): npm run lint-docs -- --fix * fix: nix lint-css script (not yet implemented) * fix(scripts): remove lint-css from run-p list (not yet implemented) * Extract Tailwind preset (#87) * chore(build): nix purge option from tailwind config * chore(deps): move tailwind-interaction-variants to dependencies * chore(browserslist): run browserslist --update-db * feat(tailwind): add tailwind preset * feat(tailwind): use tailwind preset in our config * chore: delete redundant comment * chore(tailwind): move corePlugins + variants to tailwind.theme * fix(deps): move tailwindcss to dependencies * fix(npm): add lib/tailwind to package files * fix(npm): include tailwind.preset.js * Editing buttons docs (#79) * Testing editing buttons docs * Added text from google doc * Added images + small tweaks * Trying a real button * removing image * update content to match google doc * chore(docs): reduce noise in github API errors * feat(docs): add docs/static/images * fix(docs): rebuild package-lock.json * fix(docs): safelist table[class=w-full] for styling * chore(docs): add get/setAttribute() remark helpers * chore(docs): reduce noise when version status fails * feat(docs): update button docs Co-authored-by: laurenajong <[email protected]> * feat(docs): add basic yes/no table styling * feat(tokens): add 12 + "full" to spacing * feat(theme): add full (100%) to borderRadius * chore(docs): add more spacing around button examples * fix(docs): add icons to yes/no examples * chore(docs): more consistent line breaks * fix(heroku): create a review app on pr label * fix(docs): add alt="" to decorative img Co-authored-by: Jackson Flint-Gonzales <[email protected]> * chore(lint): nuke hanging spaces * chore(docs): delete icon-example.png reference design * fix(docs): add empty link listener to prevent scrolling * fix(docs): fix bad merge Co-authored-by: Shawn Allen <[email protected]> Co-authored-by: laurenajong <[email protected]> Co-authored-by: Jackson Flint-Gonzales <[email protected]> * Update color values from Figma (#97) * fix(tokens): update color values from Figma Saved as v2.4.1 in https://www.figma.com/file/PztEA9PIX00czGHf68Gsr5/?node-id=0%3A1 * chore(lint): fix spaces * Release 2.4.0 fixes (#93) * Editing buttons docs (#79) * Testing editing buttons docs * Added text from google doc * Added images + small tweaks * Trying a real button * removing image * update content to match google doc * chore(docs): reduce noise in github API errors * feat(docs): add docs/static/images * fix(docs): rebuild package-lock.json * fix(docs): safelist table[class=w-full] for styling * chore(docs): add get/setAttribute() remark helpers * chore(docs): reduce noise when version status fails * feat(docs): update button docs Co-authored-by: laurenajong <[email protected]> * feat(docs): add basic yes/no table styling * feat(tokens): add 12 + "full" to spacing * feat(theme): add full (100%) to borderRadius * chore(docs): add more spacing around button examples * fix(docs): add icons to yes/no examples * chore(docs): more consistent line breaks * fix(heroku): create a review app on pr label * fix(docs): add alt="" to decorative img Co-authored-by: Jackson Flint-Gonzales <[email protected]> * chore(lint): nuke hanging spaces * chore(docs): delete icon-example.png reference design * fix(docs): add empty link listener to prevent scrolling * fix(docs): fix bad merge Co-authored-by: Shawn Allen <[email protected]> Co-authored-by: laurenajong <[email protected]> Co-authored-by: Jackson Flint-Gonzales <[email protected]> * fix(develop): move watching logic out of .eleventy.js * chore(lint): line breaks * docs(tailwind): cross-reference css pages * docs(tailwind): add tailwind usage docs * chore(lint): fix heading levels in Tailwind docs Co-authored-by: laurenajong <[email protected]> Co-authored-by: laurenajong <[email protected]> Co-authored-by: Jackson Flint-Gonzales <[email protected]> Co-authored-by: Jackson Flint-Gonzales <[email protected]> Co-authored-by: laurenajong <[email protected]> Co-authored-by: laurenajong <[email protected]>
1 parent 7448ff1 commit c63ce59

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3595
-2094
lines changed

.eleventy.js

+1-14
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,6 @@ const toc = require('./lib/eleventy/toc')
1111
const { environment } = require('./lib/nunjucks')
1212

1313
module.exports = config => {
14-
if (dev) {
15-
const throttle = 100
16-
const reloadOnChange = require('./lib/eleventy/reload')
17-
reloadOnChange(__filename, [
18-
'lib/**/*.js',
19-
// we need to watch these ones explicitly because they
20-
// change how examples and color swatches are rendered
21-
'docs/_includes/{example,macros}.njk'
22-
], throttle)
23-
24-
// throttle subsequent rebuilds
25-
config.setWatchThrottleWaitTime(throttle)
26-
}
27-
2814
config.addPlugin(navigation)
2915
config.addPlugin(remark, remarkConfig)
3016
config.addPlugin(toc, {
@@ -38,6 +24,7 @@ module.exports = config => {
3824
config.setUseGitIgnore(false)
3925
config.addWatchTarget('./dist')
4026
config.addPassthroughCopy('dist')
27+
config.addPassthroughCopy('docs/static')
4128

4229
return {
4330
dir: {

.eslintrc.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
module.exports = {
22
parser: '@babel/eslint-parser',
3-
plugins: ['sfgov'],
3+
plugins: [
4+
'sfgov',
5+
'unicorn'
6+
],
47
extends: [
58
'plugin:sfgov/recommended'
69
],
710
rules: {
11+
'unicorn/expiring-todo-comments': ['error', {
12+
allowWarningComments: true
13+
}]
814
},
915
overrides: [
1016
{
11-
files: ['src/js/*.js', 'src/icons/index.js'],
17+
files: ['src/**/*.js'],
1218
env: {
1319
browser: true
1420
},

.github/workflows/ci.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ jobs:
1010
with:
1111
node-version: 14
1212
cache: npm
13-
1413
- run: npm ci
14+
15+
- uses: xt0rted/markdownlint-problem-matcher@v1
1516
- run: npm run lint
1617

1718
# this sets NODE_ENV=production for all of the build scripts

.markdownlint.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
default: false
2+
heading-increment: true
3+
heading-style: atx
4+
first-heading-h1: { level: 2 }
5+
front-matter:
6+
required_keys:
7+
- title
8+
line-length: false
9+
links: true
10+
list-indent: true
11+
no-bare-urls: false
12+
no-empty: true
13+
ul-indent: { indent: 2, start_indented: false }
14+
ul-style: consistent
15+
whitespace: true

.stylelintrc.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module.exports = {
2+
extends: [
3+
'stylelint-config-standard'
4+
],
5+
plugins: [
6+
'./lib/stylelint/expiring-todo-comments'
7+
],
8+
rules: {
9+
'at-rule-no-unknown': [true, {
10+
ignoreAtRules: [
11+
'apply',
12+
'layer',
13+
'responsive',
14+
'screen',
15+
'tailwind',
16+
'variants'
17+
]
18+
}],
19+
'local/expiring-todo-comments': [true, {
20+
}],
21+
'string-quotes': 'single'
22+
}
23+
}

docs/_data/eleventyComputed.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ function getLastCommitFromGit (path) {
4444
}
4545

4646
async function getLastCommitFromGitHub (path) {
47+
if (process.env.NODE_ENV === 'development') return null
48+
4749
const args = { ...context, path, sha: branch, per_page: 1 }
4850

4951
// console.info('getting last commit from github:', args)
@@ -53,7 +55,7 @@ async function getLastCommitFromGitHub (path) {
5355
res = await github.rest.repos.listCommits(args)
5456
commits = res.data
5557
} catch (error) {
56-
console.warn('error loading commits for "%s"', path, error)
58+
console.warn('error loading commits for "%s"', path)
5759
gitMetaCache.set(path, null)
5860
return null
5961
}
@@ -71,7 +73,7 @@ async function getLastCommitFromGitHub (path) {
7173
// console.info('caching git meta for "%s"', path, meta)
7274
return meta
7375
} else {
74-
console.warn('unable to get commit for "%s"', path, res)
76+
console.warn('unable to get commit for "%s"', path)
7577
return null
7678
}
7779
}

docs/_data/examples.js

-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,5 @@ async function getExamples () {
3232
})
3333
}
3434

35-
3635
return examples
3736
}

docs/_data/package.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ async function getPublishedStatusVersion () {
3030
console.warn('no published version status for %s', sha, statuses)
3131
}
3232
} catch (error) {
33-
console.warn('unable to get published version status:', error)
33+
console.warn('unable to get published version status:', error.message)
3434
}
3535
}

docs/_data/utilities.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const postcss = require('postcss')
2+
const { readFileSync } = require('fs')
3+
4+
const UTILITY_SELECTOR_PATTERN = /^\.[-:\w]+$/
5+
6+
module.exports = function getUtilities () {
7+
const css = readFileSync('dist/css/utilities.css', 'utf8')
8+
const root = postcss.parse(css)
9+
/** @type [postcss.Declaration] */
10+
const decls = []
11+
root.walkRules(rule => {
12+
if (UTILITY_SELECTOR_PATTERN.test(rule.selector)) {
13+
rule.walkDecls((decl, index) => {
14+
decls.push(decl)
15+
})
16+
}
17+
})
18+
19+
return {
20+
decls,
21+
byClassname: Object.fromEntries(
22+
decls.map(decl => [
23+
decl.parent.selector.substring(1),
24+
decl
25+
])
26+
),
27+
byProperty: groupBy(
28+
decls,
29+
decl => decl.prop
30+
)
31+
}
32+
}
33+
34+
function groupBy (list /** @type [any] */, keyFunction /** type Function */) {
35+
return list.reduce((map, d, i) => {
36+
const key = keyFunction(d, i)
37+
if (key in map) map[key].push(d)
38+
else map[key] = [d]
39+
return map
40+
}, {})
41+
}

docs/_includes/toc.njk

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<nav
2-
class="sticky top-0 pl-16 py-4 border-0 border-l-2 border-solid border-slate"
2+
class="sticky top-0 pl-16 py-4 bg-white border-0 border-l-2 border-solid border-slate"
33
aria-hidden="true"
44
>
55
{% if title %}

docs/components/buttons.md

+160-8
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,190 @@
11
---
22
title: Buttons
33
---
4+
Use buttons for major actions.
45

5-
## Link buttons
6+
Buttons draw more attention than a simple text link. Because of their larger surface and color, they are visually more findable and easier to click or tap.
67

7-
This is some text about link buttons. We should explain why we want links to
8-
look like buttons.
8+
## When to use
9+
10+
Use a button when an action has more weight or significance. Examples:
11+
12+
* There is a clear primary action people should take
13+
* Highlighting a suggested action in a page section
14+
* A significant or destructive action will be applied and users need to be aware
15+
16+
If the action should not be prompted, a text link may be a better option.
17+
18+
## Types of buttons
19+
20+
### Primary button
21+
22+
This is the most common type of button. Use these to direct people to a clear primary action. To call out that these buttons are actionable, they are action blue (`{{ tokens.colors.action }}`).
23+
24+
```html
25+
<button class="btn">
26+
Do something
27+
</button>
28+
```
29+
30+
Try not to have more than 1 primary button on a page. Multiple primary buttons puts more cognitive load on people. It takes them more time and effort to figure out what to do.
31+
32+
### Inverse button
33+
34+
On some backgrounds, the primary button color will not have sufficient contrast. In this case, use inverse buttons, which have a white fill.
35+
36+
```html wrapper_class="bg-blue-dark p-20"
37+
<div class="bg-blue-dark">
38+
<button class="btn btn-inverse">
39+
Do something
40+
</button>
41+
</div>
42+
```
43+
44+
### Secondary button
45+
46+
```html
47+
<button class="btn btn-secondary">
48+
Do something
49+
</button>
50+
```
51+
52+
Secondary buttons don’t have as much visual weight because they are outlined instead of solid. Use these if your button is not an important action on the page.
53+
54+
Pair it side-by-side with a primary button to prompt toward the primary button’s action.
55+
56+
```html id="buttons-side-by-side"
57+
<div class="flex gap-20">
58+
<button class="btn btn-secondary">
59+
Cancel
60+
</button>
61+
<button class="btn">
62+
Continue
63+
</button>
64+
</div>
65+
```
66+
67+
## Variations
68+
69+
### Block buttons
70+
71+
Block buttons stretch to fill the width of the screen or area instead of having a set width. They are often used on mobile layouts.
72+
73+
```html
74+
<div class="bg-blue-1 p-20 text-slate text-body">
75+
<div>COVID-19 vaccination appointments available only for San Francisco Health Network patients.</div>
76+
<button class="btn btn-block my-20">
77+
Check for availability
78+
</button>
79+
<div class="text-center">
80+
Or call <a href="tel:1234567890" class="text-action">123-456-7890</a>
81+
</div>
82+
</div>
83+
```
84+
85+
### Icons
86+
87+
Icons can be on the left or right of the text in a button. Do not use more than one icon in a button.
88+
89+
```html
90+
<div class="flex justify-around items-center gap-16 title-xs">
91+
<a href="#" class="btn btn-secondary flex gap-8">
92+
<sfgov-icon symbol="arrow-left"></sfgov-icon>
93+
<span>Previous</span>
94+
</a>
95+
<a href="#" class="text-action">1</a>
96+
<span>...</span>
97+
<a href="#" class="text-action">8</a>
98+
<a href="#" class="text-action">9</a>
99+
<span>10</span>
100+
<a href="#" class="text-action">11</a>
101+
<a href="#" class="btn btn-secondary flex gap-8">
102+
<span>Next</span>
103+
<sfgov-icon symbol="arrow-right"></sfgov-icon>
104+
</a>
105+
</div>
106+
```
107+
108+
Icons should reinforce the meaning of the button’s text. In rare cases, an icon can be used without text. Only do this if the icon is extremely universally understood, such as an arrow or search magnifying glass. [Read more about icons](/foundations/icons/)
109+
110+
## Appearance
111+
112+
<img alt="" src="/static/images/button-specs.png" class="w-full">
113+
114+
Buttons have:
115+
* corner radius of 8px
116+
* 8px padding on the top and bottom
117+
* 20px padding left and right, but can be variable on block buttons
118+
* Body Bold text
119+
120+
## Usage
121+
122+
### Alignment
123+
124+
Buttons are typically left aligned with other content, not centered. For exceptions, see <a href="#block-buttons">block buttons</a>.
125+
126+
| <img class="w-1/1" alt="Left aligned button with left aligned text" src="/static/images/alignment-correct.png"> | <img class="w-1/1" alt="Center aligned button with left aligned text" src="/static/images/alignment-incorrect.png"> |
127+
| ----------- | ----------- |
128+
| Yes | No |
129+
| Button is left aligned with other content | Button is centered |
130+
131+
### Arrangement of multiple buttons
132+
133+
For 2 or more button options, place them side by side instead of on top of one another if possible. This reduces the chance of accidentally clicking the wrong one and avoids alignment issues.
134+
135+
| <div class="flex gap-20"><button class="btn btn-secondary">Cancel</button><button class="btn">Continue</button></div> | <div><button class="btn btn-secondary mb-20">Cancel</button><br><button class="btn mb-20">Continue</button></div> |
136+
| ----------- | ----------- |
137+
| Yes | No |
138+
| Choices are side by side | Choices are stacked |
139+
140+
### Writing button text
141+
142+
Button text should ideally be less than 15 characters. A maximum of 25 characters is OK if necessary.
143+
144+
Refer to the [button text library](https://sfgovdt.jira.com/wiki/spaces/SFGOV/pages/3221651460/Button+text+library) for common button uses.
145+
146+
Long button text is less legible, less impactful, and sometimes can even cause wrapping.
147+
148+
| <button class="btn mb-48">Apply now</button> | <button class="btn mb-48">Apply now for your Small Business Grant</button> |
149+
| ----------- | ----------- |
150+
| Yes | No |
151+
| Button text is short | Button text is very long |
152+
153+
| <button class="btn mb-20">Apply now</button> | <button class="btn mb-20">Apply now for your<br>Small Business Grant</button> |
154+
| ----------- | ----------- |
155+
| Yes | No |
156+
| Button text fits on one line | Button text wraps to fit |
157+
158+
## HTML implementation
159+
160+
Buttons styles can be applied to both HTML links (`<a>` elements) and interactive buttons (`<button>`).
161+
162+
### Link buttons
9163

10-
### Inline link
11164
```html
12165
<a class="btn" href="#">
13166
This is a link
14167
</a>
15168
```
16169

17170
### Block link
171+
18172
```html
19173
<a class="btn btn-block" href="#">
20174
This is a block link
21175
</a>
22176
```
23177

24-
## HTML buttons
25-
26-
This is some text about actual styling actual `<button>` elements.
178+
### HTML buttons
27179

28-
### Inline button
29180
```html
30181
<button class="btn">
31182
This is a button
32183
</button>
33184
```
34185

35186
### Block button
187+
36188
```html
37189
<button class="btn btn-block">
38190
This is a block button

0 commit comments

Comments
 (0)