├── .nvmrc ├── .env ├── scss ├── edx │ ├── overrides │ │ ├── _badges.scss │ │ ├── _dropdowns.scss │ │ ├── _navs.scss │ │ ├── _grid.scss │ │ ├── _modals.scss │ │ ├── _alerts.scss │ │ ├── _typography.scss │ │ └── _buttons.scss │ ├── _fonts.scss │ ├── theme.scss │ ├── _overrides.scss │ ├── _functions.scss │ └── custom │ │ └── _edx-custom-card.scss ├── open-edx │ ├── overrides │ │ ├── _badges.scss │ │ ├── _dropdowns.scss │ │ ├── _navs.scss │ │ ├── _grid.scss │ │ ├── _modals.scss │ │ ├── _buttons.scss │ │ ├── _typography.scss │ │ ├── _tables.scss │ │ └── _alerts.scss │ ├── _fonts.scss │ ├── theme.scss │ ├── _overrides.scss │ └── custom │ │ └── _edx-custom-card.scss └── core │ ├── _extensions.scss │ ├── extensions │ ├── _utilities.scss │ └── _buttons.scss │ └── core.scss ├── .npmrc ├── public ├── favicon.ico ├── manifest.json ├── 404.html └── index.html ├── .gitignore ├── .npmignore ├── src ├── pages │ ├── Basics.Themes.js │ ├── GettingStarted.js │ ├── bootstrap │ │ ├── Badge.js │ │ ├── Pagination.js │ │ ├── Breadcrumb.js │ │ ├── Alerts.js │ │ ├── Modal.js │ │ ├── LayoutUtils.js │ │ ├── Jumbotron.js │ │ ├── Progress.js │ │ ├── Tables.js │ │ ├── Spinners.js │ │ ├── Navs.js │ │ ├── Dropdowns.js │ │ └── Collapse.js │ ├── Basics.MiscBasics.js │ ├── Miscellaneous.js │ ├── Overview.js │ ├── Basics.Typography.js │ ├── Basics.ButtonsAndLinks.js │ ├── Examples.js │ ├── Basics.js │ ├── Navigation.js │ ├── Basics.Colors.js │ └── Forms.js ├── index.js ├── scss │ └── bootstrap-docs-4-2 │ │ ├── _anchor.scss │ │ ├── _browser-bugs.scss │ │ ├── _skippy.scss │ │ ├── _placeholder-img.scss │ │ ├── _variables.scss │ │ ├── _colors.scss │ │ ├── _footer.scss │ │ ├── _clipboard-js.scss │ │ ├── _ads.scss │ │ ├── _buttons.scss │ │ ├── _callouts.scss │ │ ├── _masthead.scss │ │ ├── _brand.scss │ │ ├── docs.scss │ │ ├── _nav.scss │ │ ├── _syntax.scss │ │ ├── _content.scss │ │ ├── _sidebar.scss │ │ ├── _algolia.scss │ │ └── _component-examples.scss ├── App.test.js ├── ScrollToTop.js ├── DocSection.js ├── index.scss ├── common │ └── MeasuredItem.js ├── Header.js ├── logo.svg └── App.js ├── stylelint.config.js ├── utils └── sass-importer.js ├── .github └── workflows │ ├── commitlint.yml │ ├── lockfileversion-check.yml │ ├── self-assign-issue.yml │ ├── add-depr-ticket-to-depr-board.yml │ ├── add-remove-label-on-comment.yml │ ├── npm-publish.yml │ └── ci.yml ├── catalog-info.yaml ├── renovate.json ├── package.json ├── README.rst └── LICENSE /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | PUBLIC_URL=/edx-bootstrap 2 | -------------------------------------------------------------------------------- /scss/edx/overrides/_badges.scss: -------------------------------------------------------------------------------- 1 | .badge { 2 | @badge-pill; 3 | } 4 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_badges.scss: -------------------------------------------------------------------------------- 1 | .badge { 2 | @badge-pill; 3 | } 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # Workaround for https://github.com/npm/npm/issues/17722 2 | 3 | optional=false 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openedx/edx-bootstrap/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /scss/core/_extensions.scss: -------------------------------------------------------------------------------- 1 | @import "./extensions/buttons"; 2 | @import "./extensions/utilities"; 3 | -------------------------------------------------------------------------------- /scss/edx/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Roboto:400,500,700"); 2 | -------------------------------------------------------------------------------- /scss/open-edx/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700"); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | build 3 | css 4 | samples/edx-bootstrap 5 | node_modules 6 | sass/.DS_Store 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .edx-bootstrap 2 | .gitignore 3 | .npmignore 4 | _config.yml 5 | doc 6 | node_modules 7 | package.json 8 | test 9 | -------------------------------------------------------------------------------- /scss/edx/overrides/_dropdowns.scss: -------------------------------------------------------------------------------- 1 | .dropdown-menu { 2 | box-shadow: $box-shadow; 3 | } 4 | .dropdown-item { 5 | text-decoration: none; 6 | } -------------------------------------------------------------------------------- /scss/open-edx/overrides/_dropdowns.scss: -------------------------------------------------------------------------------- 1 | .dropdown-menu { 2 | box-shadow: $box-shadow; 3 | } 4 | .dropdown-item { 5 | text-decoration: none; 6 | } -------------------------------------------------------------------------------- /scss/open-edx/theme.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | @import "~bootstrap/scss/functions"; 3 | @import "variables"; 4 | @import "../core/core"; 5 | @import "overrides"; 6 | -------------------------------------------------------------------------------- /scss/edx/overrides/_navs.scss: -------------------------------------------------------------------------------- 1 | .nav-link { 2 | &.active { 3 | color: $gray-900; 4 | text-decoration: none; 5 | font-weight: $font-weight-semi-bold; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /scss/edx/overrides/_grid.scss: -------------------------------------------------------------------------------- 1 | .container, 2 | .container-fluid { 3 | max-width: 1440px; 4 | padding-left: $grid-gutter-width; 5 | padding-right: $grid-gutter-width; 6 | } 7 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_navs.scss: -------------------------------------------------------------------------------- 1 | .nav-link { 2 | &.active { 3 | color: $gray-900; 4 | text-decoration: none; 5 | font-weight: $font-weight-semi-bold; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/pages/Basics.Themes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | export default function Themes() { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } -------------------------------------------------------------------------------- /scss/edx/theme.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | @import "~bootstrap/scss/functions"; 3 | @import "functions"; 4 | @import "variables"; 5 | @import "../core/core"; 6 | @import "overrides"; 7 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_grid.scss: -------------------------------------------------------------------------------- 1 | .container, 2 | .container-fluid { 3 | max-width: 1440px; 4 | padding-left: $grid-gutter-width; 5 | padding-right: $grid-gutter-width; 6 | } 7 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import './index.scss'; 5 | import App from './App'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@edx/stylelint-config-edx', 3 | "rules": { 4 | "at-rule-empty-line-before": null, 5 | "function-no-unknown": null, 6 | "scss/no-global-function-names": null, 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /scss/edx/overrides/_modals.scss: -------------------------------------------------------------------------------- 1 | .modal-content { 2 | box-shadow: $box-shadow; 3 | border: solid 1px #d6dbe0; 4 | } 5 | 6 | .modal-footer { 7 | justify-content: flex-start; 8 | padding-bottom: 1.75rem; 9 | padding-top: 0.75rem; 10 | } 11 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_modals.scss: -------------------------------------------------------------------------------- 1 | .modal-content { 2 | box-shadow: $box-shadow; 3 | border: solid 1px #d6dbe0; 4 | } 5 | 6 | .modal-footer { 7 | justify-content: flex-start; 8 | padding-bottom: 1.75rem; 9 | padding-top: 0.75rem; 10 | } 11 | -------------------------------------------------------------------------------- /utils/sass-importer.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = function importer(url, prev, done) { 4 | if (url[0] === '~') { 5 | url = path.resolve('node_modules', url.substr(1)); 6 | } 7 | 8 | return { file: url }; 9 | } 10 | -------------------------------------------------------------------------------- /.github/workflows/commitlint.yml: -------------------------------------------------------------------------------- 1 | # Run commitlint on the commit messages in a pull request. 2 | 3 | name: Lint Commit Messages 4 | 5 | on: 6 | - pull_request 7 | 8 | jobs: 9 | commitlint: 10 | uses: openedx/.github/.github/workflows/commitlint.yml@master 11 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_anchor.scss: -------------------------------------------------------------------------------- 1 | .anchorjs-link { 2 | font-weight: 400; 3 | color: rgba($link-color, .5); 4 | @include transition(color .15s ease-in-out, opacity .15s ease-in-out); 5 | 6 | &:hover { 7 | color: $link-color; 8 | text-decoration: none; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_browser-bugs.scss: -------------------------------------------------------------------------------- 1 | // Wall of Browser Bugs 2 | // 3 | // Better display for the responsive table on the Wall of Browser Bugs. 4 | 5 | .bd-browser-bugs { 6 | td p { 7 | margin-bottom: 0; 8 | } 9 | th:first-child { 10 | width: 18%; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /.github/workflows/lockfileversion-check.yml: -------------------------------------------------------------------------------- 1 | #check package-lock file version 2 | 3 | name: Lockfile Version check 4 | 5 | on: 6 | push: 7 | branches: 8 | - master 9 | pull_request: 10 | 11 | jobs: 12 | version-check: 13 | uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master 14 | -------------------------------------------------------------------------------- /scss/edx/_overrides.scss: -------------------------------------------------------------------------------- 1 | @import "./overrides/alerts"; 2 | @import "./overrides/badges"; 3 | @import "./overrides/buttons"; 4 | @import "./overrides/dropdowns"; 5 | @import "./overrides/grid"; 6 | @import "./overrides/modals"; 7 | @import "./overrides/typography"; 8 | @import "./overrides/navs"; 9 | 10 | @import "./custom/edx-custom-card"; 11 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_skippy.scss: -------------------------------------------------------------------------------- 1 | .skippy { 2 | display: block; 3 | padding: 1em; 4 | color: $white; 5 | text-align: center; 6 | background-color: $bd-purple; 7 | outline: 0; 8 | 9 | @include hover { 10 | color: $white; 11 | } 12 | } 13 | 14 | .skippy-text { 15 | padding: .5em; 16 | outline: 1px dotted; 17 | } 18 | -------------------------------------------------------------------------------- /src/ScrollToTop.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useLocation } from 'react-router-dom'; 3 | 4 | const ScrollToTop = ({ children }) => { 5 | const location = useLocation(); 6 | 7 | useEffect(() => { 8 | window.scrollTo(0, 0); 9 | }, [location.pathname]); 10 | 11 | return children; 12 | } 13 | 14 | export default ScrollToTop; 15 | -------------------------------------------------------------------------------- /scss/core/extensions/_utilities.scss: -------------------------------------------------------------------------------- 1 | @each $color, $value in $colors { 2 | @include bg-variant(".bg-#{$color}", $value); 3 | } 4 | 5 | @each $color, $value in $colors { 6 | @include text-emphasis-variant(".text-#{$color}", $value); 7 | } 8 | 9 | @each $color, $value in $colors { 10 | .border-#{$color} { 11 | border-color: $value !important; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /scss/open-edx/_overrides.scss: -------------------------------------------------------------------------------- 1 | @import "./overrides/alerts"; 2 | @import "./overrides/badges"; 3 | @import "./overrides/buttons"; 4 | @import "./overrides/dropdowns"; 5 | @import "./overrides/grid"; 6 | @import "./overrides/modals"; 7 | @import "./overrides/typography"; 8 | @import "./overrides/tables"; 9 | @import "./overrides/navs"; 10 | 11 | @import "./custom/edx-custom-card"; 12 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_placeholder-img.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Placeholder svg used in the docs. 3 | // 4 | 5 | // Remember to update `site/_layouts/examples.html` too if this changes! 6 | 7 | .bd-placeholder-img { 8 | font-size: 1.125rem; 9 | text-anchor: middle; 10 | } 11 | 12 | .bd-placeholder-img-lg { 13 | @include media-breakpoint-up(md) { 14 | font-size: 3.5rem; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_buttons.scss: -------------------------------------------------------------------------------- 1 | .btn { 2 | text-decoration: none; 3 | } 4 | 5 | .btn-link { 6 | text-decoration: $link-decoration; 7 | 8 | &.hover, 9 | &:hover, { 10 | text-decoration: $link-hover-decoration; 11 | } 12 | 13 | &.focus, 14 | &:focus { 15 | outline: 1px dotted; 16 | outline: 5px auto -webkit-focus-ring-color; 17 | text-decoration: $link-hover-decoration; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pages/GettingStarted.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class GettingStarted extends React.Component { 4 | render() { 5 | return ( 6 |
7 | 8 |

Usage

9 |

Details on how to pull this into a project and get started.

10 | 11 |
12 | ); 13 | } 14 | } -------------------------------------------------------------------------------- /.github/workflows/self-assign-issue.yml: -------------------------------------------------------------------------------- 1 | # This workflow runs when a comment is made on the ticket 2 | # If the comment starts with "assign me" it assigns the author to the 3 | # ticket (case insensitive) 4 | 5 | name: Assign comment author to ticket if they say "assign me" 6 | on: 7 | issue_comment: 8 | types: [created] 9 | 10 | jobs: 11 | self_assign_by_comment: 12 | uses: openedx/.github/.github/workflows/self-assign-issue.yml@master 13 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_variables.scss: -------------------------------------------------------------------------------- 1 | // Local docs variables 2 | $bd-purple: $primary !default; 3 | $bd-purple-bright: lighten(saturate($bd-purple, 5%), 15%) !default; 4 | $bd-purple-light: lighten(saturate($bd-purple, 5%), 45%) !default; 5 | $bd-dark: $dark !default; 6 | $bd-download: $light !default; 7 | $bd-info: $info !default; 8 | $bd-warning: $warning !default; 9 | $bd-danger: $danger !default; 10 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | # This file records information about this repo. Its use is described in OEP-55: 2 | # https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html 3 | 4 | apiVersion: backstage.io/v1alpha1 5 | kind: Component 6 | metadata: 7 | name: 'edx-bootstrap' 8 | description: "This library is an extension of Bootstrap 4, provides a set of tools to bootstrap a new Open edX project." 9 | spec: 10 | type: 'library' 11 | owner: group:openedx-unmaintained -------------------------------------------------------------------------------- /scss/open-edx/overrides/_typography.scss: -------------------------------------------------------------------------------- 1 | body { 2 | -webkit-font-smoothing: antialiased; 3 | -moz-osx-font-smoothing: grayscale; 4 | } 5 | 6 | .display-1, 7 | .display-2, 8 | .display-3, 9 | .display-4, 10 | h1, 11 | .h1 { 12 | letter-spacing: -0.025em; 13 | } 14 | 15 | h2, 16 | .h2 { 17 | font-weight: $font-weight-normal; 18 | letter-spacing: -0.0125em; 19 | } 20 | 21 | h3, 22 | h4, 23 | h5, 24 | h6, 25 | .h3, 26 | .h4, 27 | .h5, 28 | .h6 { 29 | font-family: $font-family-sans-serif; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_colors.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Docs color palette classes 3 | // 4 | 5 | @each $color, $value in $colors { 6 | .swatch-#{$color} { 7 | color: color-yiq($value); 8 | background-color: #{$value}; 9 | } 10 | } 11 | 12 | @each $color, $value in $theme-colors { 13 | .swatch-#{$color} { 14 | color: color-yiq($value); 15 | background-color: #{$value}; 16 | } 17 | } 18 | 19 | @each $color, $value in $grays { 20 | .swatch-#{$color} { 21 | color: color-yiq($value); 22 | background-color: #{$value}; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_tables.scss: -------------------------------------------------------------------------------- 1 | @mixin table-border-top() { 2 | border-top: 1px solid $gray-300; 3 | } 4 | 5 | @mixin table-border-right() { 6 | border-right: 1px solid $gray-300; 7 | } 8 | 9 | .table { 10 | border: 1px solid $gray-300; 11 | 12 | th { 13 | @include table-border-top; 14 | @include table-border-right; 15 | } 16 | 17 | td { 18 | @include table-border-top; 19 | @include table-border-right; 20 | } 21 | 22 | thead th { 23 | @include table-border-right; 24 | 25 | border-bottom: 1px solid $gray-300; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/DocSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default function DocSection(props) { 5 | return ( 6 | 7 | Section 8 |
9 |

