├── .changeset ├── README.md ├── beige-files-move.md ├── chilled-dragons-sin.md ├── config.json ├── quiet-otters-care.md ├── rude-ears-tie.md └── strange-buckets-count.md ├── .eslintrc.json ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── primer-bug-report.md │ ├── primer-feature-request.md │ └── style-guide-bug-report.md ├── dependabot.yml ├── pull_request_template.md ├── release_template.md └── workflows │ ├── axe.yml │ ├── ci.yml │ ├── codeql.yml │ ├── deploy_preview.yml │ ├── deploy_production.yml │ ├── next_major.yml │ ├── release.yml │ ├── release_canary.yml │ ├── release_candidate.yml │ ├── stale.yml │ └── welcome.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .vercelignore ├── .vscode └── story-template.code-snippets ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DEVELOP.md ├── LICENSE ├── README.md ├── RELEASING.md ├── __tests__ ├── .eslintrc.json ├── build.test.js ├── css.test.js ├── docs.test.js └── utils │ ├── css.js │ └── docs.js ├── deprecations.js ├── docs ├── .babelrc ├── .eslintrc.json ├── .storybook │ ├── main.js │ ├── preview-head.html │ └── preview.js ├── content │ ├── components │ │ ├── action-list.md │ │ ├── alerts.md │ │ ├── autocomplete.md │ │ ├── avatars.md │ │ ├── blankslate.md │ │ ├── box-overlay.md │ │ ├── box.md │ │ ├── branch-name.md │ │ ├── breadcrumb.md │ │ ├── buttons.md │ │ ├── dialog.md │ │ ├── dropdown.md │ │ ├── forms.md │ │ ├── header.md │ │ ├── index.md │ │ ├── labels.md │ │ ├── layout.md │ │ ├── links.md │ │ ├── loaders.md │ │ ├── markdown.md │ │ ├── marketing-buttons.md │ │ ├── marketing-links.md │ │ ├── navigation.md │ │ ├── pagination.md │ │ ├── popover.md │ │ ├── progress.md │ │ ├── select-menu-deprecated.md │ │ ├── select-menu.md │ │ ├── subhead.md │ │ ├── timeline.md │ │ ├── toasts.md │ │ ├── tooltips.md │ │ └── truncate.md │ ├── getting-started │ │ ├── contributing.md │ │ └── index.md │ ├── index.mdx │ ├── marketing │ │ └── index.md │ ├── principles │ │ ├── accessibility.md │ │ ├── html.md │ │ ├── index.md │ │ └── scss.md │ ├── stickersheet │ │ ├── index.md │ │ ├── labels.md │ │ └── sizes.md │ ├── support │ │ ├── breakpoints.md │ │ ├── index.md │ │ ├── spacing.md │ │ ├── theming.md │ │ ├── typography.md │ │ ├── v16-migration.mdx │ │ ├── v18-migration.mdx │ │ └── variables.mdx │ ├── tools │ │ ├── deprecations.md │ │ ├── index.md │ │ ├── linting.md │ │ ├── prototyping.md │ │ └── testing.md │ └── utilities │ │ ├── animations.md │ │ ├── borders.mdx │ │ ├── box-shadow.md │ │ ├── colors.mdx │ │ ├── details.md │ │ ├── flexbox.md │ │ ├── grid.md │ │ ├── index.md │ │ ├── layout.md │ │ ├── margin.md │ │ ├── marketing-filters.md │ │ ├── marketing-layout.md │ │ ├── marketing-type.md │ │ ├── padding.md │ │ └── typography.md ├── gatsby-browser.js ├── gatsby-config.js ├── gatsby-node.js ├── package.json ├── postcss.config.js ├── script │ └── build-storybook ├── src │ ├── @primer │ │ └── gatsby-theme-doctocat │ │ │ ├── components │ │ │ ├── hero.js │ │ │ └── live-preview-wrapper.js │ │ │ └── nav.yml │ ├── color-image.svg │ ├── color-system.js │ ├── color-variables.js │ ├── components-image.svg │ ├── hero-illustration.svg │ ├── objects-image.svg │ ├── readme.png │ ├── spacing-image.svg │ ├── stories │ │ ├── GettingStarted.stories.mdx │ │ ├── components │ │ │ ├── ActionList │ │ │ │ ├── ActionList.stories.jsx │ │ │ │ ├── ActionListDivider.stories.jsx │ │ │ │ ├── ActionListDividerFeatures.stories.jsx │ │ │ │ ├── ActionListExamples.stories.jsx │ │ │ │ ├── ActionListFeatures.stories.jsx │ │ │ │ ├── ActionListItem.stories.jsx │ │ │ │ └── ActionListItemFeatures.stories.jsx │ │ │ ├── Button │ │ │ │ ├── Button.stories.jsx │ │ │ │ └── ButtonFeatures.stories.jsx │ │ │ ├── Dialog │ │ │ │ └── Dialog.stories.jsx │ │ │ ├── Forms │ │ │ │ ├── Checkbox.stories.jsx │ │ │ │ ├── Fieldset.stories.jsx │ │ │ │ ├── FormGroup.stories.jsx │ │ │ │ ├── Input.stories.jsx │ │ │ │ ├── Radio.stories.jsx │ │ │ │ ├── Select.stories.jsx │ │ │ │ └── Textarea.stories.jsx │ │ │ ├── Label │ │ │ │ ├── IssueLabel.stories.jsx │ │ │ │ ├── Label.stories.jsx │ │ │ │ ├── LabelCounter.stories.jsx │ │ │ │ ├── LabelDiffstat.stories.jsx │ │ │ │ ├── LabelFeatures.stories.jsx │ │ │ │ ├── LabelStates.stories.jsx │ │ │ │ └── LabelStatesFeatures.stories.jsx │ │ │ ├── Layout │ │ │ │ ├── AppFrame.stories.jsx │ │ │ │ ├── LayoutAlpha.stories.jsx │ │ │ │ ├── LayoutBeta.stories.jsx │ │ │ │ ├── LayoutExamples.stories.jsx │ │ │ │ ├── PageLayout.stories.jsx │ │ │ │ ├── SplitPageLayout.stories.jsx │ │ │ │ ├── Stack.stories.jsx │ │ │ │ ├── StackExamples.stories.jsx │ │ │ │ └── StackFeatures.stories.jsx │ │ │ ├── Link │ │ │ │ └── Link.stories.jsx │ │ │ ├── Marketing │ │ │ │ ├── MarketingButton.stories.jsx │ │ │ │ └── MarketingLink.stories.jsx │ │ │ ├── Navigation │ │ │ │ ├── TabNav.stories.jsx │ │ │ │ ├── TabNavItem.stories.jsx │ │ │ │ ├── UnderlineNav.stories.jsx │ │ │ │ ├── UnderlineNavAction.stories.jsx │ │ │ │ ├── UnderlineNavItem.stories.jsx │ │ │ │ └── UnderlineNavPatterns.stories.jsx │ │ │ ├── NavigationList │ │ │ │ ├── NavigationList.stories.jsx │ │ │ │ ├── NavigationListDivider.stories.jsx │ │ │ │ ├── NavigationListDividerFeatures.stories.jsx │ │ │ │ ├── NavigationListExamples.stories.jsx │ │ │ │ ├── NavigationListFeatures.stories.jsx │ │ │ │ ├── NavigationListItem.stories.jsx │ │ │ │ ├── NavigationListItemCollapsible.stories.jsx │ │ │ │ ├── NavigationListItemCollapsibleFeatures.stories.jsx │ │ │ │ └── NavigationListItemFeatures.stories.jsx │ │ │ ├── ToggleSwitch │ │ │ │ └── ToggleSwitch.stories.jsx │ │ │ └── TreeView │ │ │ │ └── TreeView.stories.jsx │ │ ├── helpers │ │ │ ├── ColorBlock.jsx │ │ │ ├── ConditionalWrapper.jsx │ │ │ ├── code-snippet-html-helper.js │ │ │ ├── pageLayoutBehavior.jsx │ │ │ ├── storybook-styles.scss │ │ │ └── useToggle.jsx │ │ ├── patterns │ │ │ └── FocusStyles.stories.jsx │ │ ├── playground │ │ │ ├── ColorPlayground.stories.jsx │ │ │ ├── Playground.stories.jsx │ │ │ └── Prototyping.stories.mdx │ │ ├── rails-form-framework │ │ │ ├── Checkbox.stories.jsx │ │ │ ├── Radio.stories.jsx │ │ │ ├── RadioFeatures.stories.jsx │ │ │ ├── Select.stories.jsx │ │ │ ├── TextInput.stories.jsx │ │ │ └── Textarea.stories.jsx │ │ └── ui-patterns │ │ │ ├── ActionList │ │ │ ├── API.stories.mdx │ │ │ ├── ActionList.stories.jsx │ │ │ ├── ActionListDivider.stories.jsx │ │ │ ├── ActionListDividerFeatures.stories.jsx │ │ │ ├── ActionListFeatures.stories.jsx │ │ │ ├── ActionListItem.stories.jsx │ │ │ ├── ActionListItemCollapsible.stories.jsx │ │ │ ├── ActionListItemCollapsibleFeatures.stories.jsx │ │ │ ├── ActionListItemFeatures.stories.jsx │ │ │ ├── ActionListTree.stories.jsx │ │ │ ├── ActionListTreeFeatures.stories.jsx │ │ │ └── uipatterns.stories.mdx │ │ │ └── Overlay │ │ │ └── Overlay.stories.jsx │ ├── table.js │ ├── typography-image.png │ ├── utilities-image.svg │ └── variables.js └── yarn.lock ├── package.json ├── postcss.config.cjs ├── prettier.config.cjs ├── script ├── .eslintrc.json ├── analyze-variables.js ├── axe-docs ├── build-css.js ├── build-docs ├── bundle-size-report.js ├── dist.js ├── prepublish ├── pretest ├── primer-css-compiler.js ├── selector-diff-report ├── stylelint-add-disables.js └── stylelint-remove-disables.js ├── src ├── actionlist │ ├── action-list-item-divider.scss │ ├── action-list-item.scss │ ├── action-list-tree.scss │ ├── action-list-variables.scss │ ├── action-list.scss │ └── index.scss ├── alerts │ ├── README.md │ ├── flash.scss │ └── index.scss ├── autocomplete │ ├── README.md │ ├── autocomplete.scss │ ├── index.scss │ └── suggester.scss ├── avatars │ ├── README.md │ ├── avatar-parent-child.scss │ ├── avatar-stack.scss │ ├── avatar.scss │ ├── circle-badge.scss │ └── index.scss ├── base │ ├── README.md │ ├── base.scss │ ├── index.scss │ ├── kbd.scss │ ├── normalize.scss │ ├── octicons.scss │ └── typography-base.scss ├── blankslate │ ├── README.md │ ├── blankslate.scss │ └── index.scss ├── box │ ├── README.md │ ├── box-overlay.scss │ ├── box.scss │ └── index.scss ├── branch-name │ ├── README.md │ ├── branch-name.scss │ └── index.scss ├── breadcrumb │ ├── README.md │ ├── breadcrumb.scss │ └── index.scss ├── buttons │ ├── README.md │ ├── button-group.scss │ ├── button.scss │ ├── index.scss │ └── misc.scss ├── color-modes │ ├── index.scss │ ├── native.scss │ └── themes │ │ ├── dark.scss │ │ ├── dark_colorblind.scss │ │ ├── dark_dimmed.scss │ │ ├── dark_high_contrast.scss │ │ ├── dark_tritanopia.scss │ │ ├── light.scss │ │ ├── light_colorblind.scss │ │ ├── light_high_contrast.scss │ │ └── light_tritanopia.scss ├── core │ ├── README.md │ └── index.scss ├── deprecations.json ├── docs.scss ├── dropdown │ ├── README.md │ ├── dropdown.scss │ └── index.scss ├── forms │ ├── FormControl.scss │ ├── README.md │ ├── form-control.scss │ ├── form-group.scss │ ├── form-select.scss │ ├── form-validation.scss │ ├── index.scss │ ├── input-group.scss │ └── radio-group.scss ├── header │ ├── README.md │ ├── header.scss │ └── index.scss ├── index.scss ├── labels │ ├── README.md │ ├── counters.scss │ ├── diffstat.scss │ ├── index.scss │ ├── issue-labels.scss │ ├── labels.scss │ ├── mixins.scss │ └── states.scss ├── layout │ ├── README.md │ ├── app-frame.scss │ ├── container.scss │ ├── grid-offset.scss │ ├── grid.scss │ ├── index.scss │ ├── layout.scss │ ├── mixins.scss │ ├── page-layout.scss │ └── stack.scss ├── links │ ├── README.md │ ├── index.scss │ └── link.scss ├── loaders │ ├── README.md │ ├── index.scss │ └── loaders.scss ├── markdown │ ├── README.md │ ├── blob-csv.scss │ ├── code.scss │ ├── footnotes.scss │ ├── headings.scss │ ├── images.scss │ ├── index.scss │ ├── lists.scss │ ├── markdown-body.scss │ └── tables.scss ├── marketing │ ├── README.md │ ├── buttons │ │ ├── button.scss │ │ └── index.scss │ ├── index.scss │ ├── links │ │ ├── index.scss │ │ └── link.scss │ ├── support │ │ ├── index.scss │ │ └── variables.scss │ ├── type │ │ ├── index.scss │ │ └── typography.scss │ └── utilities │ │ ├── animations.scss │ │ ├── borders.scss │ │ ├── filters.scss │ │ ├── index.scss │ │ └── layout.scss ├── navigation │ ├── README.md │ ├── filter-list.scss │ ├── index.scss │ ├── menu.scss │ ├── sidenav.scss │ ├── subnav.scss │ ├── tabnav.scss │ └── underline-nav.scss ├── overlay │ ├── README.md │ ├── index.scss │ └── overlay.scss ├── pagination │ ├── README.md │ ├── index.scss │ └── pagination.scss ├── popover │ ├── README.md │ ├── index.scss │ └── popover.scss ├── primitives │ └── index.scss ├── product │ ├── README.md │ └── index.scss ├── progress │ ├── README.md │ ├── index.scss │ └── progress.scss ├── select-menu │ ├── README.md │ ├── index.scss │ └── select-menu.scss ├── subhead │ ├── README.md │ ├── index.scss │ └── subhead.scss ├── support │ ├── README.md │ ├── index.scss │ ├── mixins │ │ ├── color-modes.scss │ │ ├── layout.scss │ │ ├── misc.scss │ │ └── typography.scss │ └── variables │ │ ├── layout.scss │ │ ├── misc.scss │ │ └── typography.scss ├── table-object │ ├── index.scss │ └── table-object.scss ├── timeline │ ├── README.md │ ├── index.scss │ └── timeline-item.scss ├── toasts │ ├── README.md │ ├── index.scss │ └── toasts.scss ├── toggle-switch │ ├── index.scss │ └── toggle-switch.scss ├── tooltips │ ├── README.md │ ├── index.scss │ └── tooltips.scss ├── truncate │ ├── README.md │ ├── index.scss │ └── truncate.scss └── utilities │ ├── README.md │ ├── animations.scss │ ├── borders.scss │ ├── box-shadow.scss │ ├── colors.scss │ ├── details.scss │ ├── flexbox.scss │ ├── index.scss │ ├── layout.scss │ ├── margin.scss │ ├── padding.scss │ ├── typography.scss │ └── visibility-display.scss ├── stylelint.config.cjs └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/beige-files-move.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@primer/css": patch 3 | --- 4 | 5 | Add upper-roman and upper-alpha list types 6 | -------------------------------------------------------------------------------- /.changeset/chilled-dragons-sin.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@primer/css": patch 3 | --- 4 | 5 | Bugfix: Adding `white-space: normal` to Overlay compontn to reset wrapping. 6 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.5.0/schema.json", 3 | "changelog": ["@changesets/changelog-github", {"repo": "primer/css"}], 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "main", 8 | "updateInternalDependencies": "patch", 9 | "ignore": [] 10 | } 11 | -------------------------------------------------------------------------------- /.changeset/quiet-otters-care.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@primer/css": patch 3 | --- 4 | 5 | Increase Checkbox/Radio border contrast 6 | 7 | -------------------------------------------------------------------------------- /.changeset/rude-ears-tie.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@primer/css": patch 3 | --- 4 | 5 | [Bug] Radio checked + focus state fixes 6 | -------------------------------------------------------------------------------- /.changeset/strange-buckets-count.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@primer/css": patch 3 | --- 4 | 5 | Update dropdown hover selector 6 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaVersion": "latest" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @primer/css-reviewers 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/primer-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Primer CSS bug report 3 | about: Create a report to help us improve Primer CSS 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/primer-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Primer CSS feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/style-guide-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Style guide bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # Maintain dependencies for GitHub Actions 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "monthly" 13 | 14 | # Maintain dependencies for npm 15 | - package-ecosystem: "npm" 16 | directory: "/" 17 | schedule: 18 | interval: "monthly" 19 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### What are you trying to accomplish? 2 | 3 | 4 | 5 | ### What approach did you choose and why? 6 | 7 | 8 | 9 | ### What should reviewers focus on? 10 | 11 | 12 | 13 | ### Can these changes ship as is? 14 | 15 | 16 | 17 | - [ ] Yes, this PR does not depend on additional changes. 🚢 18 | -------------------------------------------------------------------------------- /.github/release_template.md: -------------------------------------------------------------------------------- 1 | Preparing for a release. 2 | 3 | ### Checklist 4 | 5 | Make sure these items are checked before merging. 6 | 7 | - [ ] Preview the docs change. 8 | - [ ] Preview npm release candidate. 9 | - [ ] CI passes on the release PR. 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/axe.yml: -------------------------------------------------------------------------------- 1 | name: axe 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | axe: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 16 | - name: Get changed files 17 | id: changed-files 18 | uses: tj-actions/changed-files@v34 19 | with: 20 | files: | 21 | docs/content/components/**/*.md 22 | docs/content/utilities/**/*.md 23 | files_ignore: | 24 | docs/content/components/index.md 25 | docs/content/utilities/index.md 26 | - name: Save changed files 27 | run: | 28 | echo "STRING_OF_PATHS_WE_CARE_ABOUT=${{ steps.changed-files.outputs.all_changed_files }}" >> $GITHUB_ENV 29 | - name: Use Node.js 30 | if: steps.changed-files.outputs.any_changed == 'true' 31 | uses: actions/setup-node@v3 32 | with: 33 | node-version: 14 34 | - run: yarn 35 | if: steps.changed-files.outputs.any_changed == 'true' 36 | - run: yarn dist 37 | if: steps.changed-files.outputs.any_changed == 'true' 38 | - name: Run docs site 39 | if: steps.changed-files.outputs.any_changed == 'true' 40 | run: | 41 | npm run dev & npx wait-on http://localhost:8000 42 | - name: Run axe script 43 | if: steps.changed-files.outputs.any_changed == 'true' 44 | run: | 45 | script/axe-docs $STRING_OF_PATHS_WE_CARE_ABOUT 46 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | jobs: 8 | stylelint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: 14 15 | - run: yarn 16 | - run: yarn dist 17 | - name: Lint source files 18 | run: yarn stylelint --fix 19 | - name: Look for unused stylelint:disable lines 20 | run: yarn stylelint -- --report-needless-disables 21 | - name: Push up any fixes 22 | if: ${{ github.event_name == 'pull_request' }} 23 | run: | 24 | set +e 25 | git status | grep modified 26 | if [ $? -eq 0 ] 27 | then 28 | set -e 29 | git stash 30 | git remote update 31 | git fetch 32 | git checkout --track origin/$GITHUB_HEAD_REF 33 | git config --local user.email "actions@github.com" 34 | git config --local user.name "Actions Auto Build" 35 | git stash pop 36 | git add src 37 | git commit -m "Stylelint auto-fixes" 38 | git push 39 | else 40 | set -e 41 | echo "No changes since last run" 42 | fi 43 | 44 | eslint: 45 | runs-on: ubuntu-latest 46 | steps: 47 | - uses: actions/checkout@v3 48 | - uses: actions/setup-node@v3 49 | with: 50 | node-version: 14 51 | - run: yarn 52 | - name: Lint workflow files 53 | run: yarn eslint 54 | 55 | test: 56 | runs-on: ubuntu-latest 57 | steps: 58 | - uses: actions/checkout@v3 59 | - uses: actions/setup-node@v3 60 | with: 61 | node-version: 14 62 | - run: yarn 63 | - name: Jest 64 | run: yarn test 65 | -------------------------------------------------------------------------------- /.github/workflows/deploy_preview.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | pull_request: 4 | 5 | permissions: 6 | contents: write 7 | pages: write 8 | id-token: write 9 | deployments: write 10 | issues: write 11 | statuses: write 12 | checks: write 13 | 14 | jobs: 15 | deploy: 16 | if: ${{ github.repository == 'primer/css' }} 17 | uses: primer/.github/.github/workflows/deploy_preview.yml@main 18 | name: Deploy preview 19 | secrets: 20 | gh_token: ${{ secrets.GITHUB_TOKEN }} 21 | with: 22 | node_version: 14 23 | install: yarn && cd docs && yarn && cd .. 24 | build: yarn build:docs:preview 25 | output_dir: docs/public 26 | 27 | deploy-storybook: 28 | if: ${{ github.repository == 'primer/css' }} 29 | name: Preview Storybook 30 | runs-on: ubuntu-latest 31 | needs: deploy 32 | steps: 33 | - uses: actions/checkout@v3 34 | 35 | - uses: chrnorm/deployment-action@v2.0.4 36 | name: Create GitHub deployment for storybook 37 | id: storybook 38 | with: 39 | token: ${{ secrets.GITHUB_TOKEN }} 40 | environment: Storybook Preview 41 | environment_url: '${{ needs.deploy.outputs.deployment_url }}/storybook' 42 | 43 | - name: Update storybook deployment status (success) 44 | if: success() 45 | uses: chrnorm/deployment-status@v2.0.1 46 | with: 47 | token: ${{ secrets.GITHUB_TOKEN }} 48 | environment-url: '${{ needs.deploy.outputs.deployment_url }}/storybook' 49 | state: 'success' 50 | deployment-id: ${{ steps.storybook.outputs.deployment_id }} 51 | 52 | - name: Update storybook deployment status (failure) 53 | if: failure() 54 | uses: chrnorm/deployment-status@v2.0.1 55 | with: 56 | token: ${{ secrets.GITHUB_TOKEN }} 57 | state: 'failure' 58 | deployment-id: ${{ steps.storybook.outputs.deployment_id }} 59 | -------------------------------------------------------------------------------- /.github/workflows/deploy_production.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | push: 4 | branches: 5 | - 'main' 6 | 7 | permissions: 8 | contents: write 9 | pages: write 10 | id-token: write 11 | deployments: write 12 | issues: write 13 | statuses: write 14 | checks: write 15 | 16 | jobs: 17 | guard: 18 | name: Guard 19 | runs-on: ubuntu-latest 20 | outputs: 21 | # To avoid deploying documentation for unrelease changes, we check the number of changeset files. 22 | # If it's 0, we deploy. 23 | should_deploy: ${{ steps.changeset-count.outputs.change_count == 0 }} 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - id: changeset-count 28 | run: echo "::set-output name=change_count::$(ls .changeset/*.md | grep -v README | wc -l | xargs)" 29 | 30 | # Log changeset count for debugging purposes 31 | - name: Log changeset count 32 | run: echo ${{ steps.changeset-count.outputs.change_count }} 33 | 34 | # Log guard output for debugging purposes 35 | - name: Log guard output 36 | run: echo ${{ needs.guard.outputs.should_deploy }} 37 | deploy: 38 | if: ${{ github.repository == 'primer/css' }} 39 | name: Production 40 | needs: [guard] 41 | uses: primer/.github/.github/workflows/deploy.yml@main 42 | secrets: 43 | gh_token: ${{ secrets.GITHUB_TOKEN }} 44 | with: 45 | node_version: 14 46 | install: yarn && cd docs && yarn && cd .. 47 | build: yarn build:docs 48 | output_dir: docs/public 49 | -------------------------------------------------------------------------------- /.github/workflows/next_major.yml: -------------------------------------------------------------------------------- 1 | name: Next Major Pull Request 2 | on: 3 | push: 4 | branches: 5 | - 'changeset-release/next_major' 6 | 7 | jobs: 8 | next_major_pr: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Don't Merge 12 | run: | 13 | echo "Don't merge the next_major, changeset pr into next_major. Instead when you're ready to release a new major version, change the base of this pr to main, and merge." 14 | exit 1 15 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - 'main' 6 | - 'next_major' 7 | jobs: 8 | release: 9 | name: Final 10 | if: ${{ github.repository == 'primer/css' }} 11 | 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v3 16 | with: 17 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 18 | fetch-depth: 0 19 | persist-credentials: false 20 | 21 | - name: Set up Node.js 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: 14.x 25 | 26 | - name: Install dependencies 27 | run: yarn 28 | 29 | - name: Create release pull request or publish to npm 30 | id: changesets 31 | uses: changesets/action@master 32 | with: 33 | title: Release Tracking 34 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 35 | publish: yarn release 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GPR_AUTH_TOKEN_SHARED }} 38 | NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN_SHARED }} 39 | -------------------------------------------------------------------------------- /.github/workflows/release_canary.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches-ignore: 5 | - 'main' 6 | - 'changeset-release/**' 7 | - 'dependabot/**' 8 | # Don't release canary when these paths change 9 | # It's not necessary because we don't ship them and it creates noise 10 | paths-ignore: 11 | - '.changeset/**' 12 | - 'docs/**' 13 | - 'lib/**' 14 | - '__tests__/**' 15 | - 'script/**' 16 | - 'next.config.js' 17 | - 'now.json' 18 | 19 | jobs: 20 | release-canary: 21 | name: Canary 22 | uses: primer/.github/.github/workflows/release_canary.yml@main 23 | with: 24 | install: yarn 25 | secrets: 26 | gh_token: ${{ secrets.GITHUB_TOKEN }} 27 | npm_token: ${{ secrets.NPM_AUTH_TOKEN_SHARED }} 28 | -------------------------------------------------------------------------------- /.github/workflows/release_candidate.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - 'changeset-release/**' 6 | 7 | jobs: 8 | release-candidate: 9 | name: Candidate 10 | if: ${{ github.repository == 'primer/css' }} 11 | 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v3 16 | with: 17 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 18 | fetch-depth: 0 19 | 20 | - name: Set up Node.js 21 | uses: actions/setup-node@v3 22 | with: 23 | node-version: 14.x 24 | 25 | - name: Install dependencies 26 | run: yarn 27 | 28 | - name: Create .npmrc 29 | run: | 30 | cat << EOF > "$HOME/.npmrc" 31 | //registry.npmjs.org/:_authToken=$NPM_TOKEN 32 | EOF 33 | env: 34 | NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN_SHARED }} 35 | 36 | - name: Publish release candidate 37 | run: | 38 | version=$(jq -r .version package.json) 39 | echo "$( jq ".version = \"$(echo $version)-rc.$(git rev-parse --short HEAD)\"" package.json )" > package.json 40 | yarn publish --tag next 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | 44 | - name: Output candidate version number 45 | uses: actions/github-script@v6 46 | with: 47 | script: | 48 | const package = require(`${process.env.GITHUB_WORKSPACE}/package.json`) 49 | github.rest.repos.createCommitStatus({ 50 | owner: context.repo.owner, 51 | repo: context.repo.repo, 52 | sha: context.sha, 53 | state: 'success', 54 | context: `Published ${package.name}`, 55 | description: package.version, 56 | target_url: `https://unpkg.com/${package.name}@${package.version}/` 57 | }) 58 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Stale 2 | on: 3 | schedule: 4 | - cron: '0 * * * *' 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v6 11 | with: 12 | 13 | # General settings 14 | days-before-stale: 60 15 | days-before-close: 7 16 | enable-statistics: true 17 | operations-per-run: 100 18 | remove-stale-when-updated: true 19 | 20 | # PR specific settings 21 | delete-branch: true 22 | stale-pr-message: "Hi! This pull request has been marked as stale because it has been open with no activity for 60 days. You can comment on the pull request or remove the stale label to keep it open. If you do nothing, this pull request will be closed in 7 days." 23 | 24 | # Issue specific settings 25 | days-before-issue-stale: 180 26 | stale-issue-message: "Hi! This issue has been marked as stale because it has been open with no activity for 180 days. You can comment on the issue or remove the stale label to keep it open. If you do nothing, this issue will be closed in 7 days." 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.tgz 3 | .DS_Store 4 | .cache/ 5 | .changelog/ 6 | .next/ 7 | .sass-cache 8 | .storybuild/ 9 | .stylelintcache 10 | _site 11 | dist/ 12 | docs/dist 13 | node_modules/ 14 | public/ 15 | searchIndex.js 16 | package-lock.json 17 | tmp 18 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | __tests__/ 2 | .changeset/ 3 | .github/ 4 | docs/ 5 | script/ 6 | # we ignore this because everything in src/ is copied out in script/prepublish 7 | src/ 8 | tmp/ 9 | docs.scss 10 | .* 11 | *.log 12 | vercel.json 13 | *.config.js 14 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | git-tag-version=false 2 | package-lock=false 3 | -------------------------------------------------------------------------------- /.vercelignore: -------------------------------------------------------------------------------- 1 | .*.sw? 2 | .changelog/ 3 | dist/ 4 | docs/dist 5 | docs/public/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 GitHub Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing a new version of Primer CSS 🎉 2 | 3 | ## Prepare the release (in `primer/css`) 4 | 5 | The release process is automated by [changesets]. After you familiarize yourself with how they work. We use an [action workflow integrated in ci](https://github.com/atlassian/changesets#integrating-with-ci). 6 | 7 | 1. Visit the pull requests page and find the [latest Release tracking pr from primer-css](https://github.com/primer/css/pulls/primer-css). If there isn't one, we'll need to build the next release by merging in PRs with changeset files. 8 | 9 | ## Test the release candidate (in `github/github`): 10 | 11 | 1. Create a new branch in the `github/github` repo, name it `primer-`. 12 | 13 | 1. Update the Primer CSS version to the published release candidate with: 14 | 15 | ```sh 16 | bin/npm install @primer/css@-rc. 17 | ``` 18 | 19 | Then commit and push the changes to `package.json`, `package-lock.json`, `LICENSE` and `vendor/npm`. 20 | 21 | 1. If you need to make changes to github/github due to the Primer CSS release, do them in a branch and merge _that_ into your release branch after testing. 22 | 23 | 1. Add or re-request reviewers and fix any breaking tests. 24 | 25 | 1. Test on review-lab. 26 | 27 | 28 | ## Publish the release (in `primer/css`) 29 | 30 | 1. If the release PR got approved and you've done necessary testing, merge it. 31 | 32 | After tests run, the docs site will be deployed and `@primer/css` will be published with your changes to the `latest` dist-tag. You can check [npm](https://www.npmjs.com/package/@primer/css?activeTab=versions) to see if actions has finished. 33 | 34 | 2. Done! 🎉 35 | 36 | 37 | ## Update github.com (in `github/github`): 38 | 39 | 1. Install the latest published version in the same `primer-` branch created earlier with: 40 | 41 | ``` 42 | bin/npm install @primer/css@ 43 | ``` 44 | 45 | Then commit and push the changes to `package.json`, `package-lock.json`, `LICENSE` and `vendor/npm`. 46 | 47 | 1. Fix any breaking tests. 48 | 49 | 1. Deploy! :rocket: 50 | 51 | [changelog]: ../CHANGELOG.md 52 | [changesets]: https://github.com/atlassian/changesets 53 | -------------------------------------------------------------------------------- /__tests__/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:jest/recommended" 4 | ], 5 | "rules": { 6 | "eslint-comments/no-use": 0 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /__tests__/build.test.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | 3 | let distDir 4 | 5 | beforeAll(() => { 6 | distDir = fs.readdirSync('./dist') 7 | }) 8 | 9 | describe('./dist/ folder', () => { 10 | let distCSS, distMap, distJS 11 | 12 | beforeAll(() => { 13 | distCSS = distDir.filter(i => i.match(/\.css$/)) 14 | distMap = distDir.filter(i => i.match(/\.map$/)) 15 | distJS = distDir.filter(i => i.match(/\.js$/)) 16 | }) 17 | 18 | it('is not empty', () => { 19 | expect(distDir).not.toBeNull() 20 | expect(distDir.length).not.toBe(0) 21 | }) 22 | 23 | it('contains source maps', () => { 24 | for (const file of distCSS) { 25 | if (file.includes('support')) { continue } 26 | expect(distMap).toContain(`${file}.map`) 27 | } 28 | }) 29 | 30 | it('contains stats export files', () => { 31 | for (const file of distCSS) { 32 | expect(distJS).toContain(file.replace('.css', '.js')) 33 | } 34 | }) 35 | 36 | it('contains stats/ folder', () => { 37 | expect(distDir).toContain('stats') 38 | }) 39 | }) 40 | 41 | describe('./dist/stats/ folder', () => { 42 | let statsDir 43 | 44 | beforeAll(() => { 45 | statsDir = fs.readdirSync('./dist/stats') 46 | }) 47 | 48 | it('is not empty', () => { 49 | expect(statsDir).not.toBeNull() 50 | expect(statsDir.length).not.toBe(0) 51 | }) 52 | 53 | it('contains a css file for each stat file', () => { 54 | for (const file of statsDir) { 55 | expect(distDir).toContain(file.replace('.json', '.css')) 56 | } 57 | }) 58 | }) 59 | -------------------------------------------------------------------------------- /__tests__/css.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | getCurrentVersion, 3 | getPackageStats, 4 | getSelectorDiff, 5 | getVariableDiff, 6 | currentVersionDeprecations 7 | } from './utils/css' 8 | import semver from 'semver' 9 | 10 | let selectorsDiff, variablesDiff, version 11 | 12 | beforeAll(async () => { 13 | selectorsDiff = getSelectorDiff() 14 | variablesDiff = getVariableDiff() 15 | version = getCurrentVersion() 16 | }) 17 | 18 | describe('css', () => { 19 | it('The support.css file contains no compiled css', () => { 20 | const supportStats = getPackageStats('support') 21 | expect(supportStats.size).toEqual(0) 22 | }) 23 | }) 24 | 25 | describe('deprecations', () => { 26 | it('expects deprecations and their replacement to not be equal.', () => { 27 | const deprecations = currentVersionDeprecations() 28 | Object.keys(deprecations["selectors"]).forEach(deprecation => { 29 | const replacement = deprecations["selectors"][deprecation] 30 | expect(deprecation).not.toEqual(replacement) 31 | }) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /__tests__/docs.test.js: -------------------------------------------------------------------------------- 1 | import {getNavigationLinks, getContentFrontmatter} from './utils/docs' 2 | 3 | let navLinks, contentFM 4 | 5 | beforeAll(async () => { 6 | contentFM = await getContentFrontmatter() 7 | navLinks = getNavigationLinks() 8 | }) 9 | 10 | describe('frontmatter', () => { 11 | it('page title matches link title', () => { 12 | for (const link of navLinks) { 13 | const content = contentFM[link['url']] 14 | expect(content).not.toBeNull() 15 | expect(content['title']).toBe(link['title']) 16 | } 17 | }) 18 | 19 | it('contains path attribute', () => { 20 | for (const v of Object.values(contentFM)) { 21 | expect(v['path']).not.toBeNull() 22 | } 23 | }) 24 | }) 25 | 26 | describe('navigation', () => { 27 | it('has a file for each nav item', () => { 28 | for (const link of navLinks) { 29 | const content = contentFM[link['url']] 30 | expect(content).not.toBeNull() 31 | } 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /__tests__/utils/docs.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import frontMatter from 'front-matter' 3 | import yaml from 'js-yaml' 4 | import {globby} from 'globby' 5 | import { fileURLToPath } from 'url' 6 | import {join, dirname} from 'path' 7 | 8 | const __dirname = dirname(fileURLToPath(import.meta.url)) 9 | 10 | const docsPath = join(__dirname, '../../docs') 11 | 12 | function collectNavLinks(links) { 13 | let foundLinks = [] 14 | for (const link of links) { 15 | foundLinks.push({ 16 | title: link['title'], 17 | url: link['url'] 18 | }) 19 | if (link['children']) { 20 | foundLinks = foundLinks.concat(collectNavLinks(link['children'])) 21 | } 22 | } 23 | return foundLinks 24 | } 25 | 26 | export function getNavigationLinks() { 27 | const nav = yaml.load(fs.readFileSync(join(docsPath, './src/@primer/gatsby-theme-doctocat/nav.yml'), 'utf8')) 28 | return collectNavLinks(nav) 29 | } 30 | 31 | export async function getContentFrontmatter() { 32 | const fm = {} 33 | 34 | const paths = await globby(join(docsPath, './content/**/*.md*')) 35 | for (const path of paths) { 36 | const contents = fs.readFileSync(path, 'utf8') 37 | const fmContents = frontMatter(contents) 38 | fm[path.replace(join(docsPath, './content'), '').replace(/(\/index)?\.mdx?/, '')] = fmContents['attributes'] 39 | } 40 | return fm 41 | } 42 | -------------------------------------------------------------------------------- /deprecations.js: -------------------------------------------------------------------------------- 1 | /** 2 | Deprecated Selectors 3 | ------------------------- 4 | These are deprecated selectors and should not be used. They include a replacement value, 5 | which can be an array or null. 6 | 7 | * 'deprecated-selector': 'replacement-selector' <-- Replace with this selector. 8 | * 'deprecated-selector': ['replacement-1', 'replacement-2'] <-- Replace with one of these selectors. 9 | * 'deprecated-selector': null <-- No option available, remove selector. 10 | */ 11 | 12 | import fs from 'fs' 13 | 14 | const deprecations = JSON.parse(fs.readFileSync('./dist/deprecations.json')) 15 | 16 | const deprecatedSelectors = deprecations['selectors'] 17 | const deprecatedSassVariables = deprecations['variables'] 18 | const deprecatedSassMixins = deprecations['mixins'] 19 | 20 | export { 21 | deprecatedSelectors, 22 | deprecatedSassVariables, 23 | deprecatedSassMixins 24 | } 25 | -------------------------------------------------------------------------------- /docs/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "babel-preset-gatsby", 4 | "@babel/preset-react" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /docs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:react/recommended", 4 | "plugin:jsx-a11y/recommended" 5 | ], 6 | "rules": { 7 | "import/no-namespace": 0, 8 | "no-unused-vars": ["error", { 9 | "ignoreRestSiblings": true 10 | }] 11 | }, 12 | "settings": { 13 | "react": { 14 | "version": "detect" 15 | } 16 | }, 17 | "globals": { 18 | "__DEV__": "readonly" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], 3 | addons: [ 4 | '@storybook/addon-a11y', 5 | '@storybook/addon-links', 6 | '@storybook/addon-essentials', 7 | '@storybook/preset-scss', 8 | '@whitespace/storybook-addon-html', 9 | 'storybook-addon-designs', 10 | 'storybook-color-picker', 11 | 'storybook-addon-variants/preset.js' 12 | ], 13 | framework: '@storybook/react', 14 | core: { 15 | builder: 'webpack5' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /docs/content/components/branch-name.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Branch name 3 | path: components/branch-name 4 | status: Stable 5 | source: 'https://github.com/primer/css/tree/main/src/branch-name' 6 | bundle: branch-name 7 | --- 8 | 9 | Branch names can be a link name or not: 10 | 11 | ```html live 12 | a_new_feature_branch 13 | ``` 14 | 15 | ```html live 16 | a_new_feature_branch 17 | ``` 18 | 19 | You may also include an octicon before the branch name text: 20 | 21 | ```html live 22 | 23 | 24 | 25 | a_new_feature_branch 26 | 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/content/components/breadcrumb.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Breadcrumbs 3 | path: components/breadcrumb 4 | status: Stable 5 | source: 'https://github.com/primer/css/tree/main/src/breadcrumb' 6 | bundle: breadcrumb 7 | --- 8 | 9 | Breadcrumbs are used to show taxonomical context on pages that are many levels deep in a site’s hierarchy. Breadcrumbs show and link to parent, grandparent, and sometimes great-grandparent pages. Breadcrumbs are most appropriate on pages that: 10 | 11 | - Are many levels deep on a site 12 | - Do not have a section-level navigation 13 | - May need the ability to quickly go back to the previous (parent) page 14 | 15 | All items must contain links, and the last item must be selected. 16 | 17 | #### Usage 18 | 19 | ```html live 20 | 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/content/components/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Components 3 | path: components/index 4 | --- 5 | 6 | Components make it easier to mark up a set of elements that are commonly grouped together with similar visual styles. Their base styles are shared and variants are added with modifier classes, so usually components are comprised of multiple classes. Most importantly, components should be highly reusable across the site, rather than built for specific pages or features. To achieve this: 7 | 8 | * **Separate structure and skin:** This means to define repeating visual features (like background and border styles) as separate “skins” that you can mix-and-match with your various components to achieve a large amount of visual variety without much code. 9 | * **Separate container and content:** Essentially, this means “rarely use location-dependent styles”. A component should look the same no matter where you put it. 10 | -------------------------------------------------------------------------------- /docs/content/components/loaders.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Loaders 3 | path: components/loaders 4 | status: Beta 5 | source: 'https://github.com/primer/css/tree/main/src/loaders' 6 | bundle: loaders 7 | --- 8 | 9 | Loaders inform users that an action is still in progress and might take a while to complete. 10 | 11 | ## Animated ellipsis 12 | 13 | Add an animated ellipsis at the end of text with ``. 14 | 15 | ```html live 16 | Loading 17 | ``` 18 | 19 | It can also be used in combination with other components. 20 | 21 | ```html live 22 |

Loading

23 | Loading
24 | Loading
25 | 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/content/components/pagination.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Pagination 3 | path: components/pagination 4 | status: Beta 5 | source: 'https://github.com/primer/css/tree/main/src/pagination' 6 | bundle: pagination 7 | --- 8 | 9 | Use the pagination component to apply button styles to a connected set of links that go to related pages (for example, previous, next, or page numbers). 10 | 11 | ## Previous/next pagination 12 | 13 | You can make a very simple pagination container with just the Previous and Next buttons. Add the `aria-disabled="true"` attribute to the `Previous` button if there isn't a preceding page, or to the `Next` button if there isn't a succeeding page. 14 | 15 | ```html live 16 | 22 | ``` 23 | 24 | ## Numbered pagination 25 | 26 | For pagination across multiple pages, make sure it's clear to the user where they are in a set of pages. 27 | 28 | To do this, add anchor links to the `pagination` element. Previous and Next buttons should always be present. Add the `aria-disabled="true"` attribute to the Previous button if you're on the first page. Apply the `aria-current="page"` attribute to the current numbered page. 29 | 30 | As always, make sure to include the appropriate `aria` attributes to make the element accessible. 31 | 32 | - Add `aria-label="Pagination"` to the `paginate-container` element. 33 | - Add `aria-label="Page X"` to each anchor link. 34 | 35 | ```html live 36 | 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/content/marketing/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Marketing 3 | path: marketing/index 4 | --- 5 | 6 | The marketing components and utilities are meant for marketing pages. Note that on github.com they are not available for product pages. 7 | -------------------------------------------------------------------------------- /docs/content/support/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Support 3 | path: support/index 4 | source: 'https://github.com/primer/css/tree/main/src/support' 5 | bundle: support 6 | --- 7 | 8 | 9 | Primer CSS is built on systems that form the foundation of our styles, and inform the way we write and organize our CSS. Building upon systems helps us make styles consistent and interoperable with each other, and assists us with visual hierarchy and vertical rhythm. 10 | 11 | We use Sass variables to keep color, typography, spacing, and other foundations of our system consistent. Occasionally we use Sass mixins to apply multiple CSS properties, they are a convenient solution for frequently-used verbose patterns. 12 | 13 | We've documented variables, mixins, and the systems they are built on for the following: 14 | 15 | - [Breakpoints](/support/breakpoints) 16 | - [Spacing](/support/spacing) 17 | - [Theming](/support/theming) 18 | - [Typography](/support/typography) 19 | -------------------------------------------------------------------------------- /docs/content/support/variables.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Variables 3 | path: support/variables 4 | status: Stable 5 | --- 6 | 7 | import {Variables, DeprecationIcon} from '../../src/variables' 8 | 9 | 10 | 11 | The tables below list all of the global SCSS variables defined in [the `support/variables` directory](https://github.com/primer/css/tree/main/src/support/variables). 12 | 13 | Variables with a are planned for [deprecation](../tools/deprecations) in a future version of `@primer/css`, and should be avoided. 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/content/tools/deprecations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deprecation data 3 | --- 4 | 5 | As of version 12.7.0, we publish CSS selector and SCSS variable deprecation data (as of 14.0.0) with `@primer/css`. You can access the data via the [Node API](#node) or as [JSON](#json). 6 | 7 | To deprecate a class, variable, or mixin, add the element to the [deprecations.js](https://github.com/primer/css/blob/main/deprecations.js) file with it's replacement value. 8 | 9 | The replacement can be: 10 | 11 | * A `String` for a direct replacement. 12 | * An `Array` for multiple replacement options. 13 | * `null` to indicate there is no replacement. 14 | 15 | This could look something like this: 16 | 17 | ```js 18 | const deprecations = { 19 | "deprecated-1": "replacement", 20 | "deprecated-2": ["replacement-1", "replacement-2"], 21 | "deprecated-3": null 22 | } 23 | ``` 24 | 25 | ## JSON 26 | 27 | The JSON data is available in the unpacked node module's `dist/deprecations.json`, and is an object with the following structure: 28 | 29 | ```json 30 | { 31 | "selectors" {...}, 32 | "variables": {...}, 33 | "mixins": {...} 34 | } 35 | ``` 36 | 37 | * `selectors` is an object mapping CSS selectors to their replacements. If the replacement is an Array, then there's multiple options. If the replacement is null then there are no replacements. 38 | 39 | ```json 40 | { 41 | "selectors": { 42 | "deprecated-class": "replacement-class" 43 | } 44 | } 45 | ``` 46 | 47 | * `variables` is an object mapping SCSS variables to their replacement SCSS variable. 48 | 49 | ```json 50 | { 51 | "variables": { 52 | "$deprecated-variable": "$replacement-variable" 53 | } 54 | } 55 | ``` 56 | 57 | * `mixins` is an object mapping SCSS mixins to their replacement SCSS mixins. 58 | 59 | ```json 60 | { 61 | "mixins": { 62 | "deprecated-mixin": "replacement-mixin" 63 | } 64 | } 65 | ``` 66 | 67 | 68 | ## Node 69 | 70 | The Node API for selector deprecations is available at 71 | `@primer/css/deprecations`. 72 | 73 | ### Example: 74 | 75 | ```js 76 | const { 77 | deprecatedSelectors, 78 | deprecatedSassVariables, 79 | deprecatedSassMixins 80 | } = require('@primer/css/deprecations') 81 | 82 | ``` 83 | -------------------------------------------------------------------------------- /docs/content/tools/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tools 3 | path: tools/index 4 | --- 5 | 6 | Design and development tools for working with the GitHub CSS toolkit. 7 | -------------------------------------------------------------------------------- /docs/content/tools/testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Testing resources 3 | path: tools/testing 4 | --- 5 | 6 | At GitHub we use a staging environment called review-lab for testing with production data. Deploying a branch to [review-lab](https://github.com/github/github/blob/master/docs/deployment.md#test-in-lab-environments) for testing is one of the best ways to test your work with real production data prior to an actual production deployment. 7 | 8 | To make testing on review-lab for extended periods of time easier, you can use the [Redirector](https://chrome.google.com/webstore/detail/redirector/pajiegeliagebegjdhebejdlknciafen) extension for Chrome to redirect all GitHub.com traffic to your review-lab deploy URL. 9 | 10 | ## How to use it 11 | 12 | 1. Install the [extension](https://chrome.google.com/webstore/detail/redirector/pajiegeliagebegjdhebejdlknciafen) 13 | 2. Open the extension options panel from the icon in Chrome 14 | 3. In the "From" field, enter: `https:\/\/github\.com\/?(.+)?` 15 | 4. In the "To" field, enter: `https://branchname.review-lab.github.com/$1` where `branchname` is the name of your branch. 16 | 17 | ## Tips 18 | 19 | - You'll need to remove your rule or simply disable the extension when you want to stop redirecting to your branch. 20 | - If you're trying to reach GitHub.com or your review-lab URL but are getting a "This page isn't working" message in your browser, that means your review-lab deploy has gone stale and needs to be redeployed. 21 | -------------------------------------------------------------------------------- /docs/content/utilities/details.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Details 3 | path: utilities/details 4 | status: Stable 5 | source: 'https://github.com/primer/css/blob/main/src/utilities/details.scss' 6 | bundle: utilities 7 | --- 8 | 9 | Details classes are created to enhance the native behaviors of `
`. 10 | 11 | ## Fullscreen click area 12 | 13 | Use `.details-overlay` to expand the click area of `` to cover the full screen, so user can click anywhere on a page to close `
`. 14 | 15 | ```html live 16 |
17 | More 18 |
Hidden text
19 |
20 | ``` 21 | 22 | ## Darkened fullscreen click area 23 | 24 | Use `.details-overlay-dark` darken the click area overlay. Useful for modals. 25 | 26 | ```html live 27 |
28 | More 29 |
30 | Hidden text 31 |
32 |
33 | ``` 34 | 35 | ## Custom caret 36 | 37 | Use `.details-reset` to remove the default caret (that little triangle on the left). You then can add the `.dropdown-caret` on the right of the text. 38 | 39 | ```html live 40 |
41 | More 42 |
Hidden text
43 |
44 | ``` 45 | 46 | ## Using button styles with the details summary element 47 | 48 | You can add `.btn` and `.btn-*` classes to any 49 | [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary) 50 | element so that it gains the appearance of a button, and 51 | selected/active styles when the parent 52 | [`
`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details) 53 | element is open. 54 | 55 | ```html live 56 |
57 | More 58 |
Hidden text
59 |
60 | 61 |
62 | More 63 |
Hidden text
64 |
65 | ``` 66 | -------------------------------------------------------------------------------- /docs/content/utilities/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Utilities 3 | path: utilities/index 4 | --- 5 | 6 | Utilities provide the building blocks for layout and handle a range common use cases that help us avoid writing custom styles. When we need to add some margin or padding, rather than adding a new selector specific to that use case, we can use utilities. This helps us reduce the number of unique property-value pairs, and helps us keep more consistent styles across the site. 7 | 8 | * Utilities should do one job well and one job only, are immutable, and on occasion are an acceptable approach to overriding component styles. 9 | * Utility class-names should be transparent and clearly describe the job they do. 10 | -------------------------------------------------------------------------------- /docs/content/utilities/marketing-filters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Marketing filters 3 | path: utilities/marketing-filters 4 | status: Stable 5 | status_issue: 'https://github.com/github/design-systems/issues/302' 6 | source: 'https://github.com/primer/css/blob/main/src/marketing/utilities/filters.scss' 7 | bundle: marketing-utilities 8 | --- 9 | 10 | Filter utility classes can be applied to divs or images to apply visual effects. 11 | 12 |
13 | Note: CSS filters are not supported by IE 14 |
15 | 16 | ## Grayscale 17 | 18 | Applying `.grayscale` to an element will remove all of its colors, and make it render in black and white. 19 | 20 | ```html live 21 | 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/content/utilities/marketing-layout.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Marketing layout 3 | sort_title: Layout Marketing 4 | path: utilities/marketing-layout 5 | status: Stable 6 | source: 'https://github.com/primer/css/blob/main/src/marketing/utilities/layout.scss' 7 | bundle: marketing-utilities 8 | --- 9 | 10 | Marketing layout utilities build on top of [primer-core utilities](/utilities/layout#position), adding the option of responsive positioning. 11 | 12 | 13 | 14 | ## Position elements with spacing utilities 15 | 16 | Position elements from all four element edges (`top`, `right`, `bottom`, and `left`) using any spacing utility from the global spacing scale and the marketing spacing scale (from `$spacer-1` to `$spacer-12`), including negative and 0 values. 17 | 18 | Use these with `.position-absolute` to position decorative assets and shapes on marketing sites. 19 | 20 | In an effort to reduce the size of our CSS, responsive breakpoints are only supported for `md` and `lg` breakpoints. **There is no support for `sm` and `xl` breakpoints.** 21 | 22 | ```html live 23 |
24 |
.top-2
25 |
.right-md-4
26 |
.left-lg-1
27 |
28 | ``` 29 | 30 | ## Negative offset columns 31 | 32 | Using column offset classes can pull a div over X number of columns to the left. Negative offsets are available in [spacings from 1](../support/spacing/#spacing-scale) [to 7](../support/spacing/#extended-spacing-scale). 33 | 34 | ```html live 35 |
36 |
.offset-n1
37 |
.offset-n2
38 |
39 | ``` 40 | -------------------------------------------------------------------------------- /docs/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | // temporary import until primitives moves to core bundle 2 | // importing the index from /css didn't play nice with Gatsby 3 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/base/size/size.css' 4 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/base/typography/typography.css' 5 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/size/border.css' 6 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/size/breakpoints.css' 7 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/size/size-coarse.css' 8 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/size/size-fine.css' 9 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/size/size.css' 10 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/size/viewport.css' 11 | import '../node_modules/@primer/primitives/tokens-v2-private/css/tokens/functional/typography/typography.css' 12 | -------------------------------------------------------------------------------- /docs/gatsby-config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | siteMetadata: { 5 | title: 'Primer CSS', 6 | shortName: 'CSS', 7 | description: "CSS for GitHub's Primer design system", 8 | imageUrl: 'https://user-images.githubusercontent.com/586552/47590375-121cad80-d93a-11e8-89f2-a1cf108e0548.png' 9 | }, 10 | pathPrefix: '/css', 11 | plugins: [ 12 | { 13 | resolve: '@primer/gatsby-theme-doctocat', 14 | options: { 15 | defaultBranch: 'main', 16 | repoRootPath: '..' 17 | } 18 | }, 19 | 'gatsby-plugin-sass', 20 | { 21 | resolve: 'gatsby-plugin-svgr', 22 | options: { 23 | svgo: false 24 | } 25 | }, 26 | { 27 | resolve: `gatsby-plugin-alias-imports`, 28 | options: { 29 | alias: { 30 | 'styled-components': path.resolve(__dirname, 'node_modules', 'styled-components'), 31 | react: path.resolve(__dirname, 'node_modules', 'react') 32 | } 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /docs/gatsby-node.js: -------------------------------------------------------------------------------- 1 | exports.onCreateWebpackConfig = ({actions, stage, plugins}) => { 2 | actions.setWebpackConfig({ 3 | node: { 4 | fs: 'empty' 5 | }, 6 | plugins: [ 7 | plugins.define({ 8 | __DEV__: stage === 'develop' || stage === 'develop-html' 9 | }) 10 | ] 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /docs/postcss.config.js: -------------------------------------------------------------------------------- 1 | // This config file is necessary to get postcss-loader to work in 2 | // ./src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js. 3 | const path = require('path') 4 | 5 | module.exports = { 6 | parser: 'postcss-scss', 7 | plugins: [ 8 | require('postcss-node-sass')({ 9 | includePaths: [path.join(__dirname, 'node_modules')], 10 | outputStyle: 'compressed' 11 | }), 12 | require('autoprefixer') 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /docs/script/build-storybook: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | # Add base url to be able to serve static files 4 | if [ -n "$1" ]; then 5 | echo '' >> .storybook/manager-head.html 6 | else 7 | echo '' >> .storybook/manager-head.html 8 | fi 9 | 10 | # Build storybook inside docs 11 | ./node_modules/.bin/build-storybook -o public/storybook -s public/static 12 | 13 | # Remove manager-head after build to not interfere with dev builds 14 | rm .storybook/manager-head.html 15 | -------------------------------------------------------------------------------- /docs/src/@primer/gatsby-theme-doctocat/components/hero.js: -------------------------------------------------------------------------------- 1 | import {Box, Heading, Text, ThemeProvider} from '@primer/components' 2 | import {Container} from '@primer/gatsby-theme-doctocat' 3 | import React from 'react' 4 | import {version} from '../../../../../package.json' 5 | import {ReactComponent as HeroIllustration} from '../../../hero-illustration.svg' 6 | 7 | function Hero() { 8 | return ( 9 | 10 | 11 | 12 | 13 | Primer CSS 14 | 15 | 16 | v{version} 17 | 18 | 19 | 20 | 21 | 22 | ) 23 | } 24 | 25 | export default Hero 26 | -------------------------------------------------------------------------------- /docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js: -------------------------------------------------------------------------------- 1 | import primerStyles from '!!raw-loader!postcss-loader!../../../../../src/docs.scss' 2 | import {Flex} from '@primer/components' 3 | import {Frame} from '@primer/gatsby-theme-doctocat' 4 | import {MoonIcon, SunIcon} from '@primer/octicons-react' 5 | import React from 'react' 6 | 7 | function LivePreviewWrapper({children}) { 8 | const [colorMode, setColorModeState] = React.useState('light') 9 | 10 | const setColorMode = mode => { 11 | window.dispatchEvent(new CustomEvent('color-mode-change', {detail: {mode}})) 12 | } 13 | 14 | React.useEffect(() => { 15 | const callback = e => setColorModeState(e.detail.mode) 16 | window.addEventListener('color-mode-change', callback) 17 | 18 | return () => { 19 | window.removeEventListener('color-mode-change', callback) 20 | } 21 | }, [setColorModeState]) 22 | 23 | return ( 24 | 25 | 26 |
27 | 28 | 35 | 36 |
{children}
37 |
38 | 39 | ) 40 | } 41 | 42 | export default LivePreviewWrapper 43 | -------------------------------------------------------------------------------- /docs/src/color-image.svg: -------------------------------------------------------------------------------- 1 | 2 | Group 3 | Created using Figma 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/src/components-image.svg: -------------------------------------------------------------------------------- 1 | styles 2 | -------------------------------------------------------------------------------- /docs/src/objects-image.svg: -------------------------------------------------------------------------------- 1 | objects 2 | -------------------------------------------------------------------------------- /docs/src/readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArthurClemens/css/f3acb2b116f10955e1ba4f1a35aa874eed019ceb/docs/src/readme.png -------------------------------------------------------------------------------- /docs/src/spacing-image.svg: -------------------------------------------------------------------------------- 1 | 2 | Group 3 | Created using Figma 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/src/stories/GettingStarted.stories.mdx: -------------------------------------------------------------------------------- 1 | import {Meta} from '@storybook/addon-docs' 2 | 3 | 4 | 5 | # Local development 6 | 7 | Run `yarn storybook` from root. A local server will run, and any changes made to CSS and/or stories will auto-reload the page. 8 | 9 | # Storybook config 10 | 11 | Config files live in [.storybook](docs/.storybook) 12 | 13 | [main.js](docs/.storybook/main.js): addons 14 | 15 | [preview.js](docs/.storybook/preview.js): customizations, decorators, global CSS imports 16 | 17 | [preview-head.html](docs/.storybook/preview-head.html): story-level "global" styles (within the story iframe) 18 | -------------------------------------------------------------------------------- /docs/src/stories/components/ActionList/ActionList.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {ListItemTemplate} from '../../ui-patterns/ActionList/ActionListItem.stories' 3 | import {ListTemplate} from '../../ui-patterns/ActionList/ActionList.stories.jsx' 4 | 5 | export default { 6 | title: 'Components/ActionList/ActionList', 7 | excludeStories: ['ActionListTemplate'], 8 | argTypes: { 9 | showDividers: { 10 | control: {type: 'boolean'}, 11 | description: 'Show dividers between items', 12 | table: { 13 | category: 'CSS' 14 | } 15 | }, 16 | role: { 17 | options: ['list'], 18 | control: { 19 | type: 'inline-radio' 20 | }, 21 | description: 'Semantic list role', 22 | table: { 23 | category: 'HTML' 24 | } 25 | }, 26 | ariaLabel: { 27 | name: 'ariaLabel', 28 | type: 'string', 29 | description: 'If no list ActionListDivider is provided, include an aria-label', 30 | table: { 31 | category: 'HTML' 32 | } 33 | }, 34 | ariaLabelledBy: { 35 | name: 'ariaLabelledBy', 36 | type: 'string', 37 | description: 'Reference ID of ActionListDivider', 38 | table: { 39 | category: 'HTML' 40 | } 41 | }, 42 | listPadding: { 43 | options: [0, 1], // iterator 44 | mapping: [null, 'ActionList--full'], // values 45 | control: { 46 | type: 'inline-radio', 47 | labels: ['inset', 'full-bleed'] 48 | }, 49 | description: 'ActionList includes 8px padding by default, full-bleed removes all padding', 50 | table: { 51 | category: 'CSS' 52 | } 53 | }, 54 | children: { 55 | table: { 56 | disable: true 57 | } 58 | } 59 | } 60 | } 61 | 62 | export const ActionListTemplate = ListTemplate.bind({}) 63 | 64 | export const Playground = ActionListTemplate.bind({}) 65 | Playground.args = { 66 | showDividers: false, 67 | listPadding: 0, 68 | role: 'list', 69 | ariaLabel: '', 70 | ariaLabelledBy: '', 71 | children: ( 72 | <> 73 | 74 | 75 | 76 | ) 77 | } 78 | -------------------------------------------------------------------------------- /docs/src/stories/components/ActionList/ActionListDivider.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | import {ListTemplate} from '../../ui-patterns/ActionList/ActionList.stories.jsx' 4 | import {DividerTemplate} from '../../ui-patterns/ActionList/ActionListDivider.stories.jsx' 5 | 6 | export default { 7 | title: 'Components/ActionList/ActionListDivider', 8 | excludeStories: ['ActionDividerTemplate'], 9 | argTypes: { 10 | variant: { 11 | options: [0, 1], // iterator 12 | mapping: ['', 'ActionList-sectionDivider--filled'], // values 13 | control: { 14 | type: 'inline-radio', 15 | labels: ['subtle', 'filled'] 16 | }, 17 | table: { 18 | category: 'CSS' 19 | } 20 | }, 21 | title: { 22 | defaultValue: '', 23 | type: 'string', 24 | name: 'title', 25 | description: 'string', 26 | table: { 27 | category: 'HTML' 28 | } 29 | }, 30 | description: { 31 | defaultValue: '', 32 | type: 'string', 33 | name: 'description', 34 | description: 'string', 35 | table: { 36 | category: 'HTML' 37 | } 38 | }, 39 | id: { 40 | defaultValue: '', 41 | type: 'string', 42 | name: 'id', 43 | description: 'Provide label for NavigationList
    aria-labelledby', 44 | table: { 45 | category: 'HTML' 46 | } 47 | } 48 | } 49 | } 50 | 51 | export const ActionDividerTemplate = DividerTemplate.bind({}) 52 | 53 | export const Playground = ActionDividerTemplate.bind({}) 54 | Playground.args = { 55 | title: 'Section title', 56 | description: 'Section description', 57 | variant: 0 58 | } 59 | Playground.decorators = [ 60 | Story => ( 61 | 62 | 63 | 64 | ) 65 | ] 66 | -------------------------------------------------------------------------------- /docs/src/stories/components/ActionList/ActionListDividerFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {ListTemplate} from '../../ui-patterns/ActionList/ActionList.stories.jsx' 3 | 4 | import { 5 | PatternTitle, 6 | PatternFilled, 7 | PatternWithDescription, 8 | PatternSeparator 9 | } from '../../ui-patterns/ActionList/ActionListDividerFeatures.stories.jsx' 10 | 11 | export default { 12 | title: 'Components/ActionList/ActionListDivider/Features', 13 | decorators: [ 14 | Story => ( 15 | 16 | 17 | 18 | ) 19 | ] 20 | } 21 | 22 | export const Title = ({}) => 23 | 24 | export const Filled = ({}) => 25 | 26 | export const WithDescription = ({}) => 27 | 28 | export const Separator = ({}) => 29 | -------------------------------------------------------------------------------- /docs/src/stories/components/ActionList/ActionListFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | PatternShowDividers, 4 | PatternInsetPadding, 5 | PatternFullBleed 6 | } from '../../ui-patterns/ActionList/ActionListFeatures.stories.jsx' 7 | 8 | export default { 9 | title: 'Components/ActionList/ActionList/Features' 10 | } 11 | 12 | export const ShowDividers = ({}) => 13 | 14 | export const InsetPadding = ({}) => 15 | 16 | export const FullBleed = ({}) => 17 | -------------------------------------------------------------------------------- /docs/src/stories/components/Forms/Fieldset.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default { 4 | title: 'Components/Forms/Fieldset', 5 | decorators: [ 6 | Story => ( 7 |
    8 | 9 | 10 | ) 11 | ], 12 | argTypes: { 13 | disabled: { 14 | description: 'disabled fieldset', 15 | control: {type: 'boolean'}, 16 | table: { 17 | category: 'Interactive' 18 | } 19 | } 20 | } 21 | } 22 | 23 | const FieldsetTemplate = ({disabled}) => ( 24 |
    25 | 26 | 27 | 28 | 29 | 30 |
    31 | ) 32 | 33 | export const Playground = FieldsetTemplate.bind({}) 34 | Playground.args = { 35 | disabled: false 36 | } 37 | -------------------------------------------------------------------------------- /docs/src/stories/components/Forms/Radio.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | import {CheckboxTemplate} from './Checkbox.stories' 4 | 5 | export default { 6 | title: 'Components/Forms/Radio', 7 | parameters: { 8 | layout: 'padded' 9 | }, 10 | decorators: [ 11 | Story => ( 12 |
    13 | 14 | 15 | ) 16 | ] 17 | } 18 | 19 | export const Playground = CheckboxTemplate.bind({}) 20 | Playground.args = { 21 | label: 'Label', 22 | focusElement: false, 23 | disabled: false, 24 | checked: false, 25 | highlight: false, 26 | note: '', 27 | type: 'radio', 28 | focusAllElements: false 29 | } 30 | -------------------------------------------------------------------------------- /docs/src/stories/components/Label/IssueLabel.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | 4 | export default { 5 | title: 'Components/Label/IssueLabel', 6 | excludeStories: ['IssueLabelTemplate'], 7 | argTypes: { 8 | variant: { 9 | options: [0, 1, 2, 3], // iterator 10 | mapping: [ 11 | 'color-bg-accent-emphasis', 12 | 'color-bg-danger-emphasis', 13 | 'color-bg-success-emphasis', 14 | 'color-bg-attention-emphasis' 15 | ], // values 16 | control: { 17 | type: 'select', 18 | labels: ['accent', 'danger', 'success', 'attention'] // public labels 19 | }, 20 | description: 'Colors', 21 | table: { 22 | category: 'CSS' 23 | } 24 | }, 25 | size: { 26 | options: [0, 1], // iterator 27 | mapping: ['', 'IssueLabel--big'], // values 28 | control: { 29 | type: 'select', 30 | labels: ['default', 'big'] // public labels 31 | }, 32 | description: 'Size', 33 | table: { 34 | category: 'CSS' 35 | } 36 | }, 37 | text: { 38 | name: 'stringExample', 39 | type: 'string', 40 | description: 'Label text', 41 | table: { 42 | category: 'HTML' 43 | } 44 | } 45 | } 46 | } 47 | 48 | // build every component case here in the template (private api) 49 | export const IssueLabelTemplate = ({variant, size, text}) => ( 50 | {text} 51 | ) 52 | 53 | // create a "playground" demo page that may set some defaults and allow story to access component controls 54 | export const Playground = IssueLabelTemplate.bind({}) 55 | Playground.args = { 56 | text: 'bug 🐛', 57 | variant: 'color-bg-accent-emphasis' 58 | } 59 | -------------------------------------------------------------------------------- /docs/src/stories/components/Label/Label.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | 4 | export default { 5 | title: 'Components/Label/Label', 6 | excludeStories: ['LabelTemplate'], 7 | argTypes: { 8 | inline: { 9 | control: {type: 'boolean'}, 10 | description: 'Display label inline', 11 | table: { 12 | category: 'CSS' 13 | } 14 | }, 15 | variant: { 16 | options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], // iterator 17 | mapping: [ 18 | '', 19 | 'Label--primary', 20 | 'Label--secondary', 21 | 'Label--accent', 22 | 'Label--success', 23 | 'Label--attention', 24 | 'Label--severe', 25 | 'Label--danger', 26 | 'Label--open', 27 | 'Label--closed', 28 | 'Label--done', 29 | 'Label--sponsors' 30 | ], // values 31 | control: { 32 | type: 'select', 33 | labels: ['default', 'primary', 'secondary', 'accent', 'success', 'attention', 'severe', 'danger', 'open', 'closed', 'done', 'sponsors'] 34 | }, 35 | description: 'Colors', 36 | table: { 37 | category: 'HTML' 38 | } 39 | }, 40 | size: { 41 | options: [0, 1], // iterator 42 | mapping: ['', 'Label--large'], // values 43 | control: { 44 | type: 'select', 45 | labels: ['default', 'large'] // public labels 46 | }, 47 | description: 'Colors', 48 | table: { 49 | category: 'CSS' 50 | } 51 | }, 52 | text: { 53 | name: 'text', 54 | type: 'string', 55 | description: 'Label text', 56 | table: { 57 | category: 'HTML' 58 | } 59 | } 60 | } 61 | } 62 | 63 | export const LabelTemplate = ({inline, variant, size, text}) => ( 64 | {text} 65 | ) 66 | 67 | export const Playground = LabelTemplate.bind({}) 68 | Playground.args = { 69 | text: 'Label text', 70 | inline: false, 71 | variant: 'Label--primary' 72 | } 73 | -------------------------------------------------------------------------------- /docs/src/stories/components/Label/LabelCounter.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | 4 | export default { 5 | title: 'Components/Label/Counter', 6 | excludeStories: ['LabelCounterTemplate'], 7 | argTypes: { 8 | variant: { 9 | options: [0, 1, 2], // iterator 10 | mapping: ['', 'Counter--primary', 'Counter--secondary'], // values 11 | control: { 12 | type: 'select', 13 | labels: ['default', 'primary', 'secondary'] // public labels 14 | }, 15 | table: { 16 | category: 'CSS' 17 | } 18 | }, 19 | text: { 20 | name: 'text', 21 | type: 'string', 22 | description: 'Label text', 23 | table: { 24 | category: 'HTML' 25 | } 26 | }, 27 | icon: { 28 | defaultValue: '', 29 | name: 'icon', 30 | type: 'string', 31 | description: 'Paste [Octicon](https://primer.style/octicons/) in control field', 32 | table: { 33 | category: 'HTML' 34 | } 35 | } 36 | } 37 | } 38 | 39 | // build every component case here in the template (private api) 40 | export const LabelCounterTemplate = ({variant, text, icon}) => ( 41 | 42 | <> 43 | {icon && icon} 44 | {text} 45 | 46 | 47 | ) 48 | 49 | // create a "playground" demo page that may set some defaults and allow story to access component controls 50 | export const Playground = LabelCounterTemplate.bind({}) 51 | Playground.args = { 52 | text: '23', 53 | variant: 'Counter--primary' 54 | } 55 | -------------------------------------------------------------------------------- /docs/src/stories/components/Label/LabelDiffstat.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default { 4 | title: 'Components/Label/Diffstat', 5 | excludeStories: ['LabelDiffstatTemplate'], 6 | argTypes: { 7 | diffValueIntent: { 8 | options: [0, 1, 2], // iterator 9 | mapping: ['', 'color-fg-success', 'color-fg-danger'], // values 10 | control: { 11 | type: 'select', 12 | labels: ['default', 'success', 'danger'] // public labels 13 | }, 14 | table: { 15 | category: 'CSS' 16 | } 17 | }, 18 | diffValue: { 19 | name: 'diffValue', 20 | type: 'string', 21 | description: '7', 22 | table: { 23 | category: 'HTML' 24 | } 25 | } 26 | } 27 | } 28 | 29 | // build every component case here in the template (private api) 30 | export const LabelDiffstatTemplate = ({diffValue, diffValueIntent}) => ( 31 | 32 | {diffValueIntent === 'color-fg-success' && +{diffValue}} 33 | {diffValueIntent === 'color-fg-danger' && -{diffValue}} 34 | {diffValueIntent === '' && diffValue} 35 | 36 | 37 | 38 | 39 | 40 | ) 41 | 42 | // create a "playground" demo page that may set some defaults and allow story to access component controls 43 | export const Playground = LabelDiffstatTemplate.bind({}) 44 | Playground.args = { 45 | diffValue: '7', 46 | diffValueIntent: '' 47 | } 48 | -------------------------------------------------------------------------------- /docs/src/stories/components/Label/LabelStates.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | 4 | export default { 5 | title: 'Components/Label/States', 6 | excludeStories: ['LabelStatesTemplate'], 7 | argTypes: { 8 | state: { 9 | options: [0, 1, 2, 3, 4], // iterator 10 | mapping: ['', 'State--draft', 'State--open', 'State--merged', 'State--closed'], // values 11 | control: { 12 | type: 'select', 13 | labels: ['default', 'draft', 'open', 'merged', 'closed'] // public labels 14 | }, 15 | // description: 'Colors & icons', 16 | table: { 17 | category: 'CSS' 18 | } 19 | }, 20 | size: { 21 | options: [0, 1], // iterator 22 | mapping: ['', 'State--small'], // values 23 | control: { 24 | type: 'select', 25 | labels: ['default', 'small'] // public labels 26 | }, 27 | description: 'Size', 28 | table: { 29 | category: 'CSS' 30 | } 31 | }, 32 | text: { 33 | name: 'text', 34 | type: 'string', 35 | description: 'Label text', 36 | table: { 37 | category: 'HTML' 38 | } 39 | }, 40 | icon: { 41 | defaultValue: '', 42 | name: 'icon', 43 | type: 'string', 44 | description: 'Paste [Octicon](https://primer.style/octicons/) in control field', 45 | table: { 46 | category: 'HTML' 47 | } 48 | } 49 | } 50 | } 51 | 52 | // build every component case here in the template (private api) 53 | export const LabelStatesTemplate = ({state, size, text, icon}) => ( 54 | 55 | <> 56 | {icon && } {text} 57 | 58 | 59 | ) 60 | 61 | // create a "playground" demo page that may set some defaults and allow story to access component controls 62 | export const Playground = LabelStatesTemplate.bind({}) 63 | Playground.args = { 64 | text: 'Draft', 65 | state: 'State--draft' 66 | } 67 | -------------------------------------------------------------------------------- /docs/src/stories/components/Navigation/TabNav.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | import {TabNavItemTemplate} from './TabNavItem.stories' // import stories for component compositions 4 | 5 | export default { 6 | title: 'Components/Navigation/TabNav', 7 | excludeStories: ['TabNavTemplate'], 8 | layout: 'padded', 9 | argTypes: { 10 | children: { 11 | description: 'slot for tab items', 12 | table: { 13 | category: 'HTML' 14 | } 15 | }, 16 | focusElement: { 17 | control: {type: 'boolean'}, 18 | description: 'set focus on element', 19 | table: { 20 | category: 'Interactive' 21 | } 22 | } 23 | } 24 | } 25 | 26 | const focusMethod = function getFocus() { 27 | // find the focusable element 28 | var link = document.getElementsByTagName('a')[0] 29 | // set focus on element 30 | link.focus() 31 | } 32 | 33 | export const TabNavTemplate = ({children, focusElement}) => ( 34 |
    35 | 38 | {focusElement && focusMethod()} 39 |
    40 | ) 41 | 42 | export const Playground = TabNavTemplate.bind({}) 43 | Playground.args = { 44 | focusElement: false, 45 | children: ( 46 | <> 47 | 48 | 49 | 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /docs/src/stories/components/Navigation/UnderlineNavAction.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | import {ButtonTemplate} from '../Button/Button.stories' 4 | import {LinkTemplate} from '../Link/Link.stories' 5 | 6 | export default { 7 | title: 'Components/Navigation/UnderlineNav/Action', 8 | excludeStories: ['UnderlineNavActionTemplate'], 9 | layout: 'padded', 10 | argTypes: { 11 | semanticItemType: { 12 | options: ['button', 'link'], 13 | control: { 14 | type: 'inline-radio' 15 | }, 16 | description: 'item can be a button or a link', 17 | table: { 18 | category: 'HTML' 19 | } 20 | }, 21 | label: { 22 | name: 'label', 23 | type: 'string', 24 | description: 'Item label text', 25 | table: { 26 | category: 'HTML' 27 | } 28 | }, 29 | focusElement: { 30 | control: {type: 'boolean'}, 31 | description: 'set manual focus on item', 32 | table: { 33 | category: 'Interactive' 34 | } 35 | } 36 | } 37 | } 38 | 39 | export const UnderlineNavActionTemplate = ({semanticItemType, label, focusElement}) => { 40 | return ( 41 |
    42 | {semanticItemType === 'button' ? ( 43 | 44 | ) : ( 45 | 46 | )} 47 |
    48 | ) 49 | } 50 | 51 | export const Playground = UnderlineNavActionTemplate.bind({}) 52 | Playground.args = { 53 | semanticItemType: 'button', 54 | label: 'Action', 55 | focusElement: false 56 | } 57 | -------------------------------------------------------------------------------- /docs/src/stories/components/NavigationList/NavigationListDivider.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {NavigationListTemplate} from './NavigationList.stories' 3 | import {DividerTemplate} from '../../ui-patterns/ActionList/ActionListDivider.stories.jsx' 4 | 5 | export default { 6 | title: 'Components/NavigationList/NavigationListDivider', 7 | excludeStories: ['NavigationListDividerTemplate'], 8 | argTypes: { 9 | variant: { 10 | options: [0, 1], // iterator 11 | mapping: ['', 'ActionList-sectionDivider--filled'], // values 12 | control: { 13 | type: 'inline-radio', 14 | labels: ['subtle', 'filled'] 15 | }, 16 | table: { 17 | category: 'CSS' 18 | } 19 | }, 20 | title: { 21 | defaultValue: '', 22 | type: 'string', 23 | name: 'title', 24 | description: 'string', 25 | table: { 26 | category: 'HTML' 27 | } 28 | }, 29 | description: { 30 | defaultValue: '', 31 | type: 'string', 32 | name: 'description', 33 | description: 'string', 34 | table: { 35 | category: 'HTML' 36 | } 37 | }, 38 | id: { 39 | defaultValue: '', 40 | type: 'string', 41 | name: 'id', 42 | description: 'Provide label for NavigationList
      aria-labelledby', 43 | table: { 44 | category: 'HTML' 45 | } 46 | } 47 | } 48 | } 49 | 50 | export const NavigationListDividerTemplate = DividerTemplate.bind({}) 51 | 52 | export const Playground = NavigationListDividerTemplate.bind({}) 53 | Playground.args = { 54 | title: 'Section title', 55 | description: 'Section description' 56 | } 57 | Playground.decorators = [ 58 | Story => ( 59 | 60 | 61 | 62 | ) 63 | ] 64 | -------------------------------------------------------------------------------- /docs/src/stories/components/NavigationList/NavigationListDividerFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {NavigationListTemplate} from './NavigationList.stories' 3 | import { 4 | PatternTitle, 5 | PatternFilled, 6 | PatternWithDescription, 7 | PatternSeparator 8 | } from '../../ui-patterns/ActionList/ActionListDividerFeatures.stories.jsx' 9 | 10 | export default { 11 | title: 'Components/NavigationList/NavigationListDivider/Features', 12 | decorators: [ 13 | Story => ( 14 | 15 | 16 | 17 | ) 18 | ] 19 | } 20 | 21 | export const Title = ({}) => 22 | 23 | export const Filled = ({}) => 24 | 25 | export const WithDescription = ({}) => 26 | 27 | export const Separator = ({}) => 28 | -------------------------------------------------------------------------------- /docs/src/stories/components/NavigationList/NavigationListFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | PatternShowDividers, 4 | PatternInsetPadding, 5 | PatternFullBleed, 6 | PatternNestedGroup 7 | } from '../../ui-patterns/ActionList/ActionListFeatures.stories.jsx' 8 | 9 | export default { 10 | title: 'Components/NavigationList/NavigationList/Features' 11 | } 12 | 13 | export const ShowDividers = ({}) => 14 | 15 | export const InsetPadding = ({}) => 16 | 17 | export const FullBleed = ({}) => 18 | 19 | export const NestedGroup = ({}) => 20 | -------------------------------------------------------------------------------- /docs/src/stories/components/TreeView/TreeView.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {ActionListTreeViewTemplate} from '../../ui-patterns/ActionList/ActionListTree.stories.jsx' 3 | 4 | export default { 5 | title: 'Components/TreeView/TreeView', 6 | excludeStories: ['TreeViewTemplate'], 7 | layout: 'padded', 8 | argTypes: { 9 | showGroupIcon: { 10 | control: {type: 'boolean'}, 11 | description: 'show subgroup leading icon', 12 | table: { 13 | category: 'Interactive' 14 | } 15 | }, 16 | showSubItemIcon: { 17 | control: {type: 'boolean'}, 18 | description: 'show subgroup item leading icon', 19 | table: { 20 | category: 'Interactive' 21 | } 22 | }, 23 | text: { 24 | defaultValue: '', 25 | type: 'string', 26 | name: 'title', 27 | description: 'string', 28 | table: { 29 | category: 'HTML' 30 | } 31 | }, 32 | truncateItem: { 33 | defaultValue: false, 34 | control: {type: 'boolean'}, 35 | table: { 36 | category: 'CSS' 37 | } 38 | } 39 | } 40 | } 41 | 42 | export const TreeViewTemplate = ActionListTreeViewTemplate.bind({}) 43 | 44 | export const Playground = TreeViewTemplate.bind({}) 45 | Playground.args = { 46 | showSubItemIcon: true, 47 | showGroupIcon: true, 48 | text: 'item' 49 | } 50 | -------------------------------------------------------------------------------- /docs/src/stories/helpers/ColorBlock.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | const ColorBlock = ({backgroundColor, showValueLabel}) => { 5 | return ( 6 |
      7 |
      8 | {showValueLabel &&
      {backgroundColor}
      } 9 |
      10 | ) 11 | } 12 | 13 | ColorBlock.propTypes = { 14 | backgroundColor: PropTypes.string, 15 | showValueLabel: PropTypes.bool 16 | } 17 | 18 | ColorBlock.defaultProps = { 19 | backgroundColor: null, 20 | showValueLabel: false 21 | } 22 | 23 | export default ColorBlock 24 | -------------------------------------------------------------------------------- /docs/src/stories/helpers/ConditionalWrapper.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // reference https://gist.github.com/kitze/23d82bb9eb0baabfd03a6a720b1d637f 4 | 5 | const ConditionalWrapper = ({condition, wrap, children}) => (condition ? wrap(children) : children) 6 | 7 | export default ConditionalWrapper 8 | -------------------------------------------------------------------------------- /docs/src/stories/helpers/code-snippet-html-helper.js: -------------------------------------------------------------------------------- 1 | import {renderToStaticMarkup} from 'react-dom/server' 2 | import {AllHtmlEntities} from 'html-entities' 3 | import prettier from 'prettier' 4 | import HTMLParser from 'prettier/parser-html' 5 | const entities = new AllHtmlEntities() 6 | 7 | export default story => 8 | prettier.format(entities.decode(renderToStaticMarkup(story())), { 9 | parser: 'html', 10 | plugins: [HTMLParser], 11 | htmlWhitespaceSensitivity: 'ignore', 12 | bracketSameLine: 'false' 13 | }) 14 | -------------------------------------------------------------------------------- /docs/src/stories/helpers/pageLayoutBehavior.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | export default function PageLayoutBehavior() { 3 | 4 | const pageLayoutSelector = '.PageLayout.PageLayout--responsive-separateRegions'; 5 | const primaryRegionSelector = 'PageLayout--responsive-primary'; 6 | 7 | const detectPageLayoutHash = () => { 8 | 9 | const pageLayout = document.querySelector(pageLayoutSelector); 10 | 11 | let dest; 12 | if (location.hash === '') { 13 | dest = pageLayout.getAttribute('data-primary-region'); 14 | } else if (location.hash === '#pane') { 15 | dest = 'pane'; 16 | } else if (location.hash === '#content') { 17 | dest = 'content'; 18 | } else { 19 | return; 20 | } 21 | 22 | pageLayout.setAttribute('data-current-region', dest); 23 | 24 | if (dest === 'pane') { 25 | pageLayout.classList.replace(primaryRegionSelector + '-content', primaryRegionSelector + '-pane'); 26 | } else { 27 | pageLayout.classList.replace(primaryRegionSelector + '-pane', primaryRegionSelector + '-content'); 28 | } 29 | }; 30 | 31 | window.addEventListener("hashchange", () => { 32 | detectPageLayoutHash(); 33 | }); 34 | 35 | document.addEventListener('DOMContentLoaded', (event) => { 36 | const pageLayout = document.querySelector(pageLayoutSelector); 37 | const primaryRegion = pageLayout.classList.contains(primaryRegionSelector + '-pane') ? 'pane' : 'content'; 38 | 39 | if (pageLayout.getAttribute('data-primary-region') === null) { 40 | pageLayout.setAttribute('data-primary-region', primaryRegion); 41 | } 42 | 43 | detectPageLayoutHash(); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /docs/src/stories/helpers/storybook-styles.scss: -------------------------------------------------------------------------------- 1 | // color blocks 2 | 3 | .colorBlockWrap { 4 | display: flex; 5 | flex-direction: row; 6 | flex-wrap: wrap; 7 | gap: 1rem; 8 | } 9 | 10 | .colorBlockItem { 11 | aspect-ratio: 1/1; 12 | width: 100px; 13 | } 14 | 15 | .toc { 16 | list-style: none !important; 17 | padding: 0 !important; 18 | li { 19 | margin-left: 0 !important; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/src/stories/helpers/useToggle.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | export default function useToggle(initialValue = false) { 3 | const [value, setValue] = React.useState(initialValue) 4 | const toggle = React.useCallback(() => { 5 | setValue(v => !v) 6 | }, []) 7 | return [value, toggle] 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/stories/rails-form-framework/RadioFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {RadioTemplate} from './Radio.stories.jsx' 3 | 4 | export default { 5 | title: 'Rails Forms/Radio/Features' 6 | } 7 | 8 | export const MultiRadios = ({}) => ( 9 |
      10 | 11 | 12 | 13 | 14 | ) 15 | -------------------------------------------------------------------------------- /docs/src/stories/ui-patterns/ActionList/ActionListDividerFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {ListTemplate} from './ActionList.stories' 3 | import {DividerTemplate} from './ActionListDivider.stories' 4 | 5 | export default { 6 | title: 'UI Patterns/ActionList/ActionListDivider/Features', 7 | decorators: [ 8 | Story => ( 9 | 10 | 11 | 12 | ) 13 | ] 14 | } 15 | 16 | export const PatternTitle = DividerTemplate.bind({}) 17 | PatternTitle.storyName = 'Title' 18 | PatternTitle.args = { 19 | title: 'List group title' 20 | } 21 | 22 | export const PatternFilled = DividerTemplate.bind({}) 23 | PatternFilled.storyName = 'Filled' 24 | PatternFilled.args = { 25 | variant: 'ActionList-sectionDivider--filled' 26 | } 27 | 28 | export const PatternWithDescription = DividerTemplate.bind({}) 29 | PatternWithDescription.storyName = 'With description' 30 | PatternWithDescription.args = { 31 | title: 'List group title', 32 | description: 'Group description' 33 | } 34 | 35 | export const PatternSeparator = DividerTemplate.bind({}) 36 | PatternSeparator.storyName = 'Separator' 37 | -------------------------------------------------------------------------------- /docs/src/stories/ui-patterns/ActionList/ActionListFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | import {ListTemplate} from './ActionList.stories' 4 | import {ListItemTemplate} from './ActionListItem.stories' 5 | 6 | export default { 7 | title: 'UI Patterns/ActionList/ActionList/Features' 8 | } 9 | 10 | export const PatternShowDividers = ListTemplate.bind({}) 11 | PatternShowDividers.storyName = 'Show dividers' 12 | PatternShowDividers.args = { 13 | showDividers: true, 14 | children: ( 15 | <> 16 | 17 | 18 | 19 | 20 | ) 21 | } 22 | 23 | export const PatternInsetPadding = ListTemplate.bind({}) 24 | PatternInsetPadding.storyName = 'Inset padding' 25 | PatternInsetPadding.args = { 26 | listPadding: null, 27 | children: ( 28 | <> 29 | 30 | 31 | 32 | 33 | ) 34 | } 35 | 36 | export const PatternFullBleed = ListTemplate.bind({}) 37 | PatternFullBleed.storyName = 'Full bleed' 38 | PatternFullBleed.args = { 39 | listPadding: 'ActionList--full', 40 | children: ( 41 | <> 42 | 43 | 44 | 45 | 46 | ) 47 | } 48 | 49 | export const PatternNestedGroup = ListTemplate.bind({}) 50 | PatternNestedGroup.storyName = 'Nested group' 51 | PatternNestedGroup.args = { 52 | listType: 'nested', 53 | children: ( 54 | <> 55 | 56 | 57 | 58 | 59 | ) 60 | } 61 | -------------------------------------------------------------------------------- /docs/src/stories/ui-patterns/ActionList/ActionListTreeFeatures.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {ActionListTreeViewTemplate} from './ActionListTree.stories' 3 | 4 | export default { 5 | title: 'UI Patterns/ActionList/ActionTreeView/Features' 6 | } 7 | 8 | export const TruncateText = ActionListTreeViewTemplate.bind({}) 9 | TruncateText.args = { 10 | truncateItem: true, 11 | text: 'Super duper long text that will truncate on smaller width rows' 12 | } 13 | 14 | export const WrapText = ActionListTreeViewTemplate.bind({}) 15 | WrapText.args = { 16 | text: 'Super duper long text that will wrap on smaller width rows' 17 | } 18 | -------------------------------------------------------------------------------- /docs/src/stories/ui-patterns/ActionList/uipatterns.stories.mdx: -------------------------------------------------------------------------------- 1 | import {Meta} from '@storybook/addon-docs' 2 | 3 | 4 | 5 | ## UI Patterns 6 | 7 | This directory contains pattern level stories that are used to compose component level stories. In general these stories consist of all markup/css that make up an overall "pattern" while component stories are more refined and focused on their own features and intent. 8 | 9 | As an example, Overlay is a pattern used by Dialog, Anchored overlay, and "dropdown" type scenarios. Overlay is a set of styles reused for those core components, and provides its own set of stories to be inherited from the UI Patterns directory. 10 | 11 | Consider these stories "private API" and use the stories within the `Components` directory as an official API reference. 12 | -------------------------------------------------------------------------------- /docs/src/table.js: -------------------------------------------------------------------------------- 1 | import {Box} from '@primer/components' 2 | import PropTypes from 'prop-types' 3 | import React from 'react' 4 | import styled from 'styled-components' 5 | import {fontSize} from 'styled-system' 6 | 7 | const Table = styled.table` 8 | display: table !important; 9 | width: 100%; 10 | border-collapse: separate; 11 | border-spacing: ${props => props.borderSpacing}; 12 | ${fontSize}; 13 | 14 | tr, 15 | td, 16 | th { 17 | border: 0 !important; 18 | } 19 | 20 | caption, 21 | td, 22 | th { 23 | padding: ${props => props.cellPadding} !important; 24 | text-align: left; 25 | } 26 | 27 | tr { 28 | background-color: transparent !important; 29 | } 30 | ` 31 | 32 | Table.propTypes = { 33 | borderSpacing: PropTypes.any, 34 | cellPadding: PropTypes.any, 35 | ...fontSize.propTypes 36 | } 37 | 38 | Table.defaultProps = { 39 | borderSpacing: 0, 40 | cellPadding: '4px 8px', 41 | fontSize: [1, 1, 2] 42 | } 43 | 44 | Table.Row = props => 45 | Table.Cell = props => 46 | 47 | export default Table 48 | -------------------------------------------------------------------------------- /docs/src/typography-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArthurClemens/css/f3acb2b116f10955e1ba4f1a35aa874eed019ceb/docs/src/typography-image.png -------------------------------------------------------------------------------- /docs/src/utilities-image.svg: -------------------------------------------------------------------------------- 1 | utilities 2 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const autoprefixer = require('autoprefixer') 2 | const sass = require('@koddsson/postcss-sass') 3 | const scss = require('postcss-scss') 4 | const scssImport = require('postcss-import') 5 | const {join} = require('path') 6 | 7 | module.exports = { 8 | map: { 9 | sourcesContent: false, 10 | annotation: true 11 | }, 12 | customSyntax: scss, 13 | parser: scss, 14 | plugins: [ 15 | scssImport, 16 | sass({ 17 | includePaths: [join(__dirname, 'node_modules')], 18 | outputStyle: process.env.CSS_MINIFY === '0' ? 'expanded' : 'compressed' 19 | }), 20 | autoprefixer, 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require('@github/prettier-config') 2 | -------------------------------------------------------------------------------- /script/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": 0 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /script/build-css.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import {globby} from 'globby' 3 | import compiler from './primer-css-compiler.js' 4 | import {dirname, join} from 'path' 5 | 6 | import fsExtra from 'fs-extra' 7 | const {mkdirp, readFile, writeFile} = fsExtra 8 | 9 | 10 | const inDir = 'src' 11 | const outDir = 'dist' 12 | const bundleNames = { 13 | 'index.scss': 'primer' 14 | } 15 | 16 | const files = await globby([`${inDir}/**/index.scss`]) 17 | await mkdirp(outDir) 18 | const inPattern = new RegExp(`^${inDir}/`) 19 | const tasks = files.map(async from => { 20 | const path = from.replace(inPattern, '') 21 | const name = bundleNames[path] || dirname(path).replace(/\//g, '-') 22 | 23 | const to = join(outDir, `${name}.css`) 24 | 25 | const result = await compiler(await readFile(from, 'utf8'), {from, to}) 26 | 27 | await Promise.all([ 28 | writeFile(to, result.css, 'utf8'), 29 | ]) 30 | }) 31 | 32 | await Promise.all(tasks) 33 | -------------------------------------------------------------------------------- /script/build-docs: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Build the base project so we can pull out the JSON data 4 | yarn dist 5 | cp -rf dist docs 6 | 7 | # Now build the docs site using that data 8 | cd docs 9 | 10 | if [ -n "$1" ]; then 11 | CI=true yarn gatsby build && yarn build:storybook preview 12 | else 13 | CI=true yarn gatsby build --prefix-paths && yarn build:storybook 14 | fi 15 | -------------------------------------------------------------------------------- /script/prepublish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # generate the build directory 5 | yarn dist > /dev/null 6 | 7 | files=$(git ls-files src | sed -e 's#^src/##' | sed -e 's#/.*$##' | sort -u) 8 | echo $files > publish-files.log 9 | cd src 10 | cp -rv $files .. 11 | cd - 12 | -------------------------------------------------------------------------------- /script/pretest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | mkdir -p tmp 5 | cd tmp 6 | echo "{\"package\":\"tmp\",\"version\":\"0.0.0\"}" > package.json 7 | yarn add --force @primer/css@latest 8 | -------------------------------------------------------------------------------- /script/primer-css-compiler.js: -------------------------------------------------------------------------------- 1 | import postcss from 'postcss' 2 | import postCssConfig from '../postcss.config.cjs' 3 | 4 | export default async function compiler(css, options) { 5 | const { plugins, ...config } = postCssConfig 6 | 7 | const result = await postcss(plugins).process(css, { 8 | ...config, 9 | ...options 10 | }) 11 | return result 12 | } 13 | -------------------------------------------------------------------------------- /script/selector-diff-report: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | function log() { 5 | echo "$@" 1>&2 6 | } 7 | 8 | function warn() { 9 | echo "$@" 1>&2 10 | } 11 | 12 | pkg="@primer/css" 13 | path="dist/stats/primer.json" 14 | cp "tmp/node_modules/@primer/css/dist/stats/primer.json" before.json 15 | 16 | cp $path after.json 17 | 18 | key=".selectors.values[]" 19 | jq -r $key before.json | sort | uniq > before.txt 20 | jq -r $key after.json | sort | uniq > after.txt 21 | 22 | diff -U 1 {before,after}.txt 23 | 24 | rm {before,after}.{json,txt} 25 | -------------------------------------------------------------------------------- /src/actionlist/action-list-item-divider.scss: -------------------------------------------------------------------------------- 1 | // empty divider 2 | 3 | .ActionList-sectionDivider { 4 | // has children 5 | &:not(:empty) { 6 | display: flex; 7 | padding: ($spacer-1 * 1.5) $spacer-2; 8 | font-size: $font-size-small; 9 | font-weight: $font-weight-bold; 10 | color: var(--color-fg-muted); 11 | flex-direction: column; 12 | } 13 | 14 | // no children 15 | &:empty { 16 | display: block; 17 | height: 1px; 18 | padding: 0; 19 | // stylelint-disable-next-line primer/spacing 20 | margin: ($spacer-2 - 1px) ($spacer-2 * -1) $spacer-2; 21 | list-style: none; 22 | background: var(--color-action-list-item-inline-divider); 23 | border: 0; 24 | } 25 | 26 | .ActionList-sectionDivider-title { 27 | font-size: $font-size-small; 28 | font-weight: $font-weight-bold; 29 | color: var(--color-fg-muted); 30 | } 31 | } 32 | 33 | .ActionList-sectionDivider--filled { 34 | margin: $spacer-2 ($spacer-2 * -1); 35 | background: var(--color-canvas-subtle); 36 | border-top: $border-width $border-style var(--color-action-list-item-inline-divider); 37 | border-bottom: $border-width $border-style var(--color-action-list-item-inline-divider); 38 | 39 | // if no children, treat as divider 40 | &:empty { 41 | height: $spacer-2; 42 | box-sizing: border-box; 43 | } 44 | 45 | &:first-child { 46 | margin-top: 0; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/actionlist/action-list-variables.scss: -------------------------------------------------------------------------------- 1 | $actionList-item-height-sm: $spacer-2 * 2.5 !default; 2 | $actionList-item-label-line-height: $spacer-2 * 2.5 !default; 3 | $actionList-item-padding-vertical-md: $spacer-2 * 1.25 !default; 4 | $actionList-item-padding-vertical-lg: $spacer-2 * 1.75 !default; 5 | $actionList-item-padding-vertical: $spacer-1 * 1.5 !default; 6 | $actionList-item-padding-horizontal: $spacer-2 !default; 7 | $actionList-item-bg-transition: background 33.333ms linear !default; // 2 frames on a 60hz monitor 8 | $actionList-item-checkmark-transition-timing: 50ms !default; 9 | -------------------------------------------------------------------------------- /src/actionlist/action-list.scss: -------------------------------------------------------------------------------- 1 | //
        2 | .ActionList { 3 | padding: $spacer-2; 4 | } 5 | 6 | // full bleed 7 | .ActionList--full { 8 | padding: 0; 9 | } 10 | 11 | // nested list within main ActionList 12 | .ActionList--subGroup { 13 | padding: 0; 14 | } 15 | 16 | // dividers 17 | 18 | .ActionList--divided { 19 | .ActionList-item-label::before { 20 | position: absolute; 21 | top: -$actionList-item-padding-vertical; 22 | display: block; 23 | width: 100%; 24 | height: 1px; 25 | content: ''; 26 | background: var(--color-action-list-item-inline-divider); 27 | } 28 | 29 | // if descriptionWrap--inline exists, move pseudo divider to wrapper 30 | .ActionList-item-descriptionWrap--inline { 31 | &::before { 32 | position: absolute; 33 | top: -$actionList-item-padding-vertical; 34 | display: block; 35 | width: 100%; 36 | height: $border-width; 37 | content: ''; 38 | background: var(--color-action-list-item-inline-divider); 39 | } 40 | 41 | // unset the default label pseudo 42 | .ActionList-item-label::before { 43 | content: unset; 44 | } 45 | } 46 | 47 | // hide divider if item is active 48 | .ActionList-item--navActive { 49 | // stylelint-disable-next-line selector-max-specificity, selector-max-compound-selectors 50 | .ActionList-item-label::before, 51 | + .ActionList-item .ActionList-item-label::before { 52 | visibility: hidden; 53 | } 54 | } 55 | } 56 | 57 | // hide if item is first of type with label::before, or is the first item after a sectionDivider 58 | .ActionList-item:first-of-type .ActionList-item-label::before, 59 | .ActionList-sectionDivider + .ActionList-item .ActionList-item-label::before { 60 | visibility: hidden; 61 | } 62 | 63 | // hide if item is first of type with label::before, or is the first item after a sectionDivider 64 | .ActionList-item:first-of-type .ActionList-item-descriptionWrap--inline::before, 65 | .ActionList-sectionDivider + .ActionList-item .ActionList-item-descriptionWrap--inline::before { 66 | visibility: hidden; 67 | } 68 | -------------------------------------------------------------------------------- /src/actionlist/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | @import './action-list-variables.scss'; 3 | @import './action-list.scss'; 4 | @import './action-list-tree.scss'; 5 | @import './action-list-item.scss'; 6 | @import './action-list-item-divider.scss'; 7 | -------------------------------------------------------------------------------- /src/alerts/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "alerts" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `alerts` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/alerts/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/alerts.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/alerts/index.scss: -------------------------------------------------------------------------------- 1 | // support files 2 | @import '../support/index.scss'; 3 | @import './flash.scss'; 4 | -------------------------------------------------------------------------------- /src/autocomplete/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "autocomplete" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `autocomplete` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/autocomplete/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/autocomplete.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/autocomplete/index.scss: -------------------------------------------------------------------------------- 1 | // support files 2 | @import '../support/index.scss'; 3 | @import './autocomplete.scss'; 4 | @import './suggester.scss'; 5 | -------------------------------------------------------------------------------- /src/avatars/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "avatars" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `avatars` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/avatars/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/avatars.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/avatars/avatar-parent-child.scss: -------------------------------------------------------------------------------- 1 | // .avatar-parent-child is when you see a small avatar at the bottom right 2 | // corner of a larger avatar. 3 | // 4 | // No Styleguide version 5 | .avatar-parent-child { 6 | position: relative; 7 | } 8 | 9 | .avatar-child { 10 | position: absolute; 11 | right: -15%; 12 | bottom: -9%; 13 | background-color: var(--color-canvas-default); // For transparent backgrounds 14 | // stylelint-disable-next-line primer/borders 15 | border-radius: $border-radius-1; 16 | box-shadow: var(--color-avatar-child-shadow); 17 | } 18 | -------------------------------------------------------------------------------- /src/avatars/avatar.scss: -------------------------------------------------------------------------------- 1 | .avatar { 2 | display: inline-block; 3 | overflow: hidden; // Ensure page layout in Firefox should images fail to load 4 | line-height: $lh-condensed-ultra; 5 | vertical-align: middle; 6 | background-color: var(--color-avatar-bg); // adds opaque bg to transparent avatars 7 | border-radius: $border-radius; 8 | flex-shrink: 0; 9 | // stylelint-disable-next-line primer/box-shadow 10 | box-shadow: 0 0 0 1px var(--color-avatar-border); 11 | } 12 | 13 | .avatar-link { 14 | float: left; 15 | line-height: $lh-condensed-ultra; 16 | } 17 | 18 | // User for example on /stars and /user for grids of avatars 19 | .avatar-group-item { 20 | display: inline-block; 21 | // stylelint-disable-next-line primer/spacing 22 | margin-bottom: 3px; 23 | } 24 | 25 | // Border radius 26 | 27 | .avatar-1, 28 | .avatar-2, 29 | .avatar-small { 30 | // stylelint-disable-next-line primer/borders 31 | border-radius: $border-radius-1; 32 | } 33 | 34 | // Sizes 35 | 36 | @mixin avatar-size( $size ) { 37 | width: $size; 38 | height: $size; 39 | } 40 | 41 | .avatar-1 { @include avatar-size( $size-1 ); } 42 | .avatar-2 { @include avatar-size( $size-2 ); } 43 | .avatar-3 { @include avatar-size( $size-3 ); } 44 | .avatar-4 { @include avatar-size( $size-4 ); } 45 | .avatar-5 { @include avatar-size( $size-5 ); } 46 | .avatar-6 { @include avatar-size( $size-6 ); } 47 | .avatar-7 { @include avatar-size( $size-7 ); } 48 | .avatar-8 { @include avatar-size( $size-8 ); } 49 | -------------------------------------------------------------------------------- /src/avatars/circle-badge.scss: -------------------------------------------------------------------------------- 1 | // Circle badge icon with drop shadow for icons and logos 2 | 3 | .CircleBadge { 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | background-color: var(--color-canvas-default); 8 | border-radius: 50%; 9 | box-shadow: var(--color-shadow-medium); 10 | } 11 | 12 | .CircleBadge-icon { 13 | max-width: 60% !important; 14 | height: auto !important; 15 | max-height: 55% !important; 16 | } 17 | 18 | // Small badge 19 | .CircleBadge--small { 20 | width: 56px; 21 | height: 56px; 22 | } 23 | 24 | // Medium badge 25 | .CircleBadge--medium { 26 | width: 96px; 27 | height: 96px; 28 | } 29 | 30 | // Large badge 31 | .CircleBadge--large { 32 | width: 128px; 33 | height: 128px; 34 | } 35 | 36 | // Dashed line that connects badges.. 37 | // Wrap around 2 or more badges to create a horizonal line: 38 | 39 | .DashedConnection { 40 | position: relative; 41 | 42 | &::before { 43 | position: absolute; 44 | top: 50%; 45 | left: 0; 46 | width: 100%; 47 | content: ''; 48 | // stylelint-disable-next-line primer/borders 49 | border-bottom: 2px dashed var(--color-border-default); 50 | } 51 | 52 | .CircleBadge { 53 | position: relative; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/avatars/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | 3 | // Avatars 4 | @import './avatar.scss'; 5 | @import './avatar-parent-child.scss'; 6 | @import './avatar-stack.scss'; 7 | @import './circle-badge.scss'; 8 | -------------------------------------------------------------------------------- /src/base/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "base" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `base` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/base/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/base.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/base/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | @import './normalize.scss'; 3 | @import './base.scss'; 4 | @import './kbd.scss'; 5 | @import './typography-base.scss'; 6 | @import './octicons.scss'; 7 | -------------------------------------------------------------------------------- /src/base/kbd.scss: -------------------------------------------------------------------------------- 1 | // Keyboard shortcuts 2 | // stylelint-disable selector-max-type 3 | 4 | kbd { 5 | display: inline-block; 6 | padding: ($spacer-1 - 1) ($spacer-1 + 1); 7 | font: 11px $mono-font; 8 | // stylelint-disable-next-line primer/typography 9 | line-height: 10px; 10 | color: var(--color-fg-default); 11 | vertical-align: middle; 12 | background-color: var(--color-canvas-subtle); 13 | // stylelint-disable-next-line primer/borders 14 | border: $border-style $border-width var(--color-neutral-muted); 15 | border-bottom-color: var(--color-neutral-muted); 16 | border-radius: $border-radius; 17 | // stylelint-disable-next-line primer/box-shadow 18 | box-shadow: inset 0 -1px 0 var(--color-neutral-muted); 19 | } 20 | -------------------------------------------------------------------------------- /src/base/octicons.scss: -------------------------------------------------------------------------------- 1 | .octicon { 2 | display: inline-block; 3 | overflow: visible !important; 4 | vertical-align: text-bottom; 5 | fill: currentColor; 6 | } 7 | -------------------------------------------------------------------------------- /src/base/typography-base.scss: -------------------------------------------------------------------------------- 1 | // Headings 2 | // -------------------------------------------------- 3 | // stylelint-disable selector-max-type 4 | h1, 5 | h2, 6 | h3, 7 | h4, 8 | h5, 9 | h6 { 10 | margin-top: 0; 11 | margin-bottom: 0; 12 | } 13 | 14 | h1 { @include h1; } 15 | h2 { @include h2; } 16 | h3 { @include h3; } 17 | h4 { @include h4; } 18 | h5 { @include h5; } 19 | h6 { @include h6; } 20 | 21 | // Body text 22 | // -------------------------------------------------- 23 | 24 | p { 25 | margin-top: 0; 26 | // stylelint-disable-next-line primer/spacing 27 | margin-bottom: 10px; 28 | } 29 | 30 | small { 31 | // stylelint-disable-next-line primer/typography 32 | font-size: 90%; 33 | } 34 | 35 | blockquote { 36 | margin: 0; 37 | } 38 | 39 | // Lists 40 | // -------------------------------------------------- 41 | 42 | ul, 43 | ol { 44 | padding-left: 0; 45 | margin-top: 0; 46 | margin-bottom: 0; 47 | } 48 | 49 | ol ol, 50 | ul ol { 51 | list-style-type: lower-roman; 52 | } 53 | 54 | ul ul ol, 55 | ul ol ol, 56 | ol ul ol, 57 | ol ol ol { 58 | list-style-type: lower-alpha; 59 | } 60 | 61 | dd { 62 | margin-left: 0; 63 | } 64 | 65 | // Monospaced 66 | // -------------------------------------------------- 67 | 68 | tt, 69 | code, 70 | samp { 71 | font-family: $mono-font; 72 | font-size: $font-size-small; 73 | } 74 | 75 | pre { 76 | margin-top: 0; 77 | margin-bottom: 0; 78 | font-family: $mono-font; 79 | font-size: $font-size-small; 80 | } 81 | 82 | // Octicons 83 | // -------------------------------------------------- 84 | 85 | // Move this over here as a temporary override to the octicons source repo 86 | // instead of updating that upstream. 87 | .octicon { 88 | vertical-align: text-bottom; 89 | } 90 | -------------------------------------------------------------------------------- /src/blankslate/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "blankslate" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `blankslate` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/blankslate/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/blankslate.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/blankslate/blankslate.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable selector-max-type 2 | .blankslate { 3 | position: relative; 4 | padding: $spacer-5; 5 | text-align: center; 6 | 7 | p { 8 | color: var(--color-fg-muted); 9 | } 10 | 11 | code { 12 | // stylelint-disable-next-line primer/spacing 13 | padding: 2px 5px 3px; 14 | font-size: $h5-size; 15 | background: var(--color-canvas-default); 16 | border: $border-width $border-style var(--color-border-muted); 17 | border-radius: $border-radius; 18 | } 19 | 20 | img { 21 | width: 56px; 22 | height: 56px; 23 | } 24 | } 25 | 26 | .blankslate-icon { 27 | margin-right: $spacer-1; 28 | margin-bottom: $spacer-2; 29 | margin-left: $spacer-1; 30 | color: var(--color-fg-muted); 31 | } 32 | 33 | .blankslate-image { 34 | margin-bottom: $spacer-3; 35 | } 36 | 37 | .blankslate-heading { 38 | margin-bottom: $spacer-1; 39 | } 40 | 41 | .blankslate-action { 42 | margin-top: $spacer-3; 43 | 44 | &:first-of-type { 45 | margin-top: $spacer-4; 46 | } 47 | 48 | &:last-of-type { 49 | margin-bottom: $spacer-2; 50 | } 51 | } 52 | 53 | .blankslate-capped { 54 | border-radius: 0 0 $border-radius $border-radius; 55 | } 56 | 57 | .blankslate-spacious { 58 | padding: ($spacer-6 * 2) $spacer-6; 59 | } 60 | 61 | .blankslate-narrow { 62 | max-width: 485px; 63 | margin: 0 auto; 64 | } 65 | 66 | // was .large-format 67 | // QUESTION: should we deprecate this? 68 | .blankslate-large { 69 | img { 70 | width: 80px; 71 | height: 80px; 72 | } 73 | 74 | h3 { 75 | margin: $spacer-3 0; 76 | //font-size: $h3-size; // This doesn't actually make the text larger. Should this be $h2-size? 77 | font-size: $h2-size; 78 | } 79 | 80 | p { 81 | font-size: $h4-size; 82 | } 83 | } 84 | 85 | // was .clean-background 86 | // TO DO: deprecate this and use utility instead 87 | .blankslate-clean-background { 88 | border: 0; 89 | } 90 | -------------------------------------------------------------------------------- /src/blankslate/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | @import './blankslate.scss'; 3 | -------------------------------------------------------------------------------- /src/box/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "box" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `box` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/box/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/box.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/box/box-overlay.scss: -------------------------------------------------------------------------------- 1 | .Box--overlay { 2 | // stylelint-disable-next-line primer/responsive-widths 3 | width: 448px; 4 | margin-right: auto; 5 | margin-left: auto; 6 | background-color: var(--color-canvas-default); 7 | background-clip: padding-box; 8 | border-color: var(--color-border-default); 9 | // stylelint-disable-next-line primer/box-shadow 10 | box-shadow: 0 0 18px rgba(0, 0, 0, 0.4); 11 | 12 | .Box-header { 13 | margin: 0; 14 | border-width: 0; 15 | border-bottom-width: $border-width; 16 | border-top-left-radius: $border-radius; 17 | border-top-right-radius: $border-radius; 18 | } 19 | } 20 | 21 | .Box-overlay--narrow { 22 | width: 320px; 23 | } 24 | 25 | .Box-overlay--wide { 26 | // stylelint-disable-next-line primer/responsive-widths 27 | width: 640px; 28 | } 29 | 30 | .Box-body { 31 | &.scrollable-overlay { 32 | max-height: 400px; 33 | overflow-y: scroll; 34 | } 35 | 36 | .help { 37 | padding-top: $spacer-2; 38 | margin: 0; 39 | color: var(--color-fg-muted); 40 | text-align: center; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/box/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | @import './box.scss'; 3 | @import './box-overlay.scss'; 4 | -------------------------------------------------------------------------------- /src/branch-name/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "branch-name" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `branch-name` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/branch-name/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/branch-name.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/branch-name/branch-name.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable selector-max-type, selector-no-qualifying-type 2 | 3 | // A nice way to display branch names inside the UI. Can be a link or not. 4 | 5 | .branch-name { 6 | display: inline-block; 7 | // stylelint-disable-next-line primer/spacing 8 | padding: 2px 6px; 9 | font: 12px $mono-font; 10 | color: var(--color-fg-muted); 11 | word-break: break-all; 12 | background-color: var(--color-accent-subtle); 13 | border-radius: $border-radius; 14 | 15 | .octicon { 16 | // stylelint-disable-next-line primer/spacing 17 | margin: 1px -2px 0 0; 18 | color: var(--color-fg-muted); 19 | } 20 | } 21 | 22 | // When a branch name is a link 23 | 24 | a.branch-name { 25 | color: var(--color-accent-fg); 26 | background-color: var(--color-accent-subtle); 27 | 28 | .octicon { 29 | color: var(--color-accent-fg); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/branch-name/index.scss: -------------------------------------------------------------------------------- 1 | // support files 2 | @import '../support/index.scss'; 3 | @import './branch-name.scss'; 4 | -------------------------------------------------------------------------------- /src/breadcrumb/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "breadcrumb" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `breadcrumb` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/breadcrumb/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/breadcrumb.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/breadcrumb/breadcrumb.scss: -------------------------------------------------------------------------------- 1 | .breadcrumb-item { 2 | display: inline-block; 3 | // stylelint-disable-next-line primer/spacing 4 | margin-left: -0.35em; 5 | white-space: nowrap; 6 | list-style: none; 7 | 8 | &::after { 9 | display: inline-block; 10 | height: 0.8em; 11 | margin: 0 $em-spacer-5; 12 | content: ''; 13 | // stylelint-disable-next-line primer/borders 14 | border-right: 0.1em $border-style var(--color-fg-muted); 15 | transform: rotate(15deg); 16 | } 17 | 18 | &:first-child { 19 | margin-left: 0; 20 | } 21 | } 22 | 23 | .breadcrumb-item-selected, 24 | .breadcrumb-item[aria-current]:not([aria-current='false']) { 25 | &::after { 26 | content: none; 27 | } 28 | } 29 | 30 | // stylelint-disable selector-max-type 31 | .breadcrumb-item-selected a { 32 | color: var(--color-fg-default); 33 | } 34 | -------------------------------------------------------------------------------- /src/breadcrumb/index.scss: -------------------------------------------------------------------------------- 1 | // support files 2 | @import '../support/index.scss'; 3 | @import './breadcrumb.scss'; 4 | -------------------------------------------------------------------------------- /src/buttons/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "buttons" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `buttons` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/buttons/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/buttons.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/buttons/button-group.scss: -------------------------------------------------------------------------------- 1 | // Button group 2 | // 3 | // A button group is a series of buttons laid out next to each other, all part 4 | // of one visual button, but separated by rules to be separate. 5 | 6 | .BtnGroup { 7 | display: inline-block; 8 | vertical-align: middle; 9 | 10 | @include clearfix(); 11 | 12 | // Proper spacing for multiple button groups (a la, gollum editor) 13 | + .BtnGroup, 14 | + .btn { 15 | margin-left: $spacer-1; 16 | } 17 | } 18 | 19 | .BtnGroup-item { 20 | position: relative; 21 | float: left; 22 | border-right-width: 0; 23 | border-radius: 0; 24 | 25 | &:first-child { 26 | border-top-left-radius: $border-radius; 27 | border-bottom-left-radius: $border-radius; 28 | } 29 | 30 | &:last-child { 31 | border-right-width: $border-width; 32 | border-top-right-radius: $border-radius; 33 | border-bottom-right-radius: $border-radius; 34 | } 35 | 36 | &.selected, 37 | &[aria-selected='true'], 38 | &:focus, 39 | &:active, 40 | &:hover { 41 | border-right-width: $border-width; 42 | 43 | + .BtnGroup-item, 44 | + .BtnGroup-parent .BtnGroup-item { 45 | border-left-width: 0; 46 | } 47 | } 48 | } 49 | 50 | .BtnGroup-parent { 51 | float: left; 52 | 53 | &:first-child .BtnGroup-item { 54 | border-top-left-radius: $border-radius; 55 | border-bottom-left-radius: $border-radius; 56 | } 57 | 58 | &:last-child .BtnGroup-item { 59 | border-right-width: $border-width; 60 | border-top-right-radius: $border-radius; 61 | border-bottom-right-radius: $border-radius; 62 | } 63 | 64 | .BtnGroup-item { 65 | border-right-width: 0; 66 | border-radius: 0; 67 | } 68 | 69 | &.selected, 70 | &[aria-selected='true'], 71 | &:focus, 72 | &:active, 73 | &:hover { 74 | .BtnGroup-item { 75 | border-right-width: $border-width; 76 | } 77 | 78 | + .BtnGroup-item, 79 | + .BtnGroup-parent .BtnGroup-item { 80 | border-left-width: 0; 81 | } 82 | } 83 | } 84 | 85 | // ensure that the focus ring sits above the adjacent buttons 86 | .BtnGroup-item, 87 | .BtnGroup-parent { 88 | &:focus, 89 | &:active { 90 | z-index: 1; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/buttons/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | @import './button.scss'; 3 | @import './button-group.scss'; 4 | @import './misc.scss'; 5 | -------------------------------------------------------------------------------- /src/color-modes/index.scss: -------------------------------------------------------------------------------- 1 | // All themes 2 | 3 | @import './themes/light.scss'; 4 | @import './themes/light_colorblind.scss'; 5 | @import './themes/light_high_contrast.scss'; 6 | @import './themes/light_tritanopia.scss'; 7 | @import './themes/dark.scss'; 8 | @import './themes/dark_dimmed.scss'; 9 | @import './themes/dark_high_contrast.scss'; 10 | @import './themes/dark_colorblind.scss'; 11 | @import './themes/dark_tritanopia.scss'; 12 | @import './native.scss'; 13 | -------------------------------------------------------------------------------- /src/color-modes/native.scss: -------------------------------------------------------------------------------- 1 | // color-scheme 2 | // Enables color modes for native elements 3 | 4 | @include color-mode(light) { color-scheme: light; } 5 | 6 | @include color-mode(dark) { color-scheme: dark; } 7 | 8 | [data-color-mode] { 9 | color: var(--color-fg-default); 10 | background-color: var(--color-canvas-default); 11 | } 12 | 13 | // Windows High Contrast mode 14 | 15 | // Improves focus state for various components when Windows High Contrast mode is enabled 16 | // stylelint-disable selector-max-type 17 | @media (forced-colors: active) { 18 | body { 19 | --color-accent-emphasis: Highlight; 20 | --color-fg-on-emphasis: LinkText; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/color-modes/themes/dark.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_dark.scss'; 3 | 4 | @include color-mode-theme(dark) { 5 | @include primer-colors-dark; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/dark_colorblind.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_dark_colorblind.scss'; 3 | 4 | @include color-mode-theme(dark_colorblind) { 5 | @include primer-colors-dark_colorblind; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/dark_dimmed.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_dark_dimmed.scss'; 3 | 4 | @include color-mode-theme(dark_dimmed) { 5 | @include primer-colors-dark_dimmed; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/dark_high_contrast.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_dark_high_contrast.scss'; 3 | 4 | @include color-mode-theme(dark_high_contrast) { 5 | @include primer-colors-dark_high_contrast; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/dark_tritanopia.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_dark_tritanopia.scss'; 3 | 4 | @include color-mode-theme(dark_tritanopia) { 5 | @include primer-colors-dark_tritanopia; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/light.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_light.scss'; 3 | 4 | @include color-mode-theme(light, true) { 5 | @include primer-colors-light; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/light_colorblind.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_light_colorblind.scss'; 3 | 4 | @include color-mode-theme(light_colorblind) { 5 | @include primer-colors-light_colorblind; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/light_high_contrast.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_light_high_contrast.scss'; 3 | 4 | @include color-mode-theme(light_high_contrast) { 5 | @include primer-colors-light_high_contrast; 6 | } 7 | -------------------------------------------------------------------------------- /src/color-modes/themes/light_tritanopia.scss: -------------------------------------------------------------------------------- 1 | @import '../../support/index.scss'; 2 | @import '@primer/primitives/dist/scss/colors/_light_tritanopia.scss'; 3 | 4 | @include color-mode-theme(light_tritanopia) { 5 | @include primer-colors-light_tritanopia; 6 | } 7 | -------------------------------------------------------------------------------- /src/core/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "core" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `core` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/core/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/core.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/core/index.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * @primer/css/core 3 | * http://primer.style/css 4 | * 5 | * Released under MIT license. Copyright (c) 2019 GitHub Inc. 6 | */ 7 | 8 | // Global requirements 9 | @import '../support/index.scss'; 10 | 11 | // Color modes 12 | 13 | // Core modules 14 | @import '../actionlist/index.scss'; 15 | @import '../base/index.scss'; 16 | @import '../box/index.scss'; 17 | @import '../breadcrumb/index.scss'; 18 | @import '../buttons/index.scss'; 19 | @import '../table-object/index.scss'; 20 | @import '../forms/index.scss'; 21 | @import '../layout/index.scss'; 22 | @import '../links/index.scss'; 23 | @import '../navigation/index.scss'; 24 | @import '../pagination/index.scss'; 25 | @import '../tooltips/index.scss'; 26 | @import '../truncate/index.scss'; 27 | @import '../overlay/index.scss'; 28 | 29 | // Utilities always go last so that they can override components 30 | @import '../utilities/index.scss'; 31 | -------------------------------------------------------------------------------- /src/docs.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Primer CSS 3 | * https://primer.style 4 | * 5 | * Released under MIT license. 6 | */ 7 | 8 | // Docs styles 9 | // Only meant for the docs at https://primer.style/css 10 | 11 | // CSS color variables 12 | @import './color-modes/index.scss'; 13 | 14 | // Global requirements 15 | @import './core/index.scss'; 16 | @import './product/index.scss'; 17 | @import './marketing/index.scss'; 18 | -------------------------------------------------------------------------------- /src/dropdown/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "dropdown" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `dropdown` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/dropdown/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/dropdown.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/dropdown/index.scss: -------------------------------------------------------------------------------- 1 | @import '../support/index.scss'; 2 | @import './dropdown.scss'; 3 | -------------------------------------------------------------------------------- /src/forms/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | bundle: "forms" 3 | generated: true 4 | --- 5 | 6 | # Primer CSS: `forms` bundle 7 | 8 | ## Usage 9 | 10 | Primer CSS source files are written in [SCSS]. To include this Primer CSS module in your own build, ensure that your `node_modules` directory is listed in your Sass include paths, then import it with: 11 | 12 | ```scss 13 | @import "@primer/css/forms/index.scss"; 14 | ``` 15 | 16 | ## Build 17 | 18 | The `@primer/css` npm package includes a standalone CSS build of this module in `dist/forms.css`. 19 | 20 | ## License 21 | 22 | [MIT](https://github.com/primer/css/blob/main/LICENSE) © [GitHub](https://github.com/) 23 | 24 | 25 | [scss]: https://sass-lang.com/documentation/syntax#scss 26 | -------------------------------------------------------------------------------- /src/forms/form-select.scss: -------------------------------------------------------------------------------- 1 | // Custom select 2 | // 3 | // Apply `.select` to any `