{props.title}

10 | {props.children} 11 |
12 |
13 | ); 14 | } 15 | 16 | DocSection.propTypes = { 17 | id: PropTypes.string.isRequired, 18 | title: PropTypes.string.isRequired 19 | }; 20 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | "schedule:weekly", 5 | ":automergeLinters", 6 | ":automergeMinor", 7 | ":automergeTesters", 8 | ":enableVulnerabilityAlerts", 9 | ":rebaseStalePrs", 10 | ":semanticCommits", 11 | ":updateNotScheduled" 12 | ], 13 | "packageRules": [ 14 | { 15 | "matchDepTypes": [ 16 | "devDependencies" 17 | ], 18 | "matchUpdateTypes": [ 19 | "lockFileMaintenance", 20 | "minor", 21 | "patch", 22 | "pin" 23 | ], 24 | "automerge": true 25 | } 26 | ], 27 | "timezone": "America/New_York" 28 | } 29 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_footer.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Footer 3 | // 4 | 5 | .bd-footer { 6 | font-size: 85%; 7 | text-align: center; 8 | background-color: #f7f7f7; 9 | 10 | a { 11 | font-weight: 600; 12 | color: $gray-700; 13 | 14 | &:hover, 15 | &:focus { 16 | color: $link-color; 17 | } 18 | } 19 | 20 | p { 21 | margin-bottom: 0; 22 | } 23 | 24 | @include media-breakpoint-up(sm) { 25 | text-align: left; 26 | } 27 | } 28 | 29 | .bd-footer-links { 30 | padding-left: 0; 31 | margin-bottom: 1rem; 32 | 33 | li { 34 | display: inline-block; 35 | 36 | + li { 37 | margin-left: 1rem; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /scss/edx/_functions.scss: -------------------------------------------------------------------------------- 1 | @function blend-transparent($foreground, $background, $fg-opacity, $bg-opacity: 1) { 2 | // https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending 3 | // Adapted from: https://gist.github.com/jdudek/54c80e27510b9b13d4447f803869118f 4 | 5 | $opacity: $fg-opacity + $bg-opacity * (1 - $fg-opacity); 6 | $factor: $bg-opacity * (1 - $fg-opacity); 7 | 8 | $red: (red($foreground) * $fg-opacity + red($background) * $factor) / $opacity; 9 | $green: (green($foreground) * $fg-opacity + green($background) * $factor) / $opacity; 10 | $blue: (blue($foreground) * $fg-opacity + blue($background) * $factor) / $opacity; 11 | 12 | @return rgba($red, $green, $blue, $opacity); 13 | } 14 | -------------------------------------------------------------------------------- /scss/edx/overrides/_alerts.scss: -------------------------------------------------------------------------------- 1 | .alert { 2 | padding: 0.75rem 0.75rem; 3 | } 4 | 5 | .alert-success, 6 | .alert-danger, 7 | .alert-warning, 8 | .alert-info { 9 | border: none; 10 | color: $body-color; 11 | 12 | .alert-link { 13 | color: $body-color; 14 | } 15 | } 16 | 17 | .alert-success { 18 | background: $fill-success; 19 | } 20 | 21 | .alert-danger { 22 | background: $fill-danger; 23 | } 24 | 25 | .alert-warning { 26 | background: $fill-warning; 27 | } 28 | 29 | .alert-info { 30 | background: $fill-info; 31 | } 32 | 33 | 34 | .alert-dismissible .close { 35 | color: $link-color; 36 | opacity: 1; 37 | padding: 0.65rem 1rem; 38 | 39 | @include hover { 40 | color: $link-hover-color; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.github/workflows/add-depr-ticket-to-depr-board.yml: -------------------------------------------------------------------------------- 1 | # Run the workflow that adds new tickets that are either: 2 | # - labelled "DEPR" 3 | # - title starts with "[DEPR]" 4 | # - body starts with "Proposal Date" (this is the first template field) 5 | # to the org-wide DEPR project board 6 | 7 | name: Add newly created DEPR issues to the DEPR project board 8 | 9 | on: 10 | issues: 11 | types: [opened] 12 | 13 | jobs: 14 | routeissue: 15 | uses: openedx/.github/.github/workflows/add-depr-ticket-to-depr-board.yml@master 16 | secrets: 17 | GITHUB_APP_ID: ${{ secrets.GRAPHQL_AUTH_APP_ID }} 18 | GITHUB_APP_PRIVATE_KEY: ${{ secrets.GRAPHQL_AUTH_APP_PEM }} 19 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_ISSUE_BOT_TOKEN }} 20 | -------------------------------------------------------------------------------- /scss/open-edx/overrides/_alerts.scss: -------------------------------------------------------------------------------- 1 | .alert { 2 | padding: 0.75rem 0.75rem; 3 | } 4 | 5 | .alert-success, 6 | .alert-danger, 7 | .alert-warning, 8 | .alert-info { 9 | border: none; 10 | color: $body-color; 11 | 12 | .alert-link { 13 | color: $body-color; 14 | } 15 | } 16 | 17 | .alert-success { 18 | background: $fill-success; 19 | } 20 | 21 | .alert-danger { 22 | background: $fill-danger; 23 | } 24 | 25 | .alert-warning { 26 | background: $fill-warning; 27 | } 28 | 29 | .alert-info { 30 | background: $fill-info; 31 | } 32 | 33 | 34 | .alert-dismissible .close { 35 | color: $link-color; 36 | opacity: 1; 37 | padding: 0.65rem 1rem; 38 | 39 | @include hover { 40 | color: $link-hover-color; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_clipboard-js.scss: -------------------------------------------------------------------------------- 1 | // clipboard.js 2 | // 3 | // JS-based `Copy` buttons for code snippets. 4 | 5 | .bd-clipboard { 6 | position: relative; 7 | display: none; 8 | float: right; 9 | 10 | + .highlight { 11 | margin-top: 0; 12 | } 13 | 14 | @include media-breakpoint-up(md) { 15 | display: block; 16 | } 17 | } 18 | 19 | .btn-clipboard { 20 | position: absolute; 21 | top: .5rem; 22 | right: .5rem; 23 | z-index: 10; 24 | display: block; 25 | padding: .25rem .5rem; 26 | font-size: 75%; 27 | color: #818a91; 28 | background-color: transparent; 29 | border: 0; 30 | @include border-radius; 31 | 32 | &:hover { 33 | color: $white; 34 | background-color: #027de7; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_ads.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important, selector-max-id 2 | 3 | // 4 | // Carbon ads 5 | // 6 | 7 | #carbonads { 8 | position: static; 9 | display: block; 10 | max-width: 400px; 11 | padding: 15px 15px 15px 160px; 12 | margin: 2rem 0; 13 | overflow: hidden; 14 | font-size: 13px; 15 | line-height: 1.4; 16 | text-align: left; 17 | background-color: rgba(0, 0, 0, .05); 18 | 19 | a { 20 | color: #333; 21 | text-decoration: none; 22 | } 23 | 24 | @include media-breakpoint-up(sm) { 25 | max-width: 330px; 26 | @include border-radius(4px); 27 | } 28 | } 29 | 30 | .carbon-img { 31 | float: left; 32 | margin-left: -145px; 33 | } 34 | 35 | .carbon-poweredby { 36 | display: block; 37 | color: #777 !important; 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/add-remove-label-on-comment.yml: -------------------------------------------------------------------------------- 1 | # This workflow runs when a comment is made on the ticket 2 | # If the comment starts with "label: " it tries to apply 3 | # the label indicated in rest of comment. 4 | # If the comment starts with "remove label: ", it tries 5 | # to remove the indicated label. 6 | # Note: Labels are allowed to have spaces and this script does 7 | # not parse spaces (as often a space is legitimate), so the command 8 | # "label: really long lots of words label" will apply the 9 | # label "really long lots of words label" 10 | 11 | name: Allows for the adding and removing of labels via comment 12 | 13 | on: 14 | issue_comment: 15 | types: [created] 16 | 17 | jobs: 18 | add_remove_labels: 19 | uses: openedx/.github/.github/workflows/add-remove-label-on-comment.yml@master 20 | 21 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Buttons 2 | // 3 | // Custom buttons for the docs. 4 | 5 | .btn-bd-primary { 6 | font-weight: 600; 7 | color: $bd-purple-bright; 8 | border-color: $bd-purple-bright; 9 | 10 | &:hover, 11 | &:active { 12 | color: $white; 13 | background-color: $bd-purple-bright; 14 | border-color: $bd-purple-bright; 15 | } 16 | 17 | &:focus { 18 | box-shadow: 0 0 0 3px rgba($bd-purple-bright, .25); 19 | } 20 | } 21 | 22 | .btn-bd-download { 23 | font-weight: 600; 24 | color: $bd-download; 25 | border-color: $bd-download; 26 | 27 | &:hover, 28 | &:active { 29 | color: $bd-dark; 30 | background-color: $bd-download; 31 | border-color: $bd-download; 32 | } 33 | 34 | &:focus { 35 | box-shadow: 0 0 0 3px rgba($bd-download, .25); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_callouts.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Callouts 3 | // 4 | 5 | .bd-callout { 6 | padding: 1.25rem; 7 | margin-top: 1.25rem; 8 | margin-bottom: 1.25rem; 9 | border: 1px solid #eee; 10 | border-left-width: .25rem; 11 | @include border-radius; 12 | 13 | h4 { 14 | margin-top: 0; 15 | margin-bottom: .25rem; 16 | } 17 | 18 | p:last-child { 19 | margin-bottom: 0; 20 | } 21 | 22 | code { 23 | @include border-radius; 24 | } 25 | 26 | + .bd-callout { 27 | margin-top: -.25rem; 28 | } 29 | } 30 | 31 | // Variations 32 | @mixin bs-callout-variant($color) { 33 | border-left-color: $color; 34 | 35 | h4 { color: $color; } 36 | } 37 | 38 | .bd-callout-info { @include bs-callout-variant($bd-info); } 39 | .bd-callout-warning { @include bs-callout-variant($bd-warning); } 40 | .bd-callout-danger { @include bs-callout-variant($bd-danger); } 41 | -------------------------------------------------------------------------------- /src/index.scss: -------------------------------------------------------------------------------- 1 | @import "../scss/edx/theme"; 2 | @import "./scss/bootstrap-docs-4-2/docs"; 3 | 4 | 5 | .btn-clipboard { 6 | display: none; 7 | } 8 | 9 | .bd-sidebar { 10 | overflow-y: auto; 11 | .nav > li > a { 12 | &.active { 13 | font-weight: bold; 14 | color: $primary; 15 | } 16 | text-decoration: none; 17 | &:hover { 18 | text-decoration: underline; 19 | } 20 | } 21 | a { 22 | text-decoration: none; 23 | &:hover { 24 | text-decoration: underline; 25 | } 26 | } 27 | } 28 | 29 | .color-card { 30 | box-shadow: inset 0 0 1px rgba(0,0,0,.2); 31 | } 32 | 33 | .color-label { 34 | margin-bottom: .25rem; 35 | } 36 | .text-swatch-sample { 37 | font-size: 2em; 38 | line-height: 1; 39 | margin-left: .5rem; 40 | } 41 | 42 | .bd-content { 43 | h5.section { 44 | margin: 1.5rem 0 1rem; 45 | @extend .h6; 46 | } 47 | } -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | release: 9 | name: Release 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | - name: Setup Nodejs Env 17 | run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV 18 | - name: Setup Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: ${{ env.NODE_VER }} 22 | 23 | - name: Install dependencies 24 | run: npm ci 25 | 26 | - name: Create Build 27 | run: npm run build 28 | 29 | - name: Release Package 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }} 32 | NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }} 33 | run: npm run semantic-release 34 | -------------------------------------------------------------------------------- /src/common/MeasuredItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | 4 | export default class MeasuredItem extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | 8 | this.state = { 9 | ..._.zipObject(Object.keys(this.props.styles)) 10 | } 11 | this.item = React.createRef(); 12 | } 13 | 14 | componentDidMount() { 15 | const computedStyle = getComputedStyle(this.item.current); 16 | const styleNames = Object.keys(this.props.styles); 17 | 18 | this.setState({ 19 | ..._.zipObject(styleNames, _.map(styleNames, (styleName) => computedStyle.getPropertyValue(styleName) )), 20 | }); 21 | } 22 | 23 | render() { 24 | const child = React.cloneElement(this.props.renderItem(this.props, this.state), { ref: this.item }); 25 | return ( 26 | 27 | {this.props.before ? this.props.renderValues(this.state) : null} 28 | {child} 29 | {this.props.after ? this.props.renderValues(this.state) : null} 30 | 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /src/pages/bootstrap/Badge.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Badge extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Badges / Tags

8 | 9 |

Notes

10 |
    11 |
  • Our default badges are pills. There's no need to use the 'badge-pill' class.
  • 12 |
13 | 14 |

Todo:

15 |
    16 |
  • Abby: to provide design
  • 17 |
18 | 19 |
20 | Primary 21 | Secondary 22 | Success 23 | Danger 24 | Warning 25 | Info 26 | Light 27 | Dark 28 |
29 |
30 | 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /scss/core/extensions/_buttons.scss: -------------------------------------------------------------------------------- 1 | // 2 | // This field defines a new variant of button (inverse) 3 | // and adds a focus outline to all buttons on :focus 4 | // 5 | 6 | @mixin button-inverse-variant($color, $background: color-yiq($color), $active-background: $color, $active-border: $color) { 7 | color: $color; 8 | border-color: transparent; 9 | background-color: $background; 10 | 11 | @include hover { 12 | color: darken($color, 7.5%); 13 | background-color: darken($background, 7.5%); 14 | border-color: transparent; 15 | } 16 | 17 | &:focus, 18 | &.focus { 19 | border-color: rgba($color, 0.5); 20 | } 21 | 22 | &.disabled, 23 | &:disabled { 24 | color: $color; 25 | background-color: transparent; 26 | } 27 | 28 | &:not(:disabled):not(.disabled):active, 29 | &:not(:disabled):not(.disabled).active, 30 | .show > &.dropdown-toggle { 31 | color: darken($color, 10%); 32 | background: #eee; 33 | } 34 | } 35 | 36 | 37 | // Create inverse variants 38 | 39 | @each $color, $value in $theme-colors { 40 | .btn-inverse-#{$color} { 41 | @include button-inverse-variant($value); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Header extends React.Component { 4 | constructor(props) { 5 | super(props); 6 | } 7 | 8 | render() { 9 | return ( 10 |
11 | edX Bootstrap 12 | 13 |
14 | 19 |
20 | 21 | 29 |
30 | 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_masthead.scss: -------------------------------------------------------------------------------- 1 | // // stylelint-disable declaration-no-important 2 | 3 | // .bd-masthead { 4 | // position: relative; 5 | // padding: 3rem ($grid-gutter-width / 2); 6 | // // background-image: linear-gradient(45deg, #fafafa, #f5f5f5); 7 | 8 | // h1 { 9 | // line-height: 1; 10 | // } 11 | 12 | // .btn { 13 | // padding: .8rem 2rem; 14 | // font-weight: 600; 15 | // } 16 | 17 | // .carbonad { 18 | // margin-top: 0 !important; 19 | // margin-bottom: -3rem !important; 20 | // } 21 | 22 | // @include media-breakpoint-up(sm) { 23 | // padding-top: 5rem; 24 | // padding-bottom: 5rem; 25 | 26 | // .carbonad { 27 | // margin-bottom: 0 !important; 28 | // } 29 | // } 30 | 31 | // @include media-breakpoint-up(md) { 32 | // h1 { 33 | // font-size: 4rem; 34 | // } 35 | 36 | // .carbonad { 37 | // margin-top: 3rem !important; 38 | // } 39 | // } 40 | // } 41 | 42 | // .half-rule { 43 | // width: 6rem; 44 | // margin: 2.5rem 0; 45 | // } 46 | 47 | // .masthead-followup { 48 | // .bd-clipboard { display: none; } 49 | 50 | // .highlight { 51 | // padding: .5rem 0; 52 | // background-color: transparent; 53 | // } 54 | // } 55 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - "**" 10 | 11 | jobs: 12 | tests: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | - name: Setup Nodejs 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version-file: '.nvmrc' 21 | 22 | - name: Install Dependencies 23 | run: npm ci 24 | 25 | - name: Lint 26 | run: npm run lint 27 | 28 | - name: Build 29 | run: npm run build 30 | 31 | - name: Send failure notification 32 | if: ${{ failure() }} 33 | uses: dawidd6/action-send-mail@v3 34 | with: 35 | server_address: email-smtp.us-east-1.amazonaws.com 36 | server_port: 465 37 | username: ${{secrets.EDX_SMTP_USERNAME}} 38 | password: ${{secrets.EDX_SMTP_PASSWORD}} 39 | subject: CI workflow failed in ${{github.repository}} 40 | to: frontend-working-group@edx.org 41 | from: github-actions 42 | body: CI workflow in ${{github.repository}} failed! For details see "github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 43 | -------------------------------------------------------------------------------- /scss/edx/overrides/_typography.scss: -------------------------------------------------------------------------------- 1 | body { 2 | -webkit-font-smoothing: antialiased; 3 | -moz-osx-font-smoothing: grayscale; 4 | } 5 | 6 | .display-1, 7 | .display-2, 8 | .display-3, 9 | .display-4 { 10 | font-family: $font-family-serif; 11 | font-weight: $font-weight-bold; 12 | line-height: 1.111111111111111; // 80px 13 | } 14 | 15 | h1, 16 | .h1 { 17 | font-family: $font-family-serif; 18 | font-weight: $font-weight-bold; 19 | } 20 | 21 | h2, 22 | h3, 23 | h4, 24 | .h2, 25 | .h3, 26 | .h4, { 27 | font-weight: $font-weight-semi-bold; 28 | } 29 | 30 | h5, 31 | h6, 32 | .h5, 33 | .h6 { 34 | font-weight: $font-weight-bold; 35 | } 36 | 37 | label { 38 | line-height: $headings-line-height; 39 | font-weight: $headings-font-weight; 40 | } 41 | 42 | small, 43 | .small { 44 | line-height: 1.428571428571429; // 20px 45 | } 46 | 47 | @mixin mobile-type { 48 | .display-1, 49 | .display-2, 50 | .display-3, 51 | .display-4, 52 | h1, .h1 { 53 | font-size: 2rem; 54 | line-height: $headings-line-height; 55 | } 56 | h2, .h2 { 57 | font-size: 1.75rem; 58 | } 59 | h3, .h3 { 60 | font-size: 1.5rem; 61 | } 62 | h4, .h4 { 63 | font-size: 1.375rem; 64 | } 65 | } 66 | 67 | @media (max-width: map-get($grid-breakpoints, "sm")) { 68 | @include mobile-type; 69 | } 70 | -------------------------------------------------------------------------------- /scss/core/core.scss: -------------------------------------------------------------------------------- 1 | @import "~bootstrap/scss/functions"; 2 | @import "~bootstrap/scss/variables"; 3 | @import "~bootstrap/scss/mixins"; 4 | 5 | @import "~bootstrap/scss/root"; 6 | @import "~bootstrap/scss/reboot"; 7 | @import "~bootstrap/scss/type"; 8 | @import "~bootstrap/scss/images"; 9 | @import "~bootstrap/scss/code"; 10 | @import "~bootstrap/scss/grid"; 11 | @import "~bootstrap/scss/tables"; 12 | @import "~bootstrap/scss/forms"; 13 | @import "~bootstrap/scss/buttons"; 14 | @import "~bootstrap/scss/transitions"; 15 | @import "~bootstrap/scss/dropdown"; 16 | @import "~bootstrap/scss/button-group"; 17 | @import "~bootstrap/scss/input-group"; 18 | @import "~bootstrap/scss/custom-forms"; 19 | @import "~bootstrap/scss/nav"; 20 | @import "~bootstrap/scss/navbar"; 21 | @import "~bootstrap/scss/card"; 22 | @import "~bootstrap/scss/breadcrumb"; 23 | @import "~bootstrap/scss/pagination"; 24 | @import "~bootstrap/scss/badge"; 25 | @import "~bootstrap/scss/jumbotron"; 26 | @import "~bootstrap/scss/alert"; 27 | @import "~bootstrap/scss/progress"; 28 | @import "~bootstrap/scss/media"; 29 | @import "~bootstrap/scss/list-group"; 30 | @import "~bootstrap/scss/close"; 31 | @import "~bootstrap/scss/toasts"; 32 | @import "~bootstrap/scss/modal"; 33 | @import "~bootstrap/scss/tooltip"; 34 | @import "~bootstrap/scss/popover"; 35 | @import "~bootstrap/scss/carousel"; 36 | @import "~bootstrap/scss/spinners"; 37 | @import "~bootstrap/scss/utilities"; 38 | @import "~bootstrap/scss/print"; 39 | 40 | @import "extensions"; 41 | -------------------------------------------------------------------------------- /src/pages/bootstrap/Pagination.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Pagination extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Pagination

8 |

Documentation and examples for showing pagination to indicate a series of related content exists across multiple pages.

9 | 10 |

Overview

11 |
12 | 21 |
22 | 23 | 27 |
28 | ); 29 | } 30 | } -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_brand.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Brand guidelines 3 | // 4 | 5 | // Logo series wrapper 6 | .bd-brand-logos { 7 | display: table; 8 | width: 100%; 9 | margin-bottom: 1rem; 10 | overflow: hidden; 11 | color: $bd-purple; 12 | background-color: #f9f9f9; 13 | @include border-radius; 14 | 15 | .inverse { 16 | color: $white; 17 | background-color: $bd-purple; 18 | } 19 | } 20 | 21 | // Individual items 22 | .bd-brand-item { 23 | padding: 4rem 0; 24 | text-align: center; 25 | 26 | + .bd-brand-item { 27 | border-top: 1px solid $white; 28 | } 29 | 30 | // Heading content within 31 | h1, 32 | h3 { 33 | margin-top: 0; 34 | margin-bottom: 0; 35 | } 36 | 37 | @include media-breakpoint-up(md) { 38 | display: table-cell; 39 | width: 1%; 40 | 41 | + .bd-brand-item { 42 | border-top: 0; 43 | border-left: 1px solid $white; 44 | } 45 | 46 | h1 { 47 | font-size: 4rem; 48 | } 49 | } 50 | } 51 | 52 | 53 | // 54 | // Color swatches 55 | // 56 | 57 | .color-swatches { 58 | margin: 0 -5px; 59 | overflow: hidden; // clearfix 60 | 61 | // Docs colors 62 | .bd-purple { 63 | background-color: $bd-purple; 64 | } 65 | .bd-purple-light { 66 | background-color: $bd-purple-light; 67 | } 68 | .bd-purple-lighter { 69 | background-color: #e5e1ea; 70 | } 71 | .bd-gray { 72 | background-color: #f9f9f9; 73 | } 74 | } 75 | 76 | .color-swatch { 77 | float: left; 78 | width: 4rem; 79 | height: 4rem; 80 | margin-right: .25rem; 81 | margin-left: .25rem; 82 | @include border-radius; 83 | 84 | @include media-breakpoint-up(md) { 85 | width: 6rem; 86 | height: 6rem; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/pages/Basics.MiscBasics.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | export default function MiscBasics() { 5 | return ( 6 |
7 |

Badges

8 |

9 | Primary 10 | Secondary 11 | Success 12 | Danger 13 | Warning 14 | Info 15 | Light 16 | Dark 17 |

18 | 19 | 20 |

Inline Text Decorations

21 |

OK Use the text-muted class to mute text.

22 |

OK Use the mark tag to highlight text.

23 |

OK Use strikethroughs for content that is no longer accurate or has been deleted.

24 |

Avoid Avoid using underlines for static elements

25 |

Use Sparingly Fine print text that is 80% smaller than normal.

26 |

OK This line is rendered as bold text.

27 |

AvoidItalicized text is difficult to read and hard to localize.

28 |
29 | ); 30 | } -------------------------------------------------------------------------------- /src/pages/Miscellaneous.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DocSection from '../DocSection'; 3 | 4 | export default class Miscellaneous extends React.Component { 5 | render() { 6 | return ( 7 |
8 |

Miscellaneous

9 |

Examples and usage guidelines for various styles.

10 | 11 | 12 |

Examples and usage guidelines for loaders.

13 | 14 |
15 | Loading... 16 |
17 |
18 | Loading... 19 |
20 | 21 |
22 |
23 | Loading... 24 |
25 |
26 |
27 |
28 | 34 | 40 |
41 | 42 |
43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/docs.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Docs (https://getbootstrap.com/) 3 | * Copyright 2011-2018 The Bootstrap Authors 4 | * Copyright 2011-2018 Twitter, Inc. 5 | * Licensed under the Creative Commons Attribution 3.0 Unported License. For 6 | * details, see https://creativecommons.org/licenses/by/3.0/. 7 | */ 8 | 9 | // Dev notes 10 | // 11 | // Background information on nomenclature and architecture decisions here. 12 | // 13 | // - Bootstrap functions, variables, and mixins are included for easy reuse. 14 | // Doing so gives us access to the same core utilities provided by Bootstrap. 15 | // For example, consistent media queries through those mixins. 16 | // 17 | // - Bootstrap's **docs variables** are prefixed with `$bd-`. 18 | // These custom colors avoid collision with the components Bootstrap provides. 19 | // 20 | // - Classes are prefixed with `.bd-`. 21 | // These classes indicate custom-built or modified components for the design 22 | // and layout of the Bootstrap docs. They are not included in our builds. 23 | // 24 | // Happy Bootstrapping! 25 | 26 | // Load Bootstrap variables and mixins 27 | @import "~bootstrap/scss/functions"; 28 | @import "~bootstrap/scss/variables"; 29 | @import "~bootstrap/scss/mixins"; 30 | 31 | // Load docs components 32 | @import "variables"; 33 | @import "nav"; 34 | @import "masthead"; 35 | @import "ads"; 36 | @import "content"; 37 | @import "skippy"; 38 | @import "sidebar"; 39 | @import "footer"; 40 | @import "component-examples"; 41 | @import "buttons"; 42 | @import "callouts"; 43 | @import "browser-bugs"; 44 | @import "brand"; 45 | @import "colors"; 46 | @import "clipboard-js"; 47 | @import "placeholder-img"; 48 | 49 | // Load docs dependencies 50 | @import "syntax"; 51 | @import "anchor"; 52 | @import "algolia"; 53 | -------------------------------------------------------------------------------- /src/pages/Overview.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Overview extends React.Component { 4 | render() { 5 | return ( 6 |
7 | 8 |

edX Bootstrap

9 |

Tools for designing & building great user experiences faster.

10 | 11 |

A succinct yet powerful system.

12 |

13 | This library aims to be a set of powerful tools that remain as succinct as possible. We can get a lot done with just a small set of tools. Check out Airbnb's thoughts on the matter. 14 |

15 | 16 |

Minimize design & tech debt.

17 |

18 | When designing and building our products use these patterns first. Every time we design or build a new component or variation of an element, we take on design and technical debt. Let's always keep our broader system in mind when we make new things. 19 |

20 | 21 |

Flexible and ready for changes.

22 |

23 | Nothing here to help you get your job done? Building something you think might be a useful pattern? Reach out in the #arch-team-fed-ux channel. 24 |

25 | 26 |

Built on Bootstrap.

27 |

This library is a subset of Bootstrap tools mixed with some custom edX components. Bootstrap components documented here will link to the Bootstrap documentation for usage details. Broadly speaking, learn to build with Bootstrap and you'll know how to build with edX Bootstrap.

28 | 29 | 30 |
31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /src/pages/bootstrap/Breadcrumb.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Breadcrumb extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

8 | Breadcrumbs 9 |

10 | 11 |
12 | 19 | 29 | 39 | 52 |
53 |
54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Single Page Apps for GitHub Pages 6 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_nav.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Main navbar 3 | // 4 | 5 | .bd-navbar { 6 | min-height: 4rem; 7 | background-color: $bd-purple; 8 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .05), inset 0 -1px 0 rgba(0, 0, 0, .1); 9 | 10 | @include media-breakpoint-down(md) { 11 | padding-right: .5rem; 12 | padding-left: .5rem; 13 | 14 | .navbar-nav-scroll { 15 | max-width: 100%; 16 | height: 2.5rem; 17 | margin-top: .25rem; 18 | overflow: hidden; 19 | font-size: .875rem; 20 | 21 | .navbar-nav { 22 | padding-bottom: 2rem; 23 | overflow-x: auto; 24 | white-space: nowrap; 25 | -webkit-overflow-scrolling: touch; 26 | } 27 | } 28 | } 29 | 30 | @include media-breakpoint-up(md) { 31 | @supports (position: sticky) { 32 | position: sticky; 33 | top: 0; 34 | z-index: 1071; // over everything in bootstrap 35 | } 36 | } 37 | 38 | .navbar-nav { 39 | .nav-link { 40 | padding-right: .5rem; 41 | padding-left: .5rem; 42 | color: $bd-purple-light; 43 | 44 | &.active, 45 | &:hover { 46 | color: $white; 47 | background-color: transparent; 48 | } 49 | 50 | &.active { 51 | font-weight: 600; 52 | } 53 | } 54 | } 55 | 56 | .navbar-nav-svg { 57 | display: inline-block; 58 | width: 1rem; 59 | height: 1rem; 60 | vertical-align: text-top; 61 | } 62 | 63 | .dropdown-menu { 64 | font-size: .875rem; 65 | } 66 | 67 | .dropdown-item.active { 68 | font-weight: 600; 69 | color: $gray-900; 70 | background-color: transparent; 71 | background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23292b2c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); 72 | background-repeat: no-repeat; 73 | background-position: .4rem .6rem; 74 | background-size: .75rem .75rem; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_syntax.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-block-single-line-max-declarations, selector-class-pattern 2 | 3 | .hll { background-color: #ffc; } 4 | .c { color: #999; } 5 | .k { color: #069; } 6 | .o { color: #555; } 7 | .cm { color: #999; } 8 | .cp { color: #099; } 9 | .c1 { color: #999; } 10 | .cs { color: #999; } 11 | .gd { background-color: #fcc; border: 1px solid #c00; } 12 | .ge { font-style: italic; } 13 | .gr { color: #f00; } 14 | .gh { color: #030; } 15 | .gi { background-color: #cfc; border: 1px solid #0c0; } 16 | .go { color: #aaa; } 17 | .gp { color: #009; } 18 | .gu { color: #030; } 19 | .gt { color: #9c6; } 20 | .kc { color: #069; } 21 | .kd { color: #069; } 22 | .kn { color: #069; } 23 | .kp { color: #069; } 24 | .kr { color: #069; } 25 | .kt { color: #078; } 26 | .m { color: #f60; } 27 | .s { color: #d44950; } 28 | .na { color: #4f9fcf; } 29 | .nb { color: #366; } 30 | .nc { color: #0a8; } 31 | .no { color: #360; } 32 | .nd { color: #99f; } 33 | .ni { color: #999; } 34 | .ne { color: #c00; } 35 | .nf { color: #c0f; } 36 | .nl { color: #99f; } 37 | .nn { color: #0cf; } 38 | .nt { color: #2f6f9f; } 39 | .nv { color: #033; } 40 | .ow { color: #000; } 41 | .w { color: #bbb; } 42 | .mf { color: #f60; } 43 | .mh { color: #f60; } 44 | .mi { color: #f60; } 45 | .mo { color: #f60; } 46 | .sb { color: #c30; } 47 | .sc { color: #c30; } 48 | .sd { font-style: italic; color: #c30; } 49 | .s2 { color: #c30; } 50 | .se { color: #c30; } 51 | .sh { color: #c30; } 52 | .si { color: #a00; } 53 | .sx { color: #c30; } 54 | .sr { color: #3aa; } 55 | .s1 { color: #c30; } 56 | .ss { color: #fc3; } 57 | .bp { color: #366; } 58 | .vc { color: #033; } 59 | .vg { color: #033; } 60 | .vi { color: #033; } 61 | .il { color: #f60; } 62 | 63 | .css .o, 64 | .css .o + .nt, 65 | .css .nt + .nt { color: #999; } 66 | 67 | .language-bash::before, 68 | .language-sh::before { 69 | color: #009; 70 | content: "$ "; 71 | user-select: none; 72 | } 73 | 74 | .language-powershell::before { 75 | color: #009; 76 | content: "PM> "; 77 | user-select: none; 78 | } 79 | -------------------------------------------------------------------------------- /scss/edx/overrides/_buttons.scss: -------------------------------------------------------------------------------- 1 | .btn { 2 | text-decoration: none; 3 | } 4 | 5 | .btn-link { 6 | text-decoration: $link-decoration; 7 | 8 | &.hover, 9 | &:hover, { 10 | text-decoration: $link-hover-decoration; 11 | } 12 | 13 | &.focus, 14 | &:focus { 15 | outline: 1px dotted; 16 | outline: 5px auto -webkit-focus-ring-color; 17 | text-decoration: $link-hover-decoration; 18 | } 19 | } 20 | 21 | // Add focus outlines to all of them. Box shadow focus is turned off in variables. 22 | 23 | @each $color, $value in $theme-colors { 24 | .btn-#{$color}, 25 | .btn-outline-#{$color}, 26 | .btn-inverse-#{$color} { 27 | &:not(:disabled):not(.disabled), 28 | &:not(:disabled):not(.disabled):active, 29 | &:not(:disabled):not(.disabled).active, 30 | &:active, 31 | &.active { 32 | &.focus, 33 | &:focus { 34 | position: relative; 35 | &:before { 36 | content: ''; 37 | position: absolute; 38 | top: -6px; 39 | left: -6px; 40 | bottom: -6px; 41 | right: -6px; 42 | border:solid 2px saturate(blend-transparent($value, white, 0.65), 10%); 43 | border-radius: 40rem; 44 | } 45 | box-shadow: none; 46 | } 47 | } 48 | } 49 | 50 | .btn-#{$color} { 51 | &:hover { 52 | background: darken($value, 10%); 53 | } 54 | } 55 | 56 | .btn-outline-#{$color} { 57 | &:hover { 58 | color: darken($value, 10%); 59 | border-color: darken($value, 10%); 60 | background: desaturate(blend-transparent($value, white, 0.065), 5%); 61 | } 62 | &:not(:disabled):not(.disabled) { 63 | &:active, 64 | &.active { 65 | color: darken($value, 10%); 66 | border-color: darken($value, 10%); 67 | background: desaturate(blend-transparent($value, white, 0.065), 5%); 68 | } 69 | } 70 | } 71 | 72 | .btn-inverse-#{$color} { 73 | &:hover { 74 | color: darken($value, 10%); 75 | background: desaturate(blend-transparent($value, white, 0.065), 5%); 76 | } 77 | &:not(:disabled):not(.disabled), 78 | &:not(:disabled):not(.disabled):active, 79 | &:not(:disabled):not(.disabled).active, 80 | &:active, 81 | &.active { 82 | &:focus, 83 | &.focus { 84 | border-color: transparent; 85 | &:before { 86 | border:solid 2px rgba(white, .75); 87 | } 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@edx/edx-bootstrap", 3 | "description": "The Bootstrap theme for Open edX", 4 | "license": "Apache-2.0", 5 | "repository": "git@github.com:edx/edx-bootstrap.git", 6 | "version": "1.0.4", 7 | "homepage": "http://edx.github.io/edx-bootstrap", 8 | "scripts": { 9 | "start": "react-scripts start", 10 | "build-docs": "react-scripts build", 11 | "build": "node-sass --importer=utils/sass-importer --output-style expanded scss/ -o dist/", 12 | "lint": "stylelint ./scss/**/*.scss", 13 | "lint-fix": "stylelint ./scss/**/*.scss --fix", 14 | "test": "react-scripts test", 15 | "eject": "react-scripts eject", 16 | "semantic-release": "semantic-release", 17 | "predeploy": "npm run build-docs", 18 | "deploy": "gh-pages -d build" 19 | }, 20 | "husky": { 21 | "hooks": { 22 | "pre-commit": "npm run lint" 23 | } 24 | }, 25 | "browserslist": [ 26 | "extends @edx/browserslist-config" 27 | ], 28 | "dependencies": { 29 | "bootstrap": "4.6.2" 30 | }, 31 | "devDependencies": { 32 | "@edx/browserslist-config": "^1.1.1", 33 | "@edx/stylelint-config-edx": "2.3.0", 34 | "@fortawesome/fontawesome-svg-core": "1.2.36", 35 | "@fortawesome/free-solid-svg-icons": "5.15.4", 36 | "@fortawesome/react-fontawesome": "0.2.6", 37 | "chroma-js": "2.6.0", 38 | "classnames": "2.5.1", 39 | "gh-pages": "6.3.0", 40 | "husky": "8.0.3", 41 | "jquery": "3.7.1", 42 | "lodash": "4.17.21", 43 | "node-sass": "9.0.0", 44 | "popper.js": "1.16.1", 45 | "prop-types": "15.8.1", 46 | "react": "17.0.2", 47 | "react-dom": "17.0.2", 48 | "react-router-dom": "6.30.2", 49 | "react-router-hash-link": "1.2.2", 50 | "react-scripts": "5.0.1", 51 | "semantic-release": "^21.0.7" 52 | }, 53 | "release": { 54 | "branch": "master", 55 | "tagFormat": "v${version}", 56 | "verifyConditions": [ 57 | "@semantic-release/npm", 58 | { 59 | "path": "@semantic-release/github", 60 | "assets": { 61 | "path": "dist/*" 62 | } 63 | } 64 | ], 65 | "analyzeCommits": "@semantic-release/commit-analyzer", 66 | "generateNotes": "@semantic-release/release-notes-generator", 67 | "prepare": "@semantic-release/npm", 68 | "publish": [ 69 | "@semantic-release/npm", 70 | { 71 | "path": "@semantic-release/github", 72 | "assets": { 73 | "path": "dist/*" 74 | } 75 | } 76 | ], 77 | "success": [], 78 | "fail": [] 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_content.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable no-duplicate-selectors, selector-max-combinators, selector-max-compound-selectors, selector-max-type, selector-no-qualifying-type 2 | 3 | // 4 | // Automatically style Markdown-based tables like a Bootstrap `.table`. 5 | // 6 | 7 | .bd-content { 8 | order: 1; 9 | 10 | // Hack the sticky header 11 | > h2[id], 12 | > h3[id], 13 | > h4[id] { 14 | pointer-events: none; 15 | 16 | &::before { 17 | display: block; 18 | height: 6rem; 19 | margin-top: -6rem; 20 | content: ""; 21 | } 22 | } 23 | 24 | > table { 25 | width: 100%; 26 | max-width: 100%; 27 | margin-bottom: 1rem; 28 | 29 | @include media-breakpoint-down(md) { 30 | display: block; 31 | overflow-x: auto; 32 | -ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057 33 | 34 | &.table-bordered { 35 | border: 0; 36 | } 37 | } 38 | 39 | // Cells 40 | > thead, 41 | > tbody, 42 | > tfoot { 43 | > tr { 44 | > th, 45 | > td { 46 | padding: $table-cell-padding; 47 | vertical-align: top; 48 | border: 1px solid $table-border-color; 49 | 50 | > p:last-child { 51 | margin-bottom: 0; 52 | } 53 | } 54 | } 55 | } 56 | 57 | // Prevent breaking of code (e.g., Grunt tasks list) 58 | td:first-child > code { 59 | white-space: nowrap; 60 | } 61 | } 62 | } 63 | 64 | .bd-content-title { 65 | display: block; 66 | pointer-events: auto; 67 | } 68 | 69 | // 70 | // Docs sections 71 | // 72 | 73 | .bd-content { 74 | > h2:not(:first-child) { 75 | margin-top: 3rem; 76 | } 77 | 78 | > h3 { 79 | margin-top: 1.5rem; 80 | } 81 | 82 | > ul li, 83 | > ol li { 84 | margin-bottom: .25rem; 85 | } 86 | 87 | @include media-breakpoint-up(lg) { 88 | > ul, 89 | > ol, 90 | > p { 91 | max-width: 80%; 92 | } 93 | } 94 | } 95 | 96 | .bd-title { 97 | margin-top: 1rem; 98 | // margin-bottom: .5rem; 99 | // font-weight: 300; 100 | 101 | @include media-breakpoint-up(sm) { 102 | // font-size: 3rem; 103 | } 104 | } 105 | 106 | .bd-lead { 107 | // font-size: 1.125rem; 108 | // font-weight: 300; 109 | 110 | @include media-breakpoint-up(sm) { 111 | // max-width: 80%; 112 | // margin-bottom: 1rem; 113 | // font-size: 1.5rem; 114 | } 115 | } 116 | 117 | .bd-text-purple { color: $bd-purple; } 118 | .bd-text-purple-bright { color: $bd-purple-bright; } 119 | -------------------------------------------------------------------------------- /src/pages/Basics.Typography.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MeasuredItem from '../common/MeasuredItem'; 3 | 4 | export default function Typography() { 5 | const typeMeasurements = { 6 | 'font-family': null, 7 | 'font-weight': null, 8 | 'font-size': null, 9 | 'line-height': null, 10 | 'letter-spacing': null, 11 | }; 12 | 13 | const renderTypeItem = ({ name, tagClass, tag }) => { 14 | return ( 15 | { 20 | return React.createElement(tag, { className: tagClass + ' mb-0 type-scale-item-example' }, ( 21 | {name} 22 | )); 23 | }} 24 | renderValues={styleValues => { 25 | if (!styleValues['font-family']) return; 26 | 27 | const fontFamily = styleValues['font-family'].split(',')[0]; 28 | const fontSize = Math.round(parseFloat(styleValues['font-size'])); 29 | const lineHeight = Math.round(parseFloat(styleValues['line-height'])); 30 | let letterSpacing = styleValues['letter-spacing']; 31 | const fontWeight = styleValues['font-weight']; 32 | 33 | const getWeightName = (weight) => { 34 | if (weight < 400) return 'Light'; 35 | if (weight < 500) return 'Regular'; 36 | if (weight < 600) return 'Semi-bold'; 37 | return 'Bold'; 38 | } 39 | 40 | if (letterSpacing !== 'normal') { 41 | letterSpacing = (parseFloat(letterSpacing)/fontSize) + 'em'; 42 | } 43 | 44 | return ( 45 |
46 | {fontFamily} {getWeightName(fontWeight)} 47 |   • {fontSize}px / {lineHeight}px 48 | {letterSpacing !== 'normal' ? ` • ${letterSpacing}` : null} 49 |
50 | ); 51 | }} 52 | /> 53 | ); 54 | } 55 | 56 | return ( 57 |
58 |
{renderTypeItem({name: 'Display', tag: 'h1', tagClass: 'display-3'})}
59 |
{renderTypeItem({name: 'Heading 1', tag: 'h1', tagClass: ''})}
60 |
{renderTypeItem({name: 'Heading 2', tag: 'h2', tagClass: ''})}
61 |
{renderTypeItem({name: 'Heading 3', tag: 'h3', tagClass: ''})}
62 |
{renderTypeItem({name: 'Heading 4', tag: 'h4', tagClass: ''})}
63 |
{renderTypeItem({name: 'Heading 5', tag: 'h5', tagClass: ''})}
64 |
{renderTypeItem({name: 'Heading 6', tag: 'h6', tagClass: ''})}
65 |
66 |
{renderTypeItem({name: 'Large Paragraph', tag: 'p', tagClass: 'lead'})}
67 |
{renderTypeItem({name: 'Paragraph', tag: 'p', tagClass: ''})}
68 |
{renderTypeItem({name: 'Small ', tag: 'p', tagClass: 'small'})}
69 |
70 |
{renderTypeItem({name: 'Label ', tag: 'label'})}
71 |
72 | ); 73 | } -------------------------------------------------------------------------------- /src/pages/Basics.ButtonsAndLinks.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 3 | import { faCheckCircle } from '@fortawesome/free-solid-svg-icons'; 4 | 5 | 6 | export default function ButtonsAndLinks() { 7 | return ( 8 |
9 |
10 |
Buttons
11 |

Buttons are used as triggers for actions. There should only be one primary button per page.

12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
26 | 27 |
28 |
29 |
30 | 31 |
32 |
Color Variants (Use sparingly)
33 | 34 |
35 | 36 | 37 | 38 | 39 |
40 | 41 |
42 | 43 | 44 | 45 | 46 |
47 |
48 | 49 |
50 |
Sizes
51 | 52 |
53 | 54 | 55 |
56 |
57 | 58 |
59 |
With Icons
60 | 61 |
62 | 66 | 70 |
71 |
72 | 73 | 74 | 75 |
76 | ); 77 | } -------------------------------------------------------------------------------- /src/pages/Examples.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DocSection from '../DocSection'; 3 | 4 | export default class Examples extends React.Component { 5 | render() { 6 | return ( 7 |
8 |

Examples

9 | 10 | 11 | 12 |

On the events
in question

13 | 20 |

On glancing over my notes of the seventy odd cases in which I have during the last eight years studied the methods of my friend Sherlock Holmes, I find many tragic, some comic, a large number merely strange, but none commonplace; for, working as he did rather for the love of his art than for the acquirement of wealth, he refused to associate himself with any investigation which did not tend towards the unusual, and even the fantastic.

21 |

What we know:

22 |

The events in question occurred in the early days of my association with Holmes:

23 |
    24 |
  • We were sharing rooms as bachelors in Baker Street.
  • 25 |
  • It is possible that I might have placed them upon record before.
  • 26 |
  • A promise of secrecy was made at the time.
  • 27 |
  • It was early in April in the year '83.
  • 28 |
29 |

30 | Solve the case 31 | Ask Watson 32 |

33 | 34 |
35 |
36 |
37 | 38 |
39 |

Not sure where to look?

40 |
41 | 42 |
43 |
44 |
45 | 48 |
49 |
50 |
51 |
52 |
53 | 54 | 60 |
61 |
62 |
63 |
64 | 65 |
66 |
67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/pages/Basics.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Colors from './Basics.Colors'; 3 | import Typography from './Basics.Typography'; 4 | import ButtonsAndLinks from './Basics.ButtonsAndLinks'; 5 | import Themes from './Basics.Themes'; 6 | import MiscBasics from './Basics.MiscBasics'; 7 | import DocSection from '../DocSection'; 8 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 9 | import { faCheckCircle, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; 10 | 11 | export default class Basics extends React.Component { 12 | render() { 13 | return ( 14 |
15 |

Basics

16 |

Basic style elements.

17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Links
32 |

To navigate to a new page use a link instead. By default all links are primary blue and have underlines. Removing the underline is fine, but color must not be used as the only visual means of indicating interactivity.

33 | 39 |
40 |
41 | 42 |
43 |
44 |
To do:
45 |
    46 |
  • Add documentation on how buttons should be laid out: left aligned. primary first, others second.
  • 47 |
  • Flippable for RTL.
  • 48 |
49 |
50 |
51 |
52 | 53 | 54 |

Examples and usage guidelines for icon styles.

55 |

See Font Awesome (Free)

56 |
57 | 58 | 59 |

Examples and usage guidelines for miscellaneous elements.

60 | 61 |
62 | 63 | 64 |

Examples and usage guidelines for theming.

65 | 66 |
67 | 68 |
69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/pages/bootstrap/Alerts.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 3 | import { 4 | faCheckCircle, 5 | faExclamationTriangle, 6 | faInfoCircle, 7 | faExclamationCircle, 8 | faTimes 9 | } from '@fortawesome/free-solid-svg-icons'; 10 | 11 | export default class Alerts extends React.Component { 12 | render() { 13 | return ( 14 |
15 |

16 | Alerts 17 |

18 |

19 | Provide contextual feedback messages for typical user actions with a handful of available and flexible alert 20 | messages. 21 |

22 | 23 |

Notes

24 |
    25 |
  • The four alerts below are representative samples. The various buttons/links are optional.
  • 26 |
27 | 28 |
29 |
30 | 33 |
34 |
35 | 36 |
37 |
38 |
Well done!
39 |

You've successfully read this important alert message.

40 | 41 |
42 |
43 |
44 | 45 |
46 |
47 | 48 |
49 |
50 |
Oh snap!
51 |

Change a few things up and try submitting again.

52 |
    53 |
  • You forgot to tell me I'm handsome.
  • 54 |
  • Please upload a copy of your house key.
  • 55 |
  • The cat requires that you compliment him.
  • 56 |
57 | Need help? 58 |
59 |
60 | 61 |
62 |
63 | 64 |
65 |
66 |
Warning!
67 |
Better check yourself before you wreck yourself.
68 |
69 |
70 | 71 |
72 |
73 | 74 |
75 |
76 |
Heads up!
77 |

This alert needs your attention, but not urgently.

78 | 79 | Need help? 80 |
81 |
82 |
83 |
84 | ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_sidebar.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // 4 | // Right side table of contents 5 | // 6 | 7 | .bd-toc { 8 | @supports (position: sticky) { 9 | position: sticky; 10 | top: 0; 11 | height: 100vh; 12 | overflow-y: auto; 13 | } 14 | order: 2; 15 | padding-top: 1.5rem; 16 | padding-bottom: 1.5rem; 17 | font-size: .875rem; 18 | } 19 | 20 | .section-nav { 21 | padding-left: 0; 22 | border-left: 1px solid #eee; 23 | 24 | ul { 25 | padding-left: 1rem; 26 | } 27 | } 28 | 29 | .toc-entry { 30 | display: block; 31 | 32 | a { 33 | display: block; 34 | padding: .125rem 1.5rem; 35 | color: #99979c; 36 | 37 | &:hover { 38 | color: $blue; 39 | text-decoration: none; 40 | } 41 | } 42 | } 43 | 44 | // 45 | // Left side navigation 46 | // 47 | 48 | .bd-sidebar { 49 | order: 0; 50 | padding-top:3rem; 51 | // background-color: #f5f2f9; 52 | border-bottom: 1px solid rgba(0, 0, 0, .1); 53 | 54 | @include media-breakpoint-up(md) { 55 | @supports (position: sticky) { 56 | position: sticky; 57 | top: 0rem; 58 | z-index: 1000; 59 | height: 100vh; 60 | } 61 | border-right: 1px solid rgba(0, 0, 0, .1); 62 | } 63 | 64 | @include media-breakpoint-up(xl) { 65 | flex: 0 1 320px; 66 | } 67 | } 68 | 69 | .bd-links { 70 | padding-top: 1rem; 71 | padding-bottom: 1rem; 72 | margin-right: -15px; 73 | margin-left: -15px; 74 | 75 | @include media-breakpoint-up(md) { 76 | @supports (position: sticky) { 77 | max-height: calc(100vh - 9rem); 78 | overflow-y: auto; 79 | } 80 | } 81 | 82 | // Override collapse behaviors 83 | @include media-breakpoint-up(md) { 84 | display: block !important; 85 | } 86 | } 87 | 88 | .bd-search { 89 | position: relative; // To contain the Algolia search 90 | padding: 1rem 15px; 91 | margin-right: -15px; 92 | margin-left: -15px; 93 | border-bottom: 1px solid rgba(0, 0, 0, .05); 94 | 95 | .form-control:focus { 96 | border-color: $bd-purple-bright; 97 | box-shadow: 0 0 0 3px rgba($bd-purple-bright, .25); 98 | } 99 | } 100 | 101 | .bd-search-docs-toggle { 102 | line-height: 1; 103 | color: $gray-900; 104 | } 105 | 106 | .bd-sidenav { 107 | display: none; 108 | } 109 | 110 | .bd-toc-link { 111 | display: block; 112 | padding: .25rem 1.5rem; 113 | font-weight: 600; 114 | color: rgba(0, 0, 0, .65); 115 | 116 | &:hover { 117 | color: rgba(0, 0, 0, .85); 118 | text-decoration: none; 119 | } 120 | } 121 | 122 | .bd-toc-item { 123 | &.active { 124 | margin-bottom: 1rem; 125 | 126 | &:not(:first-child) { 127 | margin-top: 1rem; 128 | } 129 | 130 | > .bd-toc-link { 131 | color: rgba(0, 0, 0, .85); 132 | 133 | &:hover { 134 | background-color: transparent; 135 | } 136 | } 137 | 138 | > .bd-sidenav { 139 | display: block; 140 | } 141 | } 142 | } 143 | 144 | // All levels of nav 145 | .bd-sidebar .nav > li > a { 146 | display: block; 147 | padding: .25rem 1.5rem; 148 | font-size: 90%; 149 | color: rgba(0, 0, 0, .65); 150 | } 151 | 152 | .bd-sidebar .nav > li > a:hover { 153 | color: rgba(0, 0, 0, .85); 154 | text-decoration: none; 155 | background-color: transparent; 156 | } 157 | 158 | .bd-sidebar .nav > .active > a, 159 | .bd-sidebar .nav > .active:hover > a { 160 | font-weight: 600; 161 | color: rgba(0, 0, 0, .85); 162 | background-color: transparent; 163 | } 164 | -------------------------------------------------------------------------------- /src/pages/bootstrap/Modal.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Modal extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

8 | Modal 9 |

10 |

11 | Use Bootstrap’s JavaScript modal plugin to add dialogs to your site for lightboxes, user notifications, or 12 | completely custom content. 13 |

14 | 15 |

To do

16 |
    17 |
  • Abby: to provide design.
  • 18 |
19 | 20 |

21 | Examples 22 |

23 | 26 |
27 |
28 |
29 |
30 |
31 |
Modal title
32 | 35 |
36 |
37 |

Modal body text goes here.

38 |
39 |
40 | 43 | 46 |
47 |
48 |
49 |
50 |
51 | 52 |

53 | Live demo 54 |

55 | 87 |
88 | 91 |
92 |
93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 15 | 16 | 25 | edX Bootstrap Docs 26 | 27 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
64 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/pages/bootstrap/LayoutUtils.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class LayoutUtils extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Utilities for layout

8 |

For faster mobile-friendly and responsive development, Bootstrap includes dozens of utility classes for showing, hiding, aligning, and spacing content.

9 | 10 |

Changing display

11 |

Use our display utilities for responsively toggling common values of the display property. Mix it with our grid system, content, or components to show or hide them across specific viewports.

12 |

Flexbox options

13 |

Bootstrap 4 is built with flexbox, but not every element’s display has been changed to display: flex as this would add many unnecessary overrides and unexpectedly change key browser behaviors. Most of our components are built with flexbox enabled.

14 |

Should you need to add display: flex to an element, do so with .d-flex or one of the responsive variants (e.g., .d-sm-flex). You’ll need this class or display value to allow the use of our extra flexbox utilities for sizing, alignment, spacing, and more.

15 |

Margin and padding

16 |

Use the margin and padding spacing utilities to control how elements and components are spaced and sized. Bootstrap 4 includes a five-level scale for spacing utilities, based on a 1rem value default $spacer variable. Choose values for all viewports (e.g., .mr-3 for margin-right: 1rem), or pick responsive variants to target specific viewports (e.g., .mr-md-3 for margin-right: 1rem starting at the md breakpoint).

17 |

Toggle visibility

18 |

When toggling display isn’t needed, you can toggle the visibility of an element with our visibility utilities. Invisible elements will still affect the layout of the page, but are visually hidden from visitors.

19 |
20 | 21 | ); 22 | } 23 | } -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ############## 2 | edX Bootstrap 3 | ############## 4 | 5 | .. image:: https://badge.fury.io/js/%40edx%2Fedx-bootstrap.svg 6 | :target: https://badge.fury.io/js/%40edx%2Fedx-bootstrap 7 | .. highlight:: css 8 | 9 | ******** 10 | Purpose 11 | ******** 12 | 13 | This library is an extension of `Bootstrap 4 `_ 14 | for use with edX and openEdX. 15 | 16 | Installation 17 | ============= 18 | 19 | Using npm:: 20 | 21 | npm install --save @edx/edx-bootstrap 22 | 23 | Cloning and Startup 24 | =================== 25 | 26 | .. code-block:: 27 | 28 | 29 | 1. Clone your new repo: 30 | 31 | ``git clone https://github.com/openedx/edx-bootstrap.git`` 32 | 33 | 2. Use node v18.x. 34 | 35 | The current version of the micro-frontend build scripts support node 18. 36 | Using other major versions of node *may* work, but this is unsupported. For 37 | convenience, this repository includes an .nvmrc file to help in setting the 38 | correct node version via `nvm `_. 39 | 40 | 3. Install npm dependencies: 41 | 42 | ``cd edx-bootstrap && npm ci`` 43 | 44 | Usage 45 | ===== 46 | 47 | Add the following import in your project's base scss file:: 48 | 49 | @import "~@edx/edx-bootstrap/scss/edx/theme.scss"; 50 | 51 | Or for Open edX users:: 52 | 53 | @import "~@edx/edx-bootstrap/scss/open-edx/theme.scss"; 54 | 55 | This includes everything you need. Bootstrap is included so you don't 56 | need to add it in your project. If you need more control, see the 57 | theming section. 58 | 59 | Alternatively, you can download this repo and use one of the compiled outputs: 60 | 61 | - ``dist/open-edx/theme.css`` (Open edX bootstrap, extensions, & theme) 62 | - ``dist/edx/theme.css`` (edX bootstrap, extensions, & theme) 63 | - ``dist/core/core.css`` (edX bootstrap & extensions only) 64 | 65 | Theming 66 | ======= 67 | 68 | The content of a `theme.scss` file:: 69 | 70 | // Optional 71 | @import "my-fonts"; 72 | @import "my-variables"; 73 | 74 | // Required core (includes bootstrap and extensions) 75 | @import "@edx/edx-boostrap/scss/core/core.scss"; 76 | 77 | // The rest of your scss 78 | // ... 79 | 80 | To create a theme, make a copy of the ``scss/open-edx`` folder in your own project 81 | and make changes. Then include it before you include edx-bootstrap:: 82 | 83 | @import "fonts"; 84 | @import "variables"; 85 | 86 | // If you are creating your own theme remove 87 | // the "../core/core" import with the line below. 88 | @import "../core/core"; 89 | // @import "@edx/edx-boostrap/scss/core/core.scss"; 90 | 91 | @import "overrides"; 92 | 93 | Getting Help 94 | ============ 95 | 96 | If you’re having trouble, you can ask in the front-end channel on Slack or contact the Frontend Working Group: 97 | 98 | - `#front-end `_ 99 | - `#frontend-working-group `_ 100 | 101 | License 102 | ======= 103 | 104 | The code in this repository uses the Apache 2.0 license unless otherwise noted. 105 | Please see the `LICENSE file `_ 106 | for details. 107 | 108 | Documentation 109 | ============= 110 | 111 | Documentation details can be found in the `docs index.rst`_. 112 | 113 | .. _docs index.rst: docs/index.rst 114 | 115 | 116 | How to Contribute 117 | ================= 118 | 119 | Contributions are very welcome, but for legal reasons, you must submit a 120 | signed `individual contributor agreement`_ before we can accept your 121 | contribution. See our `CONTRIBUTING`_ file for more information – it 122 | also contains guidelines for how to maintain high code quality, which 123 | will make your contribution more likely to be accepted. 124 | 125 | 126 | Reporting Security Issues 127 | ========================= 128 | 129 | Please do not report security issues in public. Please email 130 | security@openedx.org. 131 | 132 | .. _individual contributor agreement: https://open.edx.org/wp-content/uploads/2019/01/individual-contributor-agreement.pdf 133 | .. _CONTRIBUTING: https://github.com/openedx/.github/blob/master/CONTRIBUTING.md 134 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_algolia.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Docsearch overrides 4 | // 5 | // `!important` indicates overridden properties. 6 | .algolia-autocomplete { 7 | display: block !important; 8 | flex: 1; 9 | 10 | // Menu container 11 | .ds-dropdown-menu { 12 | width: 100%; 13 | min-width: 0 !important; 14 | max-width: none !important; 15 | padding: .75rem 0 !important; 16 | background-color: $white; 17 | background-clip: padding-box; 18 | border: 1px solid rgba(0, 0, 0, .1); 19 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); 20 | 21 | @include media-breakpoint-up(md) { 22 | width: 175%; 23 | } 24 | 25 | // Caret 26 | &::before { 27 | display: none !important; 28 | } 29 | 30 | [class^="ds-dataset-"] { 31 | padding: 0 !important; 32 | overflow: visible !important; 33 | background-color: transparent !important; 34 | border: 0 !important; 35 | } 36 | 37 | .ds-suggestions { 38 | margin-top: 0 !important; 39 | } 40 | } 41 | 42 | .algolia-docsearch-suggestion { 43 | padding: 0 !important; 44 | overflow: visible !important; 45 | } 46 | 47 | .algolia-docsearch-suggestion--category-header { 48 | padding: .125rem 1rem !important; 49 | margin-top: 0 !important; 50 | font-size: .875rem !important; 51 | font-weight: 600 !important; 52 | color: $bd-purple-bright !important; 53 | border-bottom: 0 !important; 54 | } 55 | 56 | .algolia-docsearch-suggestion--wrapper { 57 | float: none !important; 58 | padding-top: 0 !important; 59 | } 60 | 61 | // Section header 62 | .algolia-docsearch-suggestion--subcategory-column { 63 | float: none !important; 64 | width: auto !important; 65 | padding: 0 !important; 66 | text-align: left !important; 67 | } 68 | 69 | .algolia-docsearch-suggestion--subcategory-inline { 70 | display: block !important; 71 | font-size: .875rem; 72 | color: $gray-700; 73 | 74 | &::after { 75 | padding: 0 .25rem; 76 | content: "/"; 77 | } 78 | } 79 | 80 | .algolia-docsearch-suggestion--content { 81 | display: flex; 82 | flex-wrap: wrap; 83 | float: none !important; 84 | width: 100% !important; 85 | padding: .25rem 1rem !important; 86 | 87 | // Vertical divider between column header and content 88 | &::before { 89 | display: none !important; 90 | } 91 | } 92 | 93 | .ds-suggestion { 94 | &:not(:first-child) { 95 | .algolia-docsearch-suggestion--category-header { 96 | padding-top: .75rem !important; 97 | margin-top: .75rem !important; 98 | border-top: 1px solid rgba(0, 0, 0, .1); 99 | } 100 | } 101 | 102 | .algolia-docsearch-suggestion--subcategory-column { 103 | display: none !important; 104 | } 105 | } 106 | 107 | .algolia-docsearch-suggestion--title { 108 | display: block; 109 | margin-bottom: 0 !important; 110 | font-size: .875rem !important; 111 | font-weight: 400 !important; 112 | } 113 | 114 | .algolia-docsearch-suggestion--text { 115 | flex: 0 0 100%; 116 | max-width: 100%; 117 | padding: .2rem 0; 118 | font-size: .8125rem !important; 119 | font-weight: 400; 120 | line-height: 1.25 !important; 121 | color: $gray-600; 122 | } 123 | 124 | .algolia-docsearch-footer { 125 | float: none !important; 126 | width: auto !important; 127 | height: auto !important; 128 | padding: .75rem 1rem 0; 129 | font-size: .75rem !important; 130 | line-height: 1 !important; 131 | color: #767676 !important; 132 | border-top: 1px solid rgba(0, 0, 0, .1); 133 | } 134 | 135 | .algolia-docsearch-footer--logo { 136 | display: inline !important; 137 | overflow: visible !important; 138 | color: inherit !important; 139 | text-indent: 0 !important; 140 | background: none !important; 141 | } 142 | 143 | .algolia-docsearch-suggestion--highlight { 144 | color: #5f2dab; 145 | background-color: rgba(154, 132, 187, .12); 146 | } 147 | 148 | .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { 149 | box-shadow: inset 0 -2px 0 0 rgba(95, 45, 171, .5) !important; 150 | } 151 | 152 | .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { 153 | background-color: rgba(208, 189, 236, .15) !important; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/pages/bootstrap/Jumbotron.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Jumbotron extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Jumbotron

8 |

Lightweight, flexible component for showcasing hero unit style content.

9 |

To do

10 |
    11 |
  • Delete this.
  • 12 |
13 |

A lightweight, flexible component that can optionally extend the entire viewport to showcase key marketing messages on your site.

14 |
15 |
16 |

Hello, world!

17 |

This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.

18 | 19 |

It uses utility classes for typography and spacing to space content out within the larger container.

20 | Learn more 21 |
22 |
23 |
<div class="jumbotron">{"\n"}{"  "}<h1 class="display-4">Hello, world!</h1>{"\n"}{"  "}<p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>{"\n"}{"  "}<hr class="my-4">{"\n"}{"  "}<p>It uses utility classes for typography and spacing to space content out within the larger container.</p>{"\n"}{"  "}<a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>{"\n"}</div>
24 |

To make the jumbotron full width, and without rounded corners, add the .jumbotron-fluid modifier class and add a .container or .container-fluid within.

25 |
26 |
27 |
28 |

Fluid jumbotron

29 |

This is a modified jumbotron that occupies the entire horizontal space of its parent.

30 |
31 |
32 |
33 |
<div class="jumbotron jumbotron-fluid">{"\n"}{"  "}<div class="container">{"\n"}{"    "}<h1 class="display-4">Fluid jumbotron</h1>{"\n"}{"    "}<p class="lead">This is a modified jumbotron that occupies the entire horizontal space of its parent.</p>{"\n"}{"  "}</div>{"\n"}</div>
34 |
35 | 36 | ); 37 | } 38 | } -------------------------------------------------------------------------------- /src/pages/bootstrap/Progress.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Progress extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Progress

8 |

Documentation and examples for using Bootstrap custom progress bars featuring support for stacked bars, animated backgrounds, and text labels.

9 | 10 |

To do

11 |
    12 |
  • Document as progress bar (no animation, progress thru a course) and as loading bar (animated and completing)
  • 13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 | 34 |
35 |
36 |
37 |
38 |
39 | 40 |

Labels

41 | 42 |
43 |
44 |
25%
45 |
46 |
47 | 48 |

Backgrounds

49 | 50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | 65 | 66 | 67 |

Striped

68 | 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | 87 |

Animated stripes

88 | 89 |
90 |
91 |
92 |
93 |
94 | 95 |
96 | 97 | ); 98 | } 99 | } -------------------------------------------------------------------------------- /src/pages/bootstrap/Tables.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Tables extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Tables

8 | 9 |

To do

10 |
    11 |
  • Todo responsive, tables become lists.
  • 12 |
13 | 14 |

Borderless table

15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3Larry the Bird@twitter
46 |
47 | 48 |

Bordered table

49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3Larry the Bird@twitter
80 |
81 | 82 |

Striped rows

83 | 84 |
85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
#FirstLastHandle
1MarkOtto@mdo
2JacobThornton@fat
3Larrythe Bird@twitter
115 |
116 | 117 |

Contextual classes

118 |

Use contextual classes to color table rows or individual cells.

119 |
120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 |
ClassHeadingHeading
ActiveCellCell
DefaultCellCell
SuccessCellCell
DangerCellCell
WarningCellCell
InfoCellCell
161 |
162 | 163 | 164 | 165 | 166 | 167 |
168 | 169 | ); 170 | } 171 | } -------------------------------------------------------------------------------- /src/pages/Navigation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DocSection from '../DocSection'; 3 | 4 | export default class Navigation extends React.Component { 5 | render() { 6 | return ( 7 |
8 |

Navigation

9 |

Examples and usage guidelines for navigation elements.

10 | 11 | 12 |
13 | 20 | 30 | 40 | 53 |
54 |
55 | 56 | 57 |

58 | Navigation elements available in Bootstrap share general markup and styles, from the base{' '} 59 | .nav class to the active and disabled states. Swap modifier 60 | classes to change styles. 61 |

62 | 63 |
64 | 86 |
87 |
88 | 89 | 90 |

Examples and usage guidelines for tabs.

91 |

92 | Takes the basic nav from above and adds the .nav-tabs class to 93 | generate a tabbed interface. Use them to create tabbable regions with our{' '} 94 | tab JavaScript plugin. 95 |

96 |
97 | 119 |
120 |
121 | 122 | 123 |

Examples and usage guidelines for search interfaces.

124 |
125 |
126 | ); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /scss/edx/custom/_edx-custom-card.scss: -------------------------------------------------------------------------------- 1 | $charcoal-grey: #393f43 !default; 2 | $dark-slate-blue: #17285d !default; 3 | $ice-blue: #f5f8ff !default; 4 | $sapphire: #23419f !default; 5 | $silver: #d6dbe0 !default; 6 | $slate-grey: #636c72 !default; 7 | $light-border: 1px solid $silver !default; 8 | $edx-shadow-color: rgba(0, 0, 0, 0.3) !default; 9 | 10 | @mixin edx-shadow { 11 | box-shadow: 0 2px 2px 0 $edx-shadow-color; 12 | } 13 | 14 | .edx-custom { 15 | &.card { 16 | border: { 17 | top: $light-border; 18 | bottom: 0; 19 | left: 0; 20 | right: 0; 21 | radius: unset; 22 | } 23 | 24 | .card-content { 25 | display: flex; 26 | flex-direction: column; 27 | font-family: $font-family-sans-serif; 28 | } 29 | 30 | .card-title { 31 | text-decoration: underline; 32 | } 33 | 34 | .card-body { 35 | padding: 15px 20px; 36 | 37 | .card-title { 38 | text-decoration: underline; 39 | margin: 0 0 5px; 40 | font: { 41 | size: 1.25rem; 42 | weight: $font-weight-normal; 43 | } 44 | 45 | padding-bottom: 10px; 46 | line-height: 1.5; 47 | } 48 | 49 | .card-partner { 50 | font-size: 1rem; 51 | 52 | @include media-breakpoint-up(lg) { 53 | font-size: 0.875rem; 54 | } 55 | 56 | @include media-breakpoint-up(xl) { 57 | font-size: 1rem; 58 | } 59 | } 60 | } 61 | 62 | .card-footer, 63 | .out-of, 64 | .type, 65 | .card-overlay { 66 | display: none; 67 | } 68 | 69 | .card-stats { 70 | width: 100%; 71 | display: flex; 72 | justify-content: space-between; 73 | 74 | align: { 75 | items: flex-end; 76 | self: flex-end; 77 | } 78 | 79 | padding: { 80 | left: 20px; 81 | right: 20px; 82 | } 83 | 84 | color: $charcoal-grey; 85 | font-size: 1rem; 86 | 87 | .course-count { 88 | margin-right: 20px; 89 | } 90 | } 91 | 92 | @include media-breakpoint-up(sm) { 93 | @include edx-shadow(); 94 | 95 | border: $light-border; 96 | border-radius: 4px; 97 | 98 | .card-content { 99 | height: 190px; 100 | 101 | &:hover, 102 | &:focus-within, 103 | &:active { 104 | background-color: $ice-blue; 105 | } 106 | } 107 | 108 | .card-overlay { 109 | display: block; 110 | top: 100%; 111 | bottom: 0; 112 | left: 0; 113 | right: 0; 114 | width: 100%; 115 | z-index: 1; 116 | border-color: $silver; 117 | 118 | &::after { 119 | content: ""; 120 | width: 28px; 121 | height: 28px; 122 | background: $ice-blue; 123 | position: absolute; 124 | top: -14px; 125 | right: calc(50% - 14px); 126 | transform: rotate(45deg); 127 | 128 | border: { 129 | left: 2px solid $silver; 130 | top: 2px solid $silver; 131 | } 132 | } 133 | 134 | .card-overlay-link { 135 | text-decoration: underline; 136 | color: $sapphire; 137 | } 138 | 139 | .card-overlay-body { 140 | background: $ice-blue; 141 | font-size: 1rem; 142 | color: $slate-grey; 143 | padding: 20px; 144 | border: $light-border; 145 | border-radius: 4px; 146 | 147 | .h5 { 148 | font: { 149 | size: 1rem; 150 | weight: $font-weight-bold; 151 | } 152 | } 153 | } 154 | 155 | .card-overlay-close { 156 | right: 0%; 157 | top: 0%; 158 | background: none; 159 | } 160 | } 161 | 162 | .card-body { 163 | height: 125px; 164 | padding: 20px; 165 | 166 | .card-title { 167 | padding-bottom: 0; 168 | } 169 | 170 | .h6 { 171 | font-size: 1rem; 172 | } 173 | 174 | .out-of { 175 | display: block; 176 | color: $white; 177 | position: relative; 178 | z-index: 0; 179 | border-radius: 0 4px 0 0; 180 | overflow: hidden; 181 | 182 | &::before { 183 | content: ''; 184 | position: absolute; 185 | top: 0; 186 | right: 0; 187 | z-index: -1; 188 | border: 32px solid $dark-slate-blue; 189 | 190 | border: { 191 | bottom-color: transparent; 192 | left-color: transparent; 193 | } 194 | } 195 | 196 | min: { 197 | height: 65px; 198 | width: 65px; 199 | } 200 | 201 | margin: { 202 | top: -20px; 203 | right: -20px; 204 | } 205 | 206 | padding: { 207 | top: 12px; 208 | left: 34px; 209 | } 210 | 211 | font-size: 0.875rem; 212 | } 213 | 214 | &.program { 215 | background-color: $dark-slate-blue; 216 | border-top: { 217 | right-radius: 3px; 218 | left-radius: 3px; 219 | } 220 | 221 | color: $white; 222 | box-sizing: border-box; 223 | 224 | .card-partner, 225 | .card-title { 226 | color: $white; 227 | } 228 | 229 | .card-link:focus { 230 | outline: none; 231 | 232 | .card-title { 233 | outline: 1px dotted $white; 234 | } 235 | } 236 | 237 | .type { 238 | display: block; 239 | font: { 240 | size: 0.875rem; 241 | weight: $font-weight-bold; 242 | } 243 | 244 | margin: { 245 | top: -12px; 246 | right: -12px; 247 | } 248 | } 249 | } 250 | } 251 | 252 | .card-footer { 253 | display: block; 254 | color: $sapphire; 255 | width: 100%; 256 | border-top: $light-border; 257 | box-sizing: border-box; 258 | background-color: $white; 259 | height: 41px; 260 | 261 | &.btn { 262 | padding: 10px 20px; 263 | background-color: $white; 264 | color: $sapphire; 265 | justify-content: space-between; 266 | box-sizing: border-box; 267 | } 268 | 269 | &:hover, 270 | &.focus-within, 271 | &.active { 272 | background-color: $ice-blue; 273 | } 274 | 275 | &.expanded-true { 276 | background-color: $ice-blue; 277 | font-weight: $font-weight-bold; 278 | } 279 | 280 | .label-wrapper { 281 | display: flex; 282 | justify-content: space-between; 283 | } 284 | } 285 | 286 | .card-stats { 287 | padding: 10px 20px; 288 | height: 60px; 289 | } 290 | } 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /scss/open-edx/custom/_edx-custom-card.scss: -------------------------------------------------------------------------------- 1 | $charcoal-grey: #393f43 !default; 2 | $dark-slate-blue: #17285d !default; 3 | $ice-blue: #f5f8ff !default; 4 | $sapphire: #23419f !default; 5 | $silver: #d6dbe0 !default; 6 | $slate-grey: #636c72 !default; 7 | $light-border: 1px solid $silver !default; 8 | $edx-shadow-color: rgba(0, 0, 0, 0.3) !default; 9 | 10 | @mixin edx-shadow { 11 | box-shadow: 0 2px 2px 0 $edx-shadow-color; 12 | } 13 | 14 | .edx-custom { 15 | &.card { 16 | border: { 17 | top: $light-border; 18 | bottom: 0; 19 | left: 0; 20 | right: 0; 21 | radius: unset; 22 | } 23 | 24 | .card-content { 25 | display: flex; 26 | flex-direction: column; 27 | font-family: $font-family-sans-serif; 28 | } 29 | 30 | .card-title { 31 | text-decoration: underline; 32 | } 33 | 34 | .card-body { 35 | padding: 15px 20px; 36 | 37 | .card-title { 38 | text-decoration: underline; 39 | margin: 0 0 5px; 40 | font: { 41 | size: 1.25rem; 42 | weight: $font-weight-normal; 43 | } 44 | 45 | padding-bottom: 10px; 46 | line-height: 1.5; 47 | } 48 | 49 | .card-partner { 50 | font-size: 1rem; 51 | 52 | @include media-breakpoint-up(lg) { 53 | font-size: 0.875rem; 54 | } 55 | 56 | @include media-breakpoint-up(xl) { 57 | font-size: 1rem; 58 | } 59 | } 60 | } 61 | 62 | .card-footer, 63 | .out-of, 64 | .type, 65 | .card-overlay { 66 | display: none; 67 | } 68 | 69 | .card-stats { 70 | width: 100%; 71 | display: flex; 72 | justify-content: space-between; 73 | 74 | align: { 75 | items: flex-end; 76 | self: flex-end; 77 | } 78 | 79 | padding: { 80 | left: 20px; 81 | right: 20px; 82 | } 83 | 84 | color: $charcoal-grey; 85 | font-size: 1rem; 86 | 87 | .course-count { 88 | margin-right: 20px; 89 | } 90 | } 91 | 92 | @include media-breakpoint-up(sm) { 93 | @include edx-shadow(); 94 | 95 | border: $light-border; 96 | border-radius: 4px; 97 | 98 | .card-content { 99 | height: 190px; 100 | 101 | &:hover, 102 | &:focus-within, 103 | &:active { 104 | background-color: $ice-blue; 105 | } 106 | } 107 | 108 | .card-overlay { 109 | display: block; 110 | top: 100%; 111 | bottom: 0; 112 | left: 0; 113 | right: 0; 114 | width: 100%; 115 | z-index: 1; 116 | border-color: $silver; 117 | 118 | &::after { 119 | content: ""; 120 | width: 28px; 121 | height: 28px; 122 | background: $ice-blue; 123 | position: absolute; 124 | top: -14px; 125 | right: calc(50% - 14px); 126 | transform: rotate(45deg); 127 | 128 | border: { 129 | left: 2px solid $silver; 130 | top: 2px solid $silver; 131 | } 132 | } 133 | 134 | .card-overlay-link { 135 | text-decoration: underline; 136 | color: $sapphire; 137 | } 138 | 139 | .card-overlay-body { 140 | background: $ice-blue; 141 | font-size: 1rem; 142 | color: $slate-grey; 143 | padding: 20px; 144 | border: $light-border; 145 | border-radius: 4px; 146 | 147 | .h5 { 148 | font: { 149 | size: 1rem; 150 | weight: $font-weight-bold; 151 | } 152 | } 153 | } 154 | 155 | .card-overlay-close { 156 | right: 0%; 157 | top: 0%; 158 | background: none; 159 | } 160 | } 161 | 162 | .card-body { 163 | height: 125px; 164 | padding: 20px; 165 | 166 | .card-title { 167 | padding-bottom: 0; 168 | } 169 | 170 | .h6 { 171 | font-size: 1rem; 172 | } 173 | 174 | .out-of { 175 | display: block; 176 | color: $white; 177 | position: relative; 178 | z-index: 0; 179 | border-radius: 0 4px 0 0; 180 | overflow: hidden; 181 | 182 | &::before { 183 | content: ''; 184 | position: absolute; 185 | top: 0; 186 | right: 0; 187 | z-index: -1; 188 | border: 32px solid $dark-slate-blue; 189 | 190 | border: { 191 | bottom-color: transparent; 192 | left-color: transparent; 193 | } 194 | } 195 | 196 | min: { 197 | height: 65px; 198 | width: 65px; 199 | } 200 | 201 | margin: { 202 | top: -20px; 203 | right: -20px; 204 | } 205 | 206 | padding: { 207 | top: 12px; 208 | left: 34px; 209 | } 210 | 211 | font-size: 0.875rem; 212 | } 213 | 214 | &.program { 215 | background-color: $dark-slate-blue; 216 | border-top: { 217 | right-radius: 3px; 218 | left-radius: 3px; 219 | } 220 | 221 | color: $white; 222 | box-sizing: border-box; 223 | 224 | .card-partner, 225 | .card-title { 226 | color: $white; 227 | } 228 | 229 | .card-link:focus { 230 | outline: none; 231 | 232 | .card-title { 233 | outline: 1px dotted $white; 234 | } 235 | } 236 | 237 | .type { 238 | display: block; 239 | font: { 240 | size: 0.875rem; 241 | weight: $font-weight-bold; 242 | } 243 | 244 | margin: { 245 | top: -12px; 246 | right: -12px; 247 | } 248 | } 249 | } 250 | } 251 | 252 | .card-footer { 253 | display: block; 254 | color: $sapphire; 255 | width: 100%; 256 | border-top: $light-border; 257 | box-sizing: border-box; 258 | background-color: $white; 259 | height: 41px; 260 | 261 | &.btn { 262 | padding: 10px 20px; 263 | background-color: $white; 264 | color: $sapphire; 265 | justify-content: space-between; 266 | box-sizing: border-box; 267 | } 268 | 269 | &:hover, 270 | &.focus-within, 271 | &.active { 272 | background-color: $ice-blue; 273 | } 274 | 275 | &.expanded-true { 276 | background-color: $ice-blue; 277 | font-weight: $font-weight-bold; 278 | } 279 | 280 | .label-wrapper { 281 | display: flex; 282 | justify-content: space-between; 283 | } 284 | } 285 | 286 | .card-stats { 287 | padding: 10px 20px; 288 | height: 60px; 289 | } 290 | } 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /src/pages/bootstrap/Spinners.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Spinners extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Spinners

8 |

Indicate the loading state of a component or page with Bootstrap spinners, built entirely with HTML, CSS, and no JavaScript.

9 | 10 |

To do

11 |
    12 |
  • UX to provide
  • 13 |
  • Trim to one
  • 14 |
15 | 16 | 17 |
18 |
19 | Loading... 20 |
21 |
22 | 23 |

Colors

24 | 25 |
26 |
27 | Loading... 28 |
29 |
30 | Loading... 31 |
32 |
33 | Loading... 34 |
35 |
36 | Loading... 37 |
38 |
39 | Loading... 40 |
41 |
42 | Loading... 43 |
44 |
45 | Loading... 46 |
47 |
48 | Loading... 49 |
50 |
51 | 52 | 53 |

Growing spinner

54 | 55 |
56 |
57 | Loading... 58 |
59 |
60 | 61 | 62 |
63 |
64 | Loading... 65 |
66 |
67 | Loading... 68 |
69 |
70 | Loading... 71 |
72 |
73 | Loading... 74 |
75 |
76 | Loading... 77 |
78 |
79 | Loading... 80 |
81 |
82 | Loading... 83 |
84 |
85 | Loading... 86 |
87 |
88 | 89 |

Alignment

90 | 91 |

Margin

92 |

Use margin utilities like .m-5 for easy spacing.

93 |
94 |
95 | Loading... 96 |
97 |
98 | 99 |

Placement

100 | 101 |

Flex

102 |
103 |
104 |
105 | Loading... 106 |
107 |
108 |
109 | 110 |
111 |
112 | Loading... 113 | 115 |
116 | 117 |

Floats

118 |
119 |
120 |
121 | Loading... 122 |
123 |
124 |
125 | 126 |

Text align

127 |
128 |
129 |
130 | Loading... 131 |
132 |
133 |
134 | 135 |

Size

136 |

Add .spinner-border-sm and .spinner-grow-sm to make a smaller spinner that can quickly be used within other components.

137 |
138 |
139 | Loading... 140 |
141 |
142 | Loading... 143 |
144 |
145 | 146 |

Or, use custom CSS or inline styles to change the dimensions as needed.

147 |
148 |
149 | Loading... 150 |
151 |
152 | Loading... 153 |
154 |
155 | 156 |

Buttons

157 |

Use spinners within buttons to indicate an action is currently processing or taking place. You may also swap the text out of the spinner element and utilize button text as needed.

158 |
159 | 163 | 167 |
168 | 169 |
170 | 174 | 178 |
179 | 180 |
181 | 182 | ); 183 | } 184 | } -------------------------------------------------------------------------------- /src/pages/bootstrap/Navs.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Navs extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Navs

8 |

Documentation and examples for how to use Bootstrap’s included navigation components.

9 | 10 |

Base nav

11 |

Navigation available in Bootstrap share general markup and styles, from the base .nav class to the active and disabled states. Swap modifier classes to switch between each style.

12 |

The base .nav component is built with flexbox and provide a strong foundation for building all types of navigation components. It includes some style overrides (for working with lists), some link padding for larger hit areas, and basic disabled styling.

13 |
14 |

The base .nav component does not include any .active state. The following examples include the class, mainly to demonstrate that this particular class does not trigger any special styling.

15 |
16 |
17 | 31 |
32 |
<ul class="nav">{"\n"}{"  "}<li class="nav-item">{"\n"}{"    "}<a class="nav-link active" href="#">Active</a>{"\n"}{"  "}</li>{"\n"}{"  "}<li class="nav-item">{"\n"}{"    "}<a class="nav-link" href="#">Link</a>{"\n"}{"  "}</li>{"\n"}{"  "}<li class="nav-item">{"\n"}{"    "}<a class="nav-link" href="#">Link</a>{"\n"}{"  "}</li>{"\n"}{"  "}<li class="nav-item">{"\n"}{"    "}<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>{"\n"}{"  "}</li>{"\n"}</ul>
33 |

Classes are used throughout, so your markup can be super flexible. Use <ul>s like above, <ol> if the order of your items is important, or roll your own with a <nav> element. Because the .nav uses display: flex, the nav links behave the same as nav items would, but without the extra markup.

34 |
35 | 41 |
42 |
<nav class="nav">{"\n"}{"  "}<a class="nav-link active" href="#">Active</a>{"\n"}{"  "}<a class="nav-link" href="#">Link</a>{"\n"}{"  "}<a class="nav-link" href="#">Link</a>{"\n"}{"  "}<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>{"\n"}</nav>
43 |

Available styles

44 |

Change the style of .navs component with modifiers and utilities. Mix and match as needed, or build your own.

45 | 46 |

Tabs

47 |

Takes the basic nav from above and adds the .nav-tabs class to generate a tabbed interface. Use them to create tabbable regions with our tab JavaScript plugin.

48 |
49 | 63 |
64 | 65 |
66 | 67 | ); 68 | } 69 | } -------------------------------------------------------------------------------- /src/pages/bootstrap/Dropdowns.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 3 | import { faChevronDown, faChevronUp, faChevronRight, faChevronLeft } from '@fortawesome/free-solid-svg-icons'; 4 | 5 | export default class Dropdowns extends React.Component { 6 | render() { 7 | return ( 8 |
9 |

10 | Dropdowns 11 |

12 |

13 | Toggle contextual overlays for displaying lists of links and more with the Bootstrap dropdown plugin. 14 |

15 | 16 |

To do

17 |
    18 | 19 |
  • replace buttons with one that looks more like a select.
  • 20 |
  • 21 | Remove the buttons, update docs to indicate that the display of the dropdown is unimportant. It's the 22 | presences of the chevron icon. 23 |
  • 24 |
  • Menu popup itself – should use 'The Shadow' that we also use for buttons, etc.
  • 25 |
26 | 27 |

Notes:

28 |
    29 |
  • As shown, the display of the button itself isn't important. It's the existence of the chevron that matters.
  • 30 |
  • Ultimately we'll use the paragon version: Paragon Dropdown Component
  • 31 |
32 | 33 |
34 |
35 | 46 | 57 |
58 | 59 |
60 | 71 | 82 |
83 | 84 |
85 | 96 | 107 |
108 |
109 | 110 | {/* /example */} 111 |
112 |
113 | 123 | 139 |
140 | 150 | 166 |
167 | 177 | 193 |
194 |
195 | ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/scss/bootstrap-docs-4-2/_component-examples.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable no-duplicate-selectors, selector-no-qualifying-type 2 | 3 | // 4 | // Grid examples 5 | // 6 | 7 | .bd-example-row { 8 | .row { 9 | > .col, 10 | > [class^="col-"] { 11 | padding-top: .75rem; 12 | padding-bottom: .75rem; 13 | background-color: rgba(86, 61, 124, .15); 14 | border: 1px solid rgba(86, 61, 124, .2); 15 | } 16 | } 17 | 18 | .row + .row { 19 | margin-top: 1rem; 20 | } 21 | 22 | .flex-items-top, 23 | .flex-items-middle, 24 | .flex-items-bottom { 25 | min-height: 6rem; 26 | background-color: rgba(255, 0, 0, .1); 27 | } 28 | } 29 | 30 | .bd-example-row-flex-cols .row { 31 | min-height: 10rem; 32 | background-color: rgba(255, 0, 0, .1); 33 | } 34 | 35 | .bd-highlight { 36 | background-color: rgba($bd-purple, .15); 37 | border: 1px solid rgba($bd-purple, .15); 38 | } 39 | 40 | // Grid mixins 41 | .example-container { 42 | width: 800px; 43 | @include make-container(); 44 | } 45 | 46 | .example-row { 47 | @include make-row(); 48 | } 49 | 50 | .example-content-main { 51 | @include make-col-ready(); 52 | 53 | @include media-breakpoint-up(sm) { 54 | @include make-col(6); 55 | } 56 | 57 | @include media-breakpoint-up(lg) { 58 | @include make-col(8); 59 | } 60 | } 61 | 62 | .example-content-secondary { 63 | @include make-col-ready(); 64 | 65 | @include media-breakpoint-up(sm) { 66 | @include make-col(6); 67 | } 68 | 69 | @include media-breakpoint-up(lg) { 70 | @include make-col(4); 71 | } 72 | } 73 | 74 | 75 | // 76 | // Container illustrations 77 | // 78 | 79 | .bd-example-container { 80 | min-width: 16rem; 81 | max-width: 25rem; 82 | margin-right: auto; 83 | margin-left: auto; 84 | } 85 | 86 | .bd-example-container-header { 87 | height: 3rem; 88 | margin-bottom: .5rem; 89 | background-color: lighten($blue, 50%); 90 | @include border-radius; 91 | } 92 | 93 | .bd-example-container-sidebar { 94 | float: right; 95 | width: 4rem; 96 | height: 8rem; 97 | background-color: lighten($blue, 25%); 98 | @include border-radius; 99 | } 100 | 101 | .bd-example-container-body { 102 | height: 8rem; 103 | margin-right: 4.5rem; 104 | background-color: lighten($bd-purple, 25%); 105 | @include border-radius; 106 | } 107 | 108 | .bd-example-container-fluid { 109 | max-width: none; 110 | } 111 | 112 | 113 | // 114 | // Docs examples 115 | // 116 | 117 | .bd-example { 118 | position: relative; 119 | padding: 1rem; 120 | margin: 1rem (-$grid-gutter-width / 2) 0; 121 | border: solid $gray-100; 122 | border-width: .2rem 0 0; 123 | @include clearfix(); 124 | 125 | @include media-breakpoint-up(sm) { 126 | padding: 1.5rem; 127 | margin-right: 0; 128 | margin-left: 0; 129 | border-width: .2rem; 130 | } 131 | 132 | + .highlight, 133 | + .clipboard + .highlight { 134 | margin-top: 0; 135 | } 136 | 137 | + p { 138 | margin-top: 2rem; 139 | } 140 | 141 | .pos-f-t { 142 | position: relative; 143 | margin: -1rem; 144 | 145 | @include media-breakpoint-up(sm) { 146 | margin: -1.5rem; 147 | } 148 | } 149 | 150 | .custom-file-input:lang(es) ~ .custom-file-label::after { 151 | content: "Elegir"; 152 | } 153 | 154 | > .form-control { 155 | + .form-control { 156 | margin-top: .5rem; 157 | } 158 | } 159 | 160 | > .nav + .nav, 161 | > .alert + .alert, 162 | > .navbar + .navbar, 163 | > .progress + .progress, 164 | > .progress + .btn { 165 | margin-top: 1rem; 166 | } 167 | 168 | > .dropdown-menu:first-child { 169 | position: static; 170 | display: block; 171 | } 172 | 173 | > .form-group:last-child { 174 | margin-bottom: 0; 175 | } 176 | 177 | > .close { 178 | float: none; 179 | } 180 | } 181 | 182 | // Typography 183 | .bd-example-type { 184 | .table { 185 | .type-info { 186 | color: #999; 187 | vertical-align: middle; 188 | } 189 | td { 190 | padding: 1rem 0; 191 | border-color: #eee; 192 | } 193 | tr:first-child td { 194 | border-top: 0; 195 | } 196 | } 197 | 198 | h1, 199 | h2, 200 | h3, 201 | h4, 202 | h5, 203 | h6 { 204 | margin-top: 0; 205 | margin-bottom: 0; 206 | } 207 | } 208 | 209 | // Contextual background colors 210 | .bd-example-bg-classes p { 211 | padding: 1rem; 212 | } 213 | 214 | // Images 215 | .bd-example { 216 | > svg + svg, 217 | > img + img { 218 | margin-left: .5rem; 219 | } 220 | } 221 | 222 | // Buttons 223 | .bd-example { 224 | > .btn-group { 225 | margin-top: .25rem; 226 | margin-bottom: .25rem; 227 | } 228 | > .btn-toolbar + .btn-toolbar { 229 | margin-top: .5rem; 230 | } 231 | } 232 | 233 | // Forms 234 | .bd-example-control-sizing select, 235 | .bd-example-control-sizing input[type="text"] + input[type="text"] { 236 | margin-top: .5rem; 237 | } 238 | .bd-example-form .input-group { 239 | margin-bottom: .5rem; 240 | } 241 | .bd-example > textarea.form-control { 242 | resize: vertical; 243 | } 244 | 245 | // List groups 246 | .bd-example > .list-group { 247 | max-width: 400px; 248 | } 249 | .bd-example > [class*="list-group-horizontal"] { 250 | max-width: 100%; 251 | } 252 | 253 | // Navbars 254 | .bd-example { 255 | .fixed-top, 256 | .sticky-top { 257 | position: static; 258 | margin: -1rem -1rem 1rem; 259 | } 260 | .fixed-bottom { 261 | position: static; 262 | margin: 1rem -1rem -1rem; 263 | } 264 | 265 | @include media-breakpoint-up(sm) { 266 | .fixed-top, 267 | .sticky-top { 268 | margin: -1.5rem -1.5rem 1rem; 269 | } 270 | .fixed-bottom { 271 | margin: 1rem -1.5rem -1.5rem; 272 | } 273 | } 274 | } 275 | 276 | // Pagination 277 | .bd-example .pagination { 278 | margin-top: .5rem; 279 | margin-bottom: .5rem; 280 | } 281 | 282 | // Example modals 283 | .modal { 284 | z-index: 1072; 285 | 286 | .tooltip, 287 | .popover { 288 | z-index: 1073; 289 | } 290 | } 291 | 292 | .modal-backdrop { 293 | z-index: 1071; 294 | } 295 | 296 | .bd-example-modal { 297 | background-color: #fafafa; 298 | 299 | .modal { 300 | position: relative; 301 | top: auto; 302 | right: auto; 303 | bottom: auto; 304 | left: auto; 305 | z-index: 1; 306 | display: block; 307 | } 308 | 309 | .modal-dialog { 310 | left: auto; 311 | margin-right: auto; 312 | margin-left: auto; 313 | } 314 | } 315 | 316 | // Example tabbable tabs 317 | .bd-example-tabs .nav-tabs { 318 | margin-bottom: 1rem; 319 | } 320 | 321 | // Popovers 322 | .bd-example-popover-static { 323 | padding-bottom: 1.5rem; 324 | background-color: #f9f9f9; 325 | 326 | .popover { 327 | position: relative; 328 | display: block; 329 | float: left; 330 | width: 260px; 331 | margin: 1.25rem; 332 | } 333 | } 334 | 335 | // Tooltips 336 | .tooltip-demo a { 337 | white-space: nowrap; 338 | } 339 | 340 | .bd-example-tooltip-static .tooltip { 341 | position: relative; 342 | display: inline-block; 343 | margin: 10px 20px; 344 | opacity: 1; 345 | } 346 | 347 | // Scrollspy demo on fixed height div 348 | .scrollspy-example { 349 | position: relative; 350 | height: 200px; 351 | margin-top: .5rem; 352 | overflow: auto; 353 | } 354 | 355 | .scrollspy-example-2 { 356 | position: relative; 357 | height: 350px; 358 | overflow: auto; 359 | } 360 | 361 | .bd-example-border-utils { 362 | [class^="border"] { 363 | display: inline-block; 364 | width: 5rem; 365 | height: 5rem; 366 | margin: .25rem; 367 | background-color: #f5f5f5; 368 | } 369 | } 370 | 371 | .bd-example-border-utils-0 { 372 | [class^="border"] { 373 | border: 1px solid $border-color; 374 | } 375 | } 376 | 377 | // 378 | // Code snippets 379 | // 380 | 381 | .highlight { 382 | padding: 1rem; 383 | margin-top: 1rem; 384 | margin-bottom: 1rem; 385 | background-color: $gray-100; 386 | -ms-overflow-style: -ms-autohiding-scrollbar; 387 | 388 | @include media-breakpoint-up(sm) { 389 | padding: 1.5rem; 390 | } 391 | } 392 | 393 | .bd-content .highlight { 394 | margin-right: (-$grid-gutter-width / 2); 395 | margin-left: (-$grid-gutter-width / 2); 396 | 397 | @include media-breakpoint-up(sm) { 398 | margin-right: 0; 399 | margin-left: 0; 400 | } 401 | } 402 | 403 | .highlight { 404 | pre { 405 | padding: 0; 406 | margin-top: 0; 407 | margin-bottom: 0; 408 | background-color: transparent; 409 | border: 0; 410 | } 411 | pre code { 412 | font-size: inherit; 413 | color: $gray-900; // Effectively the base text color 414 | } 415 | } 416 | -------------------------------------------------------------------------------- /src/pages/Basics.Colors.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import chroma from 'chroma-js'; 3 | 4 | const colors = { 5 | 'gray-900': { 6 | value: '#111', 7 | name: 'Gray 900', 8 | utilityClassName: 'gray-900', 9 | forBG: false, 10 | forText: true, 11 | }, 12 | 'gray-700': { 13 | value: '#414141', 14 | name: 'Gray 700', 15 | utilityClassName: 'gray-700', 16 | forBG: false, 17 | forText: true, 18 | }, 19 | 'gray-600': { 20 | value: 'rgba(65,65,65,.7)', 21 | name: 'Gray 600', 22 | utilityClassName: 'gray-600', 23 | forBG: false, 24 | forText: true, 25 | }, 26 | 'primary': { 27 | value: '#23419F', 28 | name: 'UI Blue (Primary)', 29 | utilityClassName: 'primary', 30 | forBG: true, 31 | forText: true, 32 | }, 33 | 'secondary': { 34 | value: '#45096B', 35 | name: 'UI Indigo (Secondary)', 36 | utilityClassName: 'secondary', 37 | forBG: true, 38 | forText: true, 39 | }, 40 | 'success': { 41 | value: '#008100', 42 | name: 'UI Success', 43 | utilityClassName: 'success', 44 | forBG: true, 45 | forText: true, 46 | }, 47 | 'info': { 48 | value: '#065784', 49 | name: 'Text Info', 50 | utilityClassName: 'info', 51 | forBG: false, 52 | forText: true, 53 | }, 54 | 'danger': { 55 | value: '#A2221D', 56 | name: 'UI Danger', 57 | utilityClassName: 'danger', 58 | forBG: true, 59 | forText: true, 60 | }, 61 | 'fill-success': { 62 | value: '#DFF0D8', 63 | name: 'Success Fill', 64 | utilityClassName: 'fill-success', 65 | forBG: true, 66 | forText: false, 67 | }, 68 | 'fill-info': { 69 | value: '#D8EDF8', 70 | name: 'Info Fill', 71 | utilityClassName: 'fill-info', 72 | forBG: true, 73 | forText: false, 74 | }, 75 | 'fill-danger': { 76 | value: '#F2DEDE', 77 | name: 'Danger Fill', 78 | utilityClassName: 'fill-danger', 79 | forBG: true, 80 | forText: false, 81 | }, 82 | 'fill-warning': { 83 | value: '#FCF8E2', 84 | name: 'Warning Fill', 85 | utilityClassName: 'fill-warning', 86 | forBG: true, 87 | forText: false, 88 | }, 89 | 'program-masters': { 90 | value: '#414141', 91 | name: 'Masters', 92 | utilityClassName: 'program-masters', 93 | forBG: true, 94 | forText: false, 95 | }, 96 | 'program-micro-masters': { 97 | value: '#065784', 98 | name: 'MicroMasters', 99 | utilityClassName: 'program-micro-masters', 100 | forBG: true, 101 | forText: false, 102 | }, 103 | 'program-prof-cert': { 104 | value: '#9A1F60', 105 | name: 'Professional Certificate', 106 | utilityClassName: 'program-prof-cert', 107 | forBG: true, 108 | forText: false, 109 | }, 110 | 'white': { 111 | value: '#fff', 112 | name: 'White', 113 | utilityClassName: 'white', 114 | forBG: true, 115 | forText: true, 116 | }, 117 | 'pale-gray': { 118 | value: '#FCFCFC', 119 | name: 'Pale Gray', 120 | utilityClassName: 'pale-gray', 121 | forBG: true, 122 | forText: false, 123 | }, 124 | 'pale-blue': { 125 | value: '#F5F8FF', 126 | name: 'Pale. Blue', 127 | utilityClassName: 'pale-blue', 128 | forBG: true, 129 | forText: false, 130 | }, 131 | 'pale-yellow': { 132 | value: '#FFFDF3', 133 | name: 'Pale Yellow', 134 | utilityClassName: 'pale-yellow', 135 | forBG: true, 136 | forText: false, 137 | }, 138 | 'yellow': { 139 | value: '#FFBF18', 140 | name: 'Accent Yellow', 141 | utilityClassName: 'yellow', 142 | forBG: true, 143 | forText: false, 144 | }, 145 | }; 146 | 147 | const textAndInteractiveColors = [ 148 | 'gray-900', 149 | 'gray-700', 150 | 'gray-600', 151 | 'primary', 152 | 'secondary', 153 | ]; 154 | 155 | const programColors = [ 156 | 'program-masters', 157 | 'program-micro-masters', 158 | 'program-prof-cert', 159 | ]; 160 | 161 | const accentColors = [ 162 | 'yellow', 163 | ]; 164 | 165 | const systemColorsBG = [ 166 | 'fill-success', 167 | 'fill-info', 168 | 'fill-danger', 169 | 'fill-warning', 170 | ]; 171 | 172 | const systemColorsUI = [ 173 | 'success', 174 | 'info', 175 | 'danger', 176 | ]; 177 | 178 | const bgColors = [ 179 | 'white', 180 | 'pale-gray', 181 | 'pale-blue', 182 | 'pale-yellow', 183 | ]; 184 | 185 | 186 | function Tile({children}) { 187 | return ( 188 |
189 | {children} 190 |
191 | ); 192 | } 193 | 194 | function Swatch({color, textColor, className, children, style}) { 195 | return
{children || color}
205 | } 206 | 207 | function TextSwatch({color, bgColor, className, children, style}) { 208 | return
{children || color}
219 | } 220 | 221 | export default function Colors() { 222 | const renderColor = (colorKey) => { 223 | const {name, value, forBG, forText } = colors[colorKey]; 224 | const contrastColor = chroma(value).luminance() > .5 ? '#111' : '#fff'; 225 | return ( 226 |
227 | 228 | 229 | {forBG ? : null} 230 | {forText ? {value} Aa : null} 231 | 232 |
233 | ); 234 | } 235 | 236 | return ( 237 |
238 |
Text & Interactive
239 |
{textAndInteractiveColors.map(renderColor)}
240 | 241 |
Program Specific
242 |
{programColors.map(renderColor)}
243 | 244 |
Accent
245 |
{accentColors.map(renderColor)}
246 | 247 |
System Colors
248 |
{systemColorsBG.map(renderColor)}
249 |
{systemColorsUI.map(renderColor)}
250 | 251 |
Backgrounds
252 |
{bgColors.map(renderColor)}
253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | {Object.keys(colors).map(colorKey => { 264 | const { 265 | name, 266 | value, 267 | utilityClassName, 268 | forText, 269 | forBG, 270 | } = colors[colorKey]; 271 | 272 | const contrastColor = chroma(value).luminance() > .5 ? '#000' : '#fff'; 273 | 274 | return ( 275 | 276 | 280 | 290 | 300 | 305 | 306 | ); 307 | })} 308 | 309 |
Name/ValueUtility Classes
277 | {name}
278 | {value} 279 |
281 | {forText ? ( 282 | 286 | .text-{utilityClassName} 287 | 288 | ) : null} 289 | 291 | {forBG ? ( 292 | 296 | .bg-{utilityClassName} 297 | 298 | ) : null} 299 | 301 | 302 | .border-{utilityClassName} 303 | 304 |
310 |
311 | ); 312 | } 313 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { BrowserRouter, Route, NavLink, Routes } from 'react-router-dom'; 3 | import { HashLink } from 'react-router-hash-link'; 4 | 5 | import Basics from './pages/Basics'; 6 | import Navigation from './pages/Navigation'; 7 | import Forms from './pages/Forms'; 8 | import Miscellaneous from './pages/Miscellaneous'; 9 | import Overview from './pages/Overview'; 10 | import Examples from './pages/Examples'; 11 | import GettingStarted from './pages/GettingStarted'; 12 | 13 | import Alerts from './pages/bootstrap/Alerts'; 14 | import Badge from './pages/bootstrap/Badge'; 15 | import Cards from './pages/bootstrap/Cards'; 16 | import Collapse from './pages/bootstrap/Collapse'; 17 | import Dropdowns from './pages/bootstrap/Dropdowns'; 18 | import Grid from './pages/bootstrap/Grid'; 19 | import Modal from './pages/bootstrap/Modal'; 20 | import Pagination from './pages/bootstrap/Pagination'; 21 | import Popovers from './pages/bootstrap/Popovers'; 22 | import Progress from './pages/bootstrap/Progress'; 23 | import Tables from './pages/bootstrap/Tables'; 24 | 25 | class App extends Component { 26 | render() { 27 | return ( 28 | 29 |
30 |
31 |
32 |
33 |
34 | edX Bootstrap 35 |
36 |
    37 |
  • 38 | Overview 39 |
  • 40 |
  • 41 | Getting Started 42 |
  • 43 |
44 | 45 |
46 | Basics 47 |
48 |
    49 |
  • 50 | Colors 51 |
  • 52 |
  • 53 | Typography 54 |
  • 55 |
  • 56 | Buttons 57 |
  • 58 |
  • 59 | Links 60 |
  • 61 |
  • 62 | Icons 63 |
  • 64 |
65 |
66 | Navigation 67 |
68 |
    69 |
  • 70 | Breadcrumbs 71 |
  • 72 |
  • 73 | Navs 74 |
  • 75 |
  • 76 | Tabs 77 |
  • 78 |
  • 79 | Search 80 |
  • 81 |
82 |
Content
83 |
    84 |
  • 85 | Forms 86 |
  • 87 |
  • 88 | Cards 89 |
  • 90 |
  • 91 | Alerts 92 |
  • 93 |
  • 94 | Badge 95 |
  • 96 |
  • 97 | Dropdowns 98 |
  • 99 |
  • 100 | Modal 101 |
  • 102 |
  • 103 | Pagination 104 |
  • 105 |
  • 106 | Tables 107 |
  • 108 |
109 |
110 | Miscellaneous 111 |
112 |
    113 |
  • 114 | Spinners / Loaders 115 |
  • 116 |
117 |
118 | Examples 119 |
120 |
    121 |
  • 122 | Example 1 123 |
  • 124 |
125 | 126 |
In Progress Components
127 |
    128 |
  • 129 | Grid 130 |
  • 131 |
  • 132 | Popovers 133 |
  • 134 |
  • 135 | Collapse 136 |
  • 137 |
  • 138 | Progress 139 |
  • 140 |
141 | 142 |
External Links
143 | 156 |
157 | 158 | } /> 159 | } /> 160 | } /> 161 | 162 | {/* Basics */} 163 | } /> 164 | } /> 165 | } /> 166 | } /> 167 | } /> 168 | 169 | {/* Navigation */} 170 | } /> 171 | } /> 172 | } /> 173 | } /> 174 | } /> 175 | 176 | {/* Content */} 177 | } /> 178 | } /> 179 | } /> 180 | } /> 181 | } /> 182 | } /> 183 | } /> 184 | } /> 185 | 186 | {/* Miscellaneous */} 187 | } /> 188 | } /> 189 | 190 | {/* Examples */} 191 | } /> 192 | 193 | {/* Bootstrap documentation pages */} 194 | } /> 195 | } /> 196 | } /> 197 | } /> 198 | 199 |
200 |
201 |
202 |
203 | ); 204 | } 205 | } 206 | 207 | export default App; 208 | -------------------------------------------------------------------------------- /src/pages/bootstrap/Collapse.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Collapse extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

8 | Collapse 9 |

10 | 11 |

To do

12 |
    13 |
  • Update with our own examples
  • 14 |
15 | 16 |

17 | How it works 18 |

19 |

20 | Example 21 |

22 |
23 |

24 | 34 | 44 |

45 |
46 |
47 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil anim 48 | keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. 49 |
50 |
51 |
52 |

53 | Multiple targets 54 |

55 |
56 |

57 | 67 | 77 | 87 |

88 |
89 |
90 |
91 |
92 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil 93 | anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. 94 |
95 |
96 |
97 |
98 |
99 |
100 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil 101 | anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. 102 |
103 |
104 |
105 |
106 |
107 |

108 | Accordion example 109 |

110 |
111 |
112 |
113 |
114 |

115 | 125 |

126 |
127 |
133 |
134 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf 135 | moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. 136 | Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda 137 | shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea 138 | proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim 139 | aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. 140 |
141 |
142 |
143 |
144 |
145 |

146 | 156 |

157 |
158 |
159 |
160 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf 161 | moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. 162 | Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda 163 | shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea 164 | proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim 165 | aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. 166 |
167 |
168 |
169 |
170 |
171 |

172 | 182 |

183 |
184 |
190 |
191 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf 192 | moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. 193 | Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda 194 | shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea 195 | proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim 196 | aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. 197 |
198 |
199 |
200 |
201 |
202 |
203 | ); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/pages/Forms.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import DocSection from '../DocSection'; 4 | 5 | const defaultState = { 6 | email: '', 7 | password: '', 8 | mittens: false, 9 | boots: false, 10 | notMittensOrBoots: false, 11 | floofiness: null, 12 | catCount: 3, 13 | catName: '', 14 | birthday: '', 15 | nappingSpot: '', 16 | catPicture: '', 17 | }; 18 | 19 | export default class Forms extends React.Component { 20 | constructor(props) { 21 | super(props); 22 | 23 | this.state = { 24 | email: '', 25 | password: '', 26 | mittens: false, 27 | boots: false, 28 | notMittensOrBoots: false, 29 | floofiness: null, 30 | catCount: 3, 31 | catName: '', 32 | birthday: '', 33 | nappingSpot: '', 34 | catPicture: '', 35 | }; 36 | 37 | this.handleSubmit = this.handleSubmit.bind(this); 38 | this.handleChange = this.handleChange.bind(this); 39 | this.handleCancel = this.handleCancel.bind(this); 40 | } 41 | 42 | handleChange(event) { 43 | const { name } = event.target; 44 | const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value; 45 | 46 | this.setState({ 47 | [name]: value, 48 | }); 49 | } 50 | 51 | handleSubmit(e) { 52 | this.validate(); 53 | 54 | e.preventDefault(); 55 | return false; 56 | } 57 | 58 | handleCancel(e) { 59 | this.setState(defaultState); 60 | e.preventDefault(); 61 | return false; 62 | } 63 | 64 | validate() {} 65 | 66 | render() { 67 | return ( 68 |
69 | 70 |

Notes

71 |
    72 |
  • 73 | Form groups should be stacked. Label first, then input, then help text below that. 74 |
  • 75 |
  • 76 | If there is an error state for the input, it should go below the input, above the help 77 | text. 78 |
  • 79 |
  • 80 | Error states should be included at the top of the form with anchor links down to the 81 | actual errored fields. 82 |
  • 83 |
84 |
85 |
86 |
87 | 99 |
100 |
101 | 113 |
Looks good!
114 | 115 | Your password must be 8-32 characters long, contain letters and numbers, and must 116 | not contain spaces, special characters, or emoji. 117 | 118 |
119 |
120 | 121 |
122 | 133 |
134 |
135 | 146 |
147 |
148 | 160 |
161 |
162 | 163 |
164 | 165 |
166 | 178 |
179 |
180 | 192 |
193 |
194 | 207 |
208 |
209 | 210 |
211 | 227 |
228 |
229 | 246 |
247 |
248 | 258 |
259 |
260 |