├── .nvmrc ├── www ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.ico │ │ └── docusaurus.png ├── src │ ├── components │ │ ├── PropsTable │ │ │ ├── index.ts │ │ │ └── defaultPropDescriptions.ts │ │ ├── HomepageFeatures │ │ │ └── styles.module.css │ │ ├── AriaAbbr.tsx │ │ ├── DocLink.tsx │ │ ├── CssCodeBlock.tsx │ │ ├── CarbonAds.tsx │ │ └── ExampleCarouselImage.tsx │ ├── css │ │ └── algolia.scss │ ├── hooks │ │ └── useBootstrapMetadata.ts │ ├── theme │ │ ├── Playground │ │ │ └── EditorInfoMessage.tsx │ │ ├── ReactLiveScope.ts │ │ ├── MDXComponents.ts │ │ ├── CodeBlock.tsx │ │ ├── ColorModeToggle │ │ │ └── styles.module.css │ │ ├── Admonition │ │ │ └── styles.module.css │ │ └── MDXContent.tsx │ └── pages │ │ └── index.module.css ├── docs │ ├── forms │ │ ├── _category_.json │ │ ├── select.mdx │ │ └── range.mdx │ ├── layout │ │ └── _category_.json │ ├── components │ │ ├── _category_.json │ │ ├── figures.mdx │ │ ├── breadcrumb.mdx │ │ ├── images.mdx │ │ └── pagination.mdx │ ├── utilities │ │ ├── _category_.json │ │ └── restart-ui.mdx │ ├── getting-started │ │ ├── _category_.json │ │ ├── server-side-rendering.mdx │ │ ├── color-modes.mdx │ │ ├── rtl.mdx │ │ └── support.mdx │ └── examples │ │ ├── CloseButton │ │ ├── Basic.js │ │ ├── Disabled.js │ │ ├── Labelled.js │ │ └── Variants.js │ │ ├── Spinner │ │ ├── Grow.js │ │ ├── Border.js │ │ ├── Basic.js │ │ ├── Sizes.js │ │ └── Buttons.js │ │ ├── CustomBreakpoints.js │ │ ├── Image │ │ ├── Fluid.js │ │ └── Shape.js │ │ ├── ProgressBar │ │ ├── Basic.js │ │ ├── Animated.js │ │ ├── WithLabel.js │ │ ├── ScreenreaderLabel.js │ │ ├── Stacked.js │ │ ├── Contextual.js │ │ └── Striped.js │ │ ├── AsProp.js │ │ ├── Card │ │ ├── BodyShorthand.js │ │ ├── BodyOnly.js │ │ ├── ListGroups.js │ │ ├── WithHeader.js │ │ ├── ListGroupWithHeader.js │ │ ├── WithHeaderStyled.js │ │ ├── Basic.js │ │ ├── ImgOverlay.js │ │ ├── Text.js │ │ ├── HeaderAndFooter.js │ │ ├── WithHeaderAndQuote.js │ │ ├── ImageAndText.js │ │ ├── Grid.js │ │ ├── BgColor.js │ │ └── KitchenSink.js │ │ ├── Form │ │ ├── Range.js │ │ ├── InputReadOnly.js │ │ ├── NoLabels.js │ │ ├── SelectBasic.js │ │ ├── InputSizes.js │ │ ├── ColorPicker.js │ │ ├── GridBasic.js │ │ ├── Switch.js │ │ ├── SelectSizes.js │ │ ├── ValidationInputGroup.js │ │ ├── GridColSizes.js │ │ ├── FormControlDisabled.js │ │ ├── FormGroup.js │ │ ├── FormFloatingSelect.js │ │ ├── FormText.js │ │ ├── TextControls.js │ │ ├── CheckApi.js │ │ ├── FormFloatingBasic.js │ │ ├── Check.js │ │ ├── FormDisabledInputs.js │ │ ├── FormFloatingCustom.js │ │ ├── FormFloatingTextarea.js │ │ ├── Plaintext.js │ │ ├── CheckInline.js │ │ ├── CheckReverse.js │ │ ├── Basic.js │ │ └── FormLabelSizing.js │ │ ├── Placeholder │ │ ├── Width.js │ │ ├── Example.js │ │ ├── Size.js │ │ ├── Animation.js │ │ └── Color.js │ │ ├── Ratio │ │ ├── Custom.js │ │ ├── Example.js │ │ └── Default.js │ │ ├── Stack │ │ ├── Vertical.js │ │ ├── Horizontal.js │ │ ├── Buttons.js │ │ ├── HorizontalMarginStart.js │ │ ├── HorizontalVerticalRules.js │ │ └── Form.js │ │ ├── Grid │ │ ├── Container.js │ │ ├── ContainerFluid.js │ │ ├── ContainerFluidBreakpoint.js │ │ ├── Ordering.js │ │ ├── RowColLayoutColWidthBreakpoint.js │ │ ├── AutoLayout.js │ │ ├── OrderingFirstLast.js │ │ ├── ResponsiveAuto.js │ │ ├── AutoLayoutSizing.js │ │ ├── RowColLayout.js │ │ ├── Offsetting.js │ │ └── AutoLayoutVariable.js │ │ ├── AsPropComponent.js │ │ ├── Badge │ │ ├── Button.js │ │ ├── Variations.js │ │ ├── Basic.js │ │ └── Pill.js │ │ ├── Button │ │ ├── Active.js │ │ ├── Block.js │ │ ├── TagTypes.js │ │ ├── Disabled.js │ │ ├── Types.js │ │ ├── OutlineTypes.js │ │ ├── Sizes.js │ │ ├── Loading.js │ │ └── ToggleButtonGroupControlled.js │ │ ├── Navbar │ │ ├── ContainerInside.js │ │ ├── ContainerOutside.js │ │ └── TextLink.js │ │ ├── ListGroup │ │ ├── Numbered.js │ │ ├── Horizontal.js │ │ ├── Flush.js │ │ ├── Disabled.js │ │ ├── Header.js │ │ ├── Default.js │ │ ├── Buttons.js │ │ ├── Active.js │ │ ├── Linked.js │ │ ├── HorizontalResponsive.js │ │ ├── Style.js │ │ ├── Tabs.js │ │ └── StyleActions.js │ │ ├── Dropdown │ │ ├── MenuHeaders.js │ │ ├── MenuDividers.js │ │ ├── BasicButton.js │ │ ├── Basic.js │ │ ├── DropdownItemTags.js │ │ ├── MenuAlignEnd.js │ │ ├── SplitBasic.js │ │ └── SplitVariants.js │ │ ├── ButtonGroup │ │ ├── Basic.js │ │ ├── Nested.js │ │ ├── Sizes.js │ │ └── ToolbarBasic.js │ │ ├── Figure.js │ │ ├── InputGroup │ │ ├── MultipleInputs.js │ │ ├── Checkboxes.js │ │ └── MultipleAddons.js │ │ ├── Breadcrumb.js │ │ ├── Nav │ │ ├── Stacked.js │ │ ├── DropdownImpl.js │ │ ├── List.js │ │ ├── Tabs.js │ │ ├── Pills.js │ │ ├── Underline.js │ │ ├── Fill.js │ │ ├── Justified.js │ │ └── Basic.js │ │ ├── Toast │ │ ├── Basic.js │ │ └── Stacking.js │ │ ├── Alert │ │ ├── Basic.js │ │ ├── Link.js │ │ ├── AdditionalContent.js │ │ ├── Dismissible.js │ │ └── DismissibleControlled.js │ │ ├── Theming │ │ ├── Variants.js │ │ └── Prefixes.js │ │ ├── Overlays │ │ ├── Disabled.js │ │ ├── Trigger.js │ │ ├── PopoverBasic.js │ │ ├── TooltipOverlay.js │ │ ├── TooltipPositioned.js │ │ ├── TriggerRenderProp.js │ │ └── PopoverPositioned.js │ │ ├── Pagination │ │ ├── Basic.js │ │ └── Advanced.js │ │ ├── Tabs │ │ ├── Uncontrolled.js │ │ ├── NoAnimation.js │ │ ├── Fill.js │ │ ├── Controlled.js │ │ ├── Justified.js │ │ └── LeftTabs.js │ │ ├── Modal │ │ └── Static.js │ │ ├── Fade.js │ │ ├── Collapse.js │ │ ├── Table │ │ ├── Basic.js │ │ ├── StripedRow.js │ │ ├── Dark.js │ │ ├── Small.js │ │ ├── StripedColumns.js │ │ └── Responsive.js │ │ └── Offcanvas │ │ ├── StaticBackdrop.js │ │ └── Basic.js ├── babel.config.js ├── .gitignore ├── README.md ├── tsconfig.json ├── plugins │ ├── react-resolver-plugin.js │ └── webpack-plugin.js └── sidebars.js ├── codecov.yml ├── .gitattributes ├── .husky └── pre-commit ├── manual_releases.md ├── renovate.json ├── vitest.setup.ts ├── .eslintignore ├── src ├── Anchor.tsx ├── InputGroupContext.tsx ├── SSRProvider.ts ├── FormContext.tsx ├── CardHeaderContext.tsx ├── triggerBrowserReflow.tsx ├── getInitialPopperStyles.ts ├── AccordionItemContext.ts ├── ModalContext.tsx ├── divWithClassName.tsx ├── ToastContext.tsx ├── safeFindDOMNode.ts ├── NavbarContext.tsx ├── getTabTransitionComponent.ts ├── NavContext.tsx ├── DropdownContext.ts ├── ToastFade.tsx ├── FigureImage.tsx ├── Switch.tsx ├── AccordionContext.ts ├── transitionEndListener.ts ├── createChainedFunction.tsx ├── NavItem.tsx ├── CardBody.tsx ├── CardText.tsx ├── CardLink.tsx ├── CardGroup.tsx ├── ModalBody.tsx ├── ToastBody.tsx ├── CardFooter.tsx ├── TabContent.tsx ├── NavbarText.tsx ├── ModalFooter.tsx ├── PopoverBody.tsx ├── FormFloating.tsx ├── OffcanvasBody.tsx ├── PopoverHeader.tsx ├── CardImgOverlay.tsx ├── InputGroupText.tsx ├── FigureCaption.tsx ├── useWrappedRefWithWarning.tsx ├── AlertLink.tsx ├── CarouselCaption.tsx ├── DropdownItemText.tsx ├── NavbarOffcanvas.tsx ├── usePlaceholder.ts ├── DropdownHeader.tsx ├── CardTitle.tsx ├── DropdownDivider.tsx ├── ModalTitle.tsx ├── CardSubtitle.tsx ├── Figure.tsx └── OffcanvasTitle.tsx ├── tsconfig.json ├── test ├── tsconfig.json ├── .eslintrc ├── TabContentSpec.tsx ├── NavbarToggleSpec.tsx ├── ToastBodySpec.tsx ├── helpers.ts ├── TooltipSpec.tsx ├── getInitialPopperStylesSpec.ts ├── helpersSpec.ts ├── PlaceholderButtonSpec.tsx ├── ButtonToolbarSpec.tsx ├── NavbarBrandSpec.tsx ├── StackSpec.tsx ├── PlaceholderSpec.tsx └── ToastHeaderSpec.tsx ├── .travis.yml ├── .editorconfig ├── vitest.config.ts └── .babelrc.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /www/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: off 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | yarn lint-staged 2 | -------------------------------------------------------------------------------- /manual_releases.md: -------------------------------------------------------------------------------- 1 | number of manually triggered releases: 1 2 | -------------------------------------------------------------------------------- /www/src/components/PropsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './PropsTable'; 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>4Catalyzer/renovate-config:library"] 3 | } 4 | -------------------------------------------------------------------------------- /www/docs/forms/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Forms", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /www/docs/layout/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Layout", 3 | "position": 2 4 | } 5 | -------------------------------------------------------------------------------- /www/docs/components/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Components", 3 | "position": 4 4 | } 5 | -------------------------------------------------------------------------------- /www/docs/utilities/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Utilities", 3 | "position": 5 4 | } 5 | -------------------------------------------------------------------------------- /www/docs/getting-started/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Getting started", 3 | "position": 1 4 | } 5 | -------------------------------------------------------------------------------- /www/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/react-bootstrap/master/www/static/img/favicon.ico -------------------------------------------------------------------------------- /www/static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/react-bootstrap/master/www/static/img/docusaurus.png -------------------------------------------------------------------------------- /www/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import { cleanup } from '@testing-library/react'; 2 | import { afterEach } from 'vitest'; 3 | 4 | afterEach(cleanup); 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | node_modules/** 3 | coverage/ 4 | **/node_modules/** 5 | www/.cache 6 | www/public 7 | www/plugins 8 | **/*.d.ts 9 | -------------------------------------------------------------------------------- /src/Anchor.tsx: -------------------------------------------------------------------------------- 1 | import Anchor, { AnchorProps } from '@restart/ui/Anchor'; 2 | 3 | export type { AnchorProps }; 4 | 5 | export default Anchor; 6 | -------------------------------------------------------------------------------- /www/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /www/src/components/AriaAbbr.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default function AriaAbbr() { 4 | return ARIA; 5 | } 6 | -------------------------------------------------------------------------------- /www/src/css/algolia.scss: -------------------------------------------------------------------------------- 1 | // Removes a tiny vertical scrollbar in the list item. 2 | .DocSearch-Hit-content-wrapper { 3 | overflow: hidden; 4 | } 5 | 6 | .DocSearch-Button { 7 | flex-grow: 1; 8 | } -------------------------------------------------------------------------------- /www/docs/examples/CloseButton/Basic.js: -------------------------------------------------------------------------------- 1 | import CloseButton from 'react-bootstrap/CloseButton'; 2 | 3 | function BasicExample() { 4 | return ; 5 | } 6 | 7 | export default BasicExample; 8 | -------------------------------------------------------------------------------- /www/docs/examples/Spinner/Grow.js: -------------------------------------------------------------------------------- 1 | import Spinner from 'react-bootstrap/Spinner'; 2 | 3 | function GrowExample() { 4 | return ; 5 | } 6 | 7 | export default GrowExample; 8 | -------------------------------------------------------------------------------- /src/InputGroupContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const context = React.createContext(null); 4 | context.displayName = 'InputGroupContext'; 5 | 6 | export default context; 7 | -------------------------------------------------------------------------------- /src/SSRProvider.ts: -------------------------------------------------------------------------------- 1 | import { SSRProvider } from '@restart/ui/ssr'; 2 | import type { SSRProviderProps } from '@restart/ui/ssr'; 3 | 4 | export type { SSRProviderProps }; 5 | 6 | export default SSRProvider; 7 | -------------------------------------------------------------------------------- /www/docs/examples/CustomBreakpoints.js: -------------------------------------------------------------------------------- 1 | 5 | Your app... 6 | ; 7 | -------------------------------------------------------------------------------- /www/docs/examples/Image/Fluid.js: -------------------------------------------------------------------------------- 1 | import Image from 'react-bootstrap/Image'; 2 | 3 | function FluidExample() { 4 | return ; 5 | } 6 | 7 | export default FluidExample; 8 | -------------------------------------------------------------------------------- /www/docs/examples/Spinner/Border.js: -------------------------------------------------------------------------------- 1 | import Spinner from 'react-bootstrap/Spinner'; 2 | 3 | function BorderExample() { 4 | return ; 5 | } 6 | 7 | export default BorderExample; 8 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/Basic.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function BasicExample() { 4 | return ; 5 | } 6 | 7 | export default BasicExample; 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@4c/tsconfig/web.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib", 6 | "noImplicitAny": false 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /www/docs/examples/CloseButton/Disabled.js: -------------------------------------------------------------------------------- 1 | import CloseButton from 'react-bootstrap/CloseButton'; 2 | 3 | function DisabledExample() { 4 | return ; 5 | } 6 | 7 | export default DisabledExample; 8 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "..", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "lib": ["DOM", "ESNext"], 6 | "rootDir": ".." 7 | }, 8 | "include": ["../src", ".", "../tests"] 9 | } 10 | -------------------------------------------------------------------------------- /www/docs/examples/CloseButton/Labelled.js: -------------------------------------------------------------------------------- 1 | import CloseButton from 'react-bootstrap/CloseButton'; 2 | 3 | function LabelledExample() { 4 | return ; 5 | } 6 | 7 | export default LabelledExample; 8 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/Animated.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function AnimatedExample() { 4 | return ; 5 | } 6 | 7 | export default AnimatedExample; 8 | -------------------------------------------------------------------------------- /www/docs/examples/AsProp.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | Button as link 4 | 5 | 6 | Button as link 7 | 8 | ; 9 | -------------------------------------------------------------------------------- /src/FormContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | // TODO 4 | interface FormContextType { 5 | controlId?: any; 6 | } 7 | 8 | const FormContext = React.createContext({}); 9 | 10 | export default FormContext; 11 | -------------------------------------------------------------------------------- /www/docs/examples/Card/BodyShorthand.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function BodyShorthandExample() { 4 | return This is some text within a card body.; 5 | } 6 | 7 | export default BodyShorthandExample; 8 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-script-url": 0, 4 | "no-unused-expressions": 0, 5 | "padded-blocks": 0, 6 | "react/no-multi-comp": 0, 7 | "react/prop-types": 0, 8 | "max-classes-per-file": "off", 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/WithLabel.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function WithLabelExample() { 4 | const now = 60; 5 | return ; 6 | } 7 | 8 | export default WithLabelExample; 9 | -------------------------------------------------------------------------------- /www/docs/examples/Form/Range.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function RangeExample() { 4 | return ( 5 | <> 6 | Range 7 | 8 | > 9 | ); 10 | } 11 | 12 | export default RangeExample; 13 | -------------------------------------------------------------------------------- /www/docs/examples/Form/InputReadOnly.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function InputReadOnlyExample() { 4 | return ( 5 | 6 | ); 7 | } 8 | 9 | export default InputReadOnlyExample; 10 | -------------------------------------------------------------------------------- /www/docs/examples/Card/BodyOnly.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function BodyOnlyExample() { 4 | return ( 5 | 6 | This is some text within a card body. 7 | 8 | ); 9 | } 10 | 11 | export default BodyOnlyExample; 12 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/ScreenreaderLabel.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function ScreenreaderLabelExample() { 4 | const now = 60; 5 | return ; 6 | } 7 | 8 | export default ScreenreaderLabelExample; 9 | -------------------------------------------------------------------------------- /src/CardHeaderContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | interface CardHeaderContextValue { 4 | cardHeaderBsPrefix: string; 5 | } 6 | 7 | const context = React.createContext(null); 8 | context.displayName = 'CardHeaderContext'; 9 | 10 | export default context; 11 | -------------------------------------------------------------------------------- /src/triggerBrowserReflow.tsx: -------------------------------------------------------------------------------- 1 | // reading a dimension prop will cause the browser to recalculate, 2 | // which will let our animations work 3 | export default function triggerBrowserReflow(node: HTMLElement): void { 4 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions 5 | node.offsetHeight; 6 | } 7 | -------------------------------------------------------------------------------- /www/docs/examples/Form/NoLabels.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function NoLabelExample() { 4 | return ( 5 | <> 6 | 7 | 8 | > 9 | ); 10 | } 11 | 12 | export default NoLabelExample; 13 | -------------------------------------------------------------------------------- /src/getInitialPopperStyles.ts: -------------------------------------------------------------------------------- 1 | export default function getInitialPopperStyles( 2 | position: React.CSSProperties['position'] = 'absolute', 3 | ): Partial { 4 | return { 5 | position, 6 | top: '0', 7 | left: '0', 8 | opacity: '0', 9 | pointerEvents: 'none', 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /www/docs/examples/Spinner/Basic.js: -------------------------------------------------------------------------------- 1 | import Spinner from 'react-bootstrap/Spinner'; 2 | 3 | function BasicExample() { 4 | return ( 5 | 6 | Loading... 7 | 8 | ); 9 | } 10 | 11 | export default BasicExample; 12 | -------------------------------------------------------------------------------- /src/AccordionItemContext.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface AccordionItemContextValue { 4 | eventKey: string; 5 | } 6 | 7 | const context = React.createContext({ 8 | eventKey: '', 9 | }); 10 | context.displayName = 'AccordionItemContext'; 11 | 12 | export default context; 13 | -------------------------------------------------------------------------------- /src/ModalContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | interface ModalContextType { 4 | onHide: () => void; 5 | } 6 | 7 | const ModalContext = React.createContext({ 8 | // eslint-disable-next-line @typescript-eslint/no-empty-function 9 | onHide() {}, 10 | }); 11 | 12 | export default ModalContext; 13 | -------------------------------------------------------------------------------- /www/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /www/docs/examples/Placeholder/Width.js: -------------------------------------------------------------------------------- 1 | import Placeholder from 'react-bootstrap/Placeholder'; 2 | 3 | function WidthExample() { 4 | return ( 5 | <> 6 | 7 | 8 | > 9 | ); 10 | } 11 | 12 | export default WidthExample; 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | env: 5 | global: 6 | - BROWSER=ChromeHeadless 7 | addons: 8 | chrome: stable 9 | 10 | cache: 11 | yarn: true 12 | npm: true 13 | directories: 14 | - www/node_modules 15 | 16 | install: 17 | - yarn bootstrap 18 | 19 | branches: 20 | only: 21 | - master 22 | -------------------------------------------------------------------------------- /www/docs/examples/CloseButton/Variants.js: -------------------------------------------------------------------------------- 1 | import CloseButton from 'react-bootstrap/CloseButton'; 2 | 3 | function VariantsExample() { 4 | return ( 5 | 6 | 7 | 8 | 9 | ); 10 | } 11 | 12 | export default VariantsExample; 13 | -------------------------------------------------------------------------------- /src/divWithClassName.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | export default (className: string) => 5 | React.forwardRef>((p, ref) => ( 6 | 11 | )); 12 | -------------------------------------------------------------------------------- /www/docs/examples/Placeholder/Example.js: -------------------------------------------------------------------------------- 1 | import Placeholder from 'react-bootstrap/Placeholder'; 2 | 3 | function BasicExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | 11 | > 12 | ); 13 | } 14 | 15 | export default BasicExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Ratio/Custom.js: -------------------------------------------------------------------------------- 1 | import Ratio from 'react-bootstrap/Ratio'; 2 | 3 | function CustomExample() { 4 | return ( 5 | <> 6 | 7 | 2x1 8 | 9 | 10 | 2x1 11 | 12 | > 13 | ); 14 | } 15 | 16 | export default CustomExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Stack/Vertical.js: -------------------------------------------------------------------------------- 1 | import Stack from 'react-bootstrap/Stack'; 2 | 3 | function VerticalExample() { 4 | return ( 5 | 6 | First item 7 | Second item 8 | Third item 9 | 10 | ); 11 | } 12 | 13 | export default VerticalExample; 14 | -------------------------------------------------------------------------------- /src/ToastContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface ToastContextType { 4 | onClose?: (e?: React.MouseEvent | React.KeyboardEvent) => void; 5 | } 6 | 7 | const ToastContext = React.createContext({ 8 | // eslint-disable-next-line @typescript-eslint/no-empty-function 9 | onClose() {}, 10 | }); 11 | 12 | export default ToastContext; 13 | -------------------------------------------------------------------------------- /www/docs/examples/Placeholder/Size.js: -------------------------------------------------------------------------------- 1 | import Placeholder from 'react-bootstrap/Placeholder'; 2 | 3 | function SizeExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | > 11 | ); 12 | } 13 | 14 | export default SizeExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Ratio/Example.js: -------------------------------------------------------------------------------- 1 | import Ratio from 'react-bootstrap/Ratio'; 2 | 3 | function BasicExample() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | export default BasicExample; 14 | -------------------------------------------------------------------------------- /src/safeFindDOMNode.ts: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | 3 | export default function safeFindDOMNode( 4 | componentOrElement: React.Component | Element | null | undefined, 5 | ) { 6 | if (componentOrElement && 'setState' in componentOrElement) { 7 | return ReactDOM.findDOMNode(componentOrElement); 8 | } 9 | return (componentOrElement ?? null) as Element | Text | null; 10 | } 11 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/Container.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function ContainerExample() { 6 | return ( 7 | 8 | 9 | 1 of 1 10 | 11 | 12 | ); 13 | } 14 | 15 | export default ContainerExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Ratio/Default.js: -------------------------------------------------------------------------------- 1 | import Ratio from 'react-bootstrap/Ratio'; 2 | 3 | function DefaultExample() { 4 | return ( 5 | <> 6 | {['1x1', '4x3', '16x9', '21x9'].map((ratio) => ( 7 | 8 | {ratio} 9 | 10 | ))} 11 | > 12 | ); 13 | } 14 | 15 | export default DefaultExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Spinner/Sizes.js: -------------------------------------------------------------------------------- 1 | import Spinner from 'react-bootstrap/Spinner'; 2 | 3 | function SizesExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | > 11 | ); 12 | } 13 | 14 | export default SizesExample; 15 | -------------------------------------------------------------------------------- /test/TabContentSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render } from '@testing-library/react'; 3 | import TabContent from '../src/TabContent'; 4 | 5 | describe('', () => { 6 | it('Should have div as default component', () => { 7 | const { container } = render(); 8 | 9 | expect(container.tagName).toEqual('DIV'); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /www/src/components/DocLink.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Link from '@docusaurus/Link'; 3 | import useBootstrapMetadata from '@site/src/hooks/useBootstrapMetadata'; 4 | 5 | function DocLink({ path, children }) { 6 | const { bootstrapDocsUrl } = useBootstrapMetadata(); 7 | return {children}; 8 | } 9 | 10 | export default DocLink; 11 | -------------------------------------------------------------------------------- /www/docs/examples/AsPropComponent.js: -------------------------------------------------------------------------------- 1 | import Badge from 'react-bootstrap/Badge'; 2 | import Button from 'react-bootstrap/Button'; 3 | 4 | function Example() { 5 | return ( 6 | 7 | 8 | Example heading 9 | 10 | New 11 | 12 | 13 | 14 | ); 15 | } 16 | 17 | export default Example; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Badge/Button.js: -------------------------------------------------------------------------------- 1 | import Badge from 'react-bootstrap/Badge'; 2 | import Button from 'react-bootstrap/Button'; 3 | 4 | function ButtonExample() { 5 | return ( 6 | 7 | Profile 9 8 | unread messages 9 | 10 | ); 11 | } 12 | 13 | export default ButtonExample; 14 | -------------------------------------------------------------------------------- /www/docs/examples/Stack/Horizontal.js: -------------------------------------------------------------------------------- 1 | import Stack from 'react-bootstrap/Stack'; 2 | 3 | function HorizontalExample() { 4 | return ( 5 | 6 | First item 7 | Second item 8 | Third item 9 | 10 | ); 11 | } 12 | 13 | export default HorizontalExample; 14 | -------------------------------------------------------------------------------- /www/docs/examples/Button/Active.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function ActiveExample() { 4 | return ( 5 | <> 6 | 7 | Primary button 8 | 9 | 10 | Button 11 | 12 | > 13 | ); 14 | } 15 | 16 | export default ActiveExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/ContainerFluid.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function ContainerFluidExample() { 6 | return ( 7 | 8 | 9 | 1 of 1 10 | 11 | 12 | ); 13 | } 14 | 15 | export default ContainerFluidExample; 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [*.js] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [{package.json,.travis.yml}] 17 | indent_style = space 18 | indent_size = 2 19 | -------------------------------------------------------------------------------- /www/docs/examples/Stack/Buttons.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Stack from 'react-bootstrap/Stack'; 3 | 4 | function ButtonsExample() { 5 | return ( 6 | 7 | Save changes 8 | Cancel 9 | 10 | ); 11 | } 12 | 13 | export default ButtonsExample; 14 | -------------------------------------------------------------------------------- /www/src/hooks/useBootstrapMetadata.ts: -------------------------------------------------------------------------------- 1 | import { usePluginData } from '@docusaurus/useGlobalData'; 2 | 3 | interface BootstrapMetadata { 4 | bootstrapVersion: string; 5 | bootstrapDocsUrl: string; 6 | bootstrapCssHash: string; 7 | rbVersion: string; 8 | } 9 | 10 | export default function useBootstrapMetadata(): BootstrapMetadata { 11 | return usePluginData('bootstrap-metadata-plugin') as BootstrapMetadata; 12 | } 13 | -------------------------------------------------------------------------------- /src/NavbarContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | // TODO: check 4 | export interface NavbarContextType { 5 | onToggle: () => void; 6 | bsPrefix?: string; 7 | expanded: boolean; 8 | expand?: boolean | string | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; 9 | } 10 | 11 | const context = React.createContext(null); 12 | context.displayName = 'NavbarContext'; 13 | 14 | export default context; 15 | -------------------------------------------------------------------------------- /test/NavbarToggleSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render, screen } from '@testing-library/react'; 3 | import NavbarToggle from '../src/NavbarToggle'; 4 | 5 | describe('', () => { 6 | it('Should have button as default component', () => { 7 | render(); 8 | expect(screen.getByTestId('test').tagName).toEqual('BUTTON'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /www/docs/examples/Button/Block.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function BlockExample() { 4 | return ( 5 | 6 | 7 | Block level button 8 | 9 | 10 | Block level button 11 | 12 | 13 | ); 14 | } 15 | 16 | export default BlockExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/ContainerFluidBreakpoint.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function ContainerFluidBreakpointExample() { 6 | return ( 7 | 8 | 9 | 1 of 1 10 | 11 | 12 | ); 13 | } 14 | 15 | export default ContainerFluidBreakpointExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Navbar/ContainerInside.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Navbar from 'react-bootstrap/Navbar'; 3 | 4 | function ContainerInsideExample() { 5 | return ( 6 | 7 | 8 | Navbar 9 | 10 | 11 | ); 12 | } 13 | 14 | export default ContainerInsideExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/Stacked.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function StackedExample() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | export default StackedExample; 14 | -------------------------------------------------------------------------------- /www/docs/examples/Stack/HorizontalMarginStart.js: -------------------------------------------------------------------------------- 1 | import Stack from 'react-bootstrap/Stack'; 2 | 3 | function HorizontalMarginStartExample() { 4 | return ( 5 | 6 | First item 7 | Second item 8 | Third item 9 | 10 | ); 11 | } 12 | 13 | export default HorizontalMarginStartExample; 14 | -------------------------------------------------------------------------------- /www/docs/examples/Form/SelectBasic.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function SelectBasicExample() { 4 | return ( 5 | 6 | Open this select menu 7 | One 8 | Two 9 | Three 10 | 11 | ); 12 | } 13 | 14 | export default SelectBasicExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/Contextual.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function ContextualExample() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | export default ContextualExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Placeholder/Animation.js: -------------------------------------------------------------------------------- 1 | import Placeholder from 'react-bootstrap/Placeholder'; 2 | 3 | function AnimationExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | 11 | 12 | > 13 | ); 14 | } 15 | 16 | export default AnimationExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Numbered.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function NumberedExample() { 4 | return ( 5 | 6 | Cras justo odio 7 | Cras justo odio 8 | Cras justo odio 9 | 10 | ); 11 | } 12 | 13 | export default NumberedExample; 14 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/MenuHeaders.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | 3 | function MenuHeadersExample() { 4 | return ( 5 | 6 | Dropdown header 7 | Another action 8 | Something else here 9 | 10 | ); 11 | } 12 | 13 | export default MenuHeadersExample; 14 | -------------------------------------------------------------------------------- /www/docs/examples/Form/InputSizes.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function InputSizesExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | 11 | > 12 | ); 13 | } 14 | 15 | export default InputSizesExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Form/ColorPicker.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function ColorPickerExample() { 4 | return ( 5 | <> 6 | Color picker 7 | 13 | > 14 | ); 15 | } 16 | 17 | export default ColorPickerExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Horizontal.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function HorizontalExample() { 4 | return ( 5 | 6 | This 7 | ListGroup 8 | renders 9 | horizontally! 10 | 11 | ); 12 | } 13 | 14 | export default HorizontalExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Button/TagTypes.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function TagTypesExample() { 4 | return ( 5 | <> 6 | Link Button 7 | 8 | 9 | 10 | > 11 | ); 12 | } 13 | 14 | export default TagTypesExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/ProgressBar/Striped.js: -------------------------------------------------------------------------------- 1 | import ProgressBar from 'react-bootstrap/ProgressBar'; 2 | 3 | function StripedExample() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | export default StripedExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/ButtonGroup/Basic.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import ButtonGroup from 'react-bootstrap/ButtonGroup'; 3 | 4 | function BasicExample() { 5 | return ( 6 | 7 | Left 8 | Middle 9 | Right 10 | 11 | ); 12 | } 13 | 14 | export default BasicExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Stack/HorizontalVerticalRules.js: -------------------------------------------------------------------------------- 1 | import Stack from 'react-bootstrap/Stack'; 2 | 3 | function HorizontalVerticalRulesExample() { 4 | return ( 5 | 6 | First item 7 | Second item 8 | 9 | Third item 10 | 11 | ); 12 | } 13 | 14 | export default HorizontalVerticalRulesExample; 15 | -------------------------------------------------------------------------------- /www/src/theme/Playground/EditorInfoMessage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import styles from './styles.module.css'; 4 | 5 | const EditorInfoMessage: React.FC> = ( 6 | props, 7 | ) => ( 8 | 12 | ); 13 | 14 | EditorInfoMessage.displayName = 'EditorInfoMessage'; 15 | 16 | export default EditorInfoMessage; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Figure.js: -------------------------------------------------------------------------------- 1 | import Figure from 'react-bootstrap/Figure'; 2 | 3 | function FigureExample() { 4 | return ( 5 | 6 | 12 | 13 | Nulla vitae elit libero, a pharetra augue mollis interdum. 14 | 15 | 16 | ); 17 | } 18 | 19 | export default FigureExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/InputGroup/MultipleInputs.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | import InputGroup from 'react-bootstrap/InputGroup'; 3 | 4 | function MultipleInputsExample() { 5 | return ( 6 | 7 | First and last name 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | export default MultipleInputsExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Breadcrumb.js: -------------------------------------------------------------------------------- 1 | import Breadcrumb from 'react-bootstrap/Breadcrumb'; 2 | 3 | function BreadcrumbExample() { 4 | return ( 5 | 6 | Home 7 | 8 | Library 9 | 10 | Data 11 | 12 | ); 13 | } 14 | 15 | export default BreadcrumbExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Flush.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function FlushExample() { 4 | return ( 5 | 6 | Cras justo odio 7 | Dapibus ac facilisis in 8 | Morbi leo risus 9 | Porta ac consectetur ac 10 | 11 | ); 12 | } 13 | 14 | export default FlushExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Disabled.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function DisabledExample() { 4 | return ( 5 | 6 | Cras justo odio 7 | Dapibus ac facilisis in 8 | Morbi leo risus 9 | Porta ac consectetur ac 10 | 11 | ); 12 | } 13 | 14 | export default DisabledExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Navbar/ContainerOutside.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Navbar from 'react-bootstrap/Navbar'; 3 | 4 | function ContainerOutsideExample() { 5 | return ( 6 | 7 | 8 | 9 | Navbar 10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | export default ContainerOutsideExample; 17 | -------------------------------------------------------------------------------- /src/getTabTransitionComponent.ts: -------------------------------------------------------------------------------- 1 | import { TransitionComponent } from '@restart/ui/types'; 2 | import NoopTransition from '@restart/ui/NoopTransition'; 3 | import Fade from './Fade'; 4 | import { TransitionType } from './helpers'; 5 | 6 | export default function getTabTransitionComponent( 7 | transition?: TransitionType, 8 | ): TransitionComponent | undefined { 9 | if (typeof transition === 'boolean') { 10 | return transition ? Fade : NoopTransition; 11 | } 12 | 13 | return transition; 14 | } 15 | -------------------------------------------------------------------------------- /src/NavContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { EventKey } from '@restart/ui/types'; 3 | 4 | interface NavContextType { 5 | role?: string; // used by NavLink to determine it's role 6 | activeKey: EventKey | null; 7 | getControlledId: (key: EventKey | null) => string; 8 | getControllerId: (key: EventKey | null) => string; 9 | } 10 | 11 | const NavContext = React.createContext(null); 12 | NavContext.displayName = 'NavContext'; 13 | 14 | export default NavContext; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Stacked.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function StackedExample() { 4 | return ( 5 | 6 | Active 7 | Link 8 | Link 9 | 10 | Disabled 11 | 12 | 13 | ); 14 | } 15 | 16 | export default StackedExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Toast/Basic.js: -------------------------------------------------------------------------------- 1 | import Toast from 'react-bootstrap/Toast'; 2 | 3 | function BasicExample() { 4 | return ( 5 | 6 | 7 | 8 | Bootstrap 9 | 11 mins ago 10 | 11 | Hello, world! This is a toast message. 12 | 13 | ); 14 | } 15 | 16 | export default BasicExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Button/Disabled.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function DisabledExample() { 4 | return ( 5 | <> 6 | 7 | Primary button 8 | 9 | 10 | Button 11 | 12 | 13 | Link 14 | 15 | > 16 | ); 17 | } 18 | 19 | export default DisabledExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/Ordering.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function OrderingExample() { 6 | return ( 7 | 8 | 9 | First, but unordered 10 | Second, but last 11 | Third, but second 12 | 13 | 14 | ); 15 | } 16 | 17 | export default OrderingExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Form/GridBasic.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import Form from 'react-bootstrap/Form'; 3 | import Row from 'react-bootstrap/Row'; 4 | 5 | function GridBasicExample() { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default GridBasicExample; 21 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/RowColLayoutColWidthBreakpoint.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function RowColLayoutColWidthBreakpointExample() { 6 | return ( 7 | 8 | 9 | 1 of 3 10 | 2 of 3 11 | 3 of 3 12 | 13 | 14 | ); 15 | } 16 | 17 | export default RowColLayoutColWidthBreakpointExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Header.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function HeaderExample() { 4 | return ( 5 | 6 | Some body text 7 | 8 | Linked item 9 | 10 | 11 | Danger styling 12 | 13 | 14 | ); 15 | } 16 | 17 | export default HeaderExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Form/Switch.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function SwitchExample() { 4 | return ( 5 | 6 | 11 | 17 | 18 | ); 19 | } 20 | 21 | export default SwitchExample; 22 | -------------------------------------------------------------------------------- /src/DropdownContext.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { AlignType } from './types'; 3 | 4 | export type DropDirection = 5 | | 'up' 6 | | 'up-centered' 7 | | 'start' 8 | | 'end' 9 | | 'down' 10 | | 'down-centered'; 11 | 12 | export type DropdownContextValue = { 13 | align?: AlignType; 14 | drop?: DropDirection; 15 | isRTL?: boolean; 16 | }; 17 | 18 | const DropdownContext = React.createContext({}); 19 | DropdownContext.displayName = 'DropdownContext'; 20 | 21 | export default DropdownContext; 22 | -------------------------------------------------------------------------------- /src/ToastFade.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Transition, { 3 | ENTERING, 4 | EXITING, 5 | } from 'react-transition-group/Transition'; 6 | import Fade, { FadeProps } from './Fade'; 7 | 8 | const fadeStyles = { 9 | [ENTERING]: 'showing', 10 | [EXITING]: 'showing show', 11 | }; 12 | 13 | const ToastFade = React.forwardRef, FadeProps>((props, ref) => ( 14 | 15 | )); 16 | 17 | ToastFade.displayName = 'ToastFade'; 18 | 19 | export default ToastFade; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/DropdownImpl.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | import NavItem from 'react-bootstrap/NavItem'; 3 | import NavLink from 'react-bootstrap/NavLink'; 4 | 5 | function DropdownImplExample() { 6 | return ( 7 | 8 | Click to see more… 9 | 10 | Hello there! 11 | 12 | 13 | ); 14 | } 15 | 16 | export default DropdownImplExample; 17 | -------------------------------------------------------------------------------- /www/docs/utilities/restart-ui.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "@restart/ui" 3 | description: Low-level components and utilities for building beautiful accessible components 4 | sidebar_position: 3 5 | --- 6 | 7 | Often times you may need a more generic or low-level version of a 8 | Bootstrap component. Many of the `react-bootstrap` components 9 | are built on top of components from [@restart/ui](https://github.com/react-restart/ui). 10 | If you find yourself at the limit of a Bootstrap component, consider using 11 | the `@restart/ui` base component directly. 12 | -------------------------------------------------------------------------------- /www/src/theme/ReactLiveScope.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactBootstrap from 'react-bootstrap'; 3 | import * as formik from 'formik'; 4 | import * as yup from 'yup'; 5 | import ExampleCarouselImage from '../components/ExampleCarouselImage'; 6 | 7 | // Add react-live imports you need here 8 | const ReactLiveScope = { 9 | React, 10 | ...React, 11 | ...ReactBootstrap, 12 | formik, 13 | yup, 14 | ExampleCarouselImage, 15 | }; 16 | 17 | delete (ReactLiveScope as any).default; 18 | 19 | export default ReactLiveScope; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Form/SelectSizes.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function SelectSizesExample() { 4 | return ( 5 | <> 6 | 7 | Large select 8 | 9 | 10 | 11 | Default select 12 | 13 | 14 | 15 | Small select 16 | 17 | > 18 | ); 19 | } 20 | 21 | export default SelectSizesExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/AutoLayout.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function AutoLayoutExample() { 6 | return ( 7 | 8 | 9 | 1 of 2 10 | 2 of 2 11 | 12 | 13 | 1 of 3 14 | 2 of 3 15 | 3 of 3 16 | 17 | 18 | ); 19 | } 20 | 21 | export default AutoLayoutExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Default.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function DefaultExample() { 4 | return ( 5 | 6 | Cras justo odio 7 | Dapibus ac facilisis in 8 | Morbi leo risus 9 | Porta ac consectetur ac 10 | Vestibulum at eros 11 | 12 | ); 13 | } 14 | 15 | export default DefaultExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/List.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function ListExample() { 4 | return ( 5 | 6 | 7 | Active 8 | 9 | 10 | Link 11 | 12 | 13 | Link 14 | 15 | 16 | ); 17 | } 18 | 19 | export default ListExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Card/ListGroups.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | import ListGroup from 'react-bootstrap/ListGroup'; 3 | 4 | function ListGroupExample() { 5 | return ( 6 | 7 | 8 | Cras justo odio 9 | Dapibus ac facilisis in 10 | Vestibulum at eros 11 | 12 | 13 | ); 14 | } 15 | 16 | export default ListGroupExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/OrderingFirstLast.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function OrderingFirstLastExample() { 6 | return ( 7 | 8 | 9 | First, but last 10 | Second, but unordered 11 | Third, but first 12 | 13 | 14 | ); 15 | } 16 | 17 | export default OrderingFirstLastExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Form/ValidationInputGroup.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | import InputGroup from 'react-bootstrap/InputGroup'; 3 | 4 | function ValidationInputGroupExample() { 5 | return ( 6 | 7 | @ 8 | 9 | 10 | Please choose a username. 11 | 12 | 13 | ); 14 | } 15 | 16 | export default ValidationInputGroupExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Stack/Form.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Form from 'react-bootstrap/Form'; 3 | import Stack from 'react-bootstrap/Stack'; 4 | 5 | function FormExample() { 6 | return ( 7 | 8 | 9 | Submit 10 | 11 | Reset 12 | 13 | ); 14 | } 15 | 16 | export default FormExample; 17 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/MenuDividers.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | 3 | function MenuDividersExample() { 4 | return ( 5 | 6 | Action 7 | Another action 8 | Something else here 9 | 10 | Separated link 11 | 12 | ); 13 | } 14 | 15 | export default MenuDividersExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Alert/Basic.js: -------------------------------------------------------------------------------- 1 | import Alert from 'react-bootstrap/Alert'; 2 | 3 | function BasicExample() { 4 | return ( 5 | <> 6 | {[ 7 | 'primary', 8 | 'secondary', 9 | 'success', 10 | 'danger', 11 | 'warning', 12 | 'info', 13 | 'light', 14 | 'dark', 15 | ].map((variant) => ( 16 | 17 | This is a {variant} alert—check it out! 18 | 19 | ))} 20 | > 21 | ); 22 | } 23 | 24 | export default BasicExample; 25 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Buttons.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function ButtonExample() { 4 | const alertClicked = () => { 5 | alert('You clicked the third ListGroupItem'); 6 | }; 7 | 8 | return ( 9 | 10 | Link 1 11 | Link 2 12 | 13 | Trigger an alert 14 | 15 | 16 | ); 17 | } 18 | 19 | export default ButtonExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/ResponsiveAuto.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function ResponsiveAutoExample() { 6 | return ( 7 | 8 | 9 | sm=8 10 | sm=4 11 | 12 | 13 | sm=true 14 | sm=true 15 | sm=true 16 | 17 | 18 | ); 19 | } 20 | 21 | export default ResponsiveAutoExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/BasicButton.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | import DropdownButton from 'react-bootstrap/DropdownButton'; 3 | 4 | function BasicButtonExample() { 5 | return ( 6 | 7 | Action 8 | Another action 9 | Something else 10 | 11 | ); 12 | } 13 | 14 | export default BasicButtonExample; 15 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Tabs.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function TabsExample() { 4 | return ( 5 | 6 | 7 | Active 8 | 9 | 10 | Option 2 11 | 12 | 13 | 14 | Disabled 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default TabsExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/Theming/Variants.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function VariantsExample() { 4 | return ( 5 | <> 6 | 19 | 20 | 21 | flat button 22 | 23 | > 24 | ); 25 | } 26 | 27 | export default VariantsExample; 28 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Active.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function ActiveExample() { 4 | return ( 5 | 6 | 7 | Cras justo odio 8 | 9 | Dapibus ac facilisis in 10 | 11 | Morbi leo risus 12 | 13 | Porta ac consectetur ac 14 | 15 | ); 16 | } 17 | 18 | export default ActiveExample; 19 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Pills.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function PillsExample() { 4 | return ( 5 | 6 | 7 | Active 8 | 9 | 10 | Option 2 11 | 12 | 13 | 14 | Disabled 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default PillsExample; 22 | -------------------------------------------------------------------------------- /www/src/theme/MDXComponents.ts: -------------------------------------------------------------------------------- 1 | // Import the original mapper 2 | import MDXComponents from '@theme-original/MDXComponents'; 3 | import AriaAbbr from '@site/src/components/AriaAbbr'; 4 | import CodeBlock from '@theme/CodeBlock'; 5 | import CssCodeBlock from '@site/src/components/CssCodeBlock'; 6 | import DocLink from '@site/src/components/DocLink'; 7 | import PropsTable from '@site/src/components/PropsTable'; 8 | 9 | export default { 10 | // Re-use the default mapping 11 | ...MDXComponents, 12 | AriaAbbr, 13 | CodeBlock, 14 | CssCodeBlock, 15 | DocLink, 16 | PropsTable, 17 | }; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Theming/Prefixes.js: -------------------------------------------------------------------------------- 1 | import ThemeProvider from 'react-bootstrap/ThemeProvider'; 2 | import Button from 'react-bootstrap/Button'; 3 | 4 | function PrefixesExample() { 5 | return ( 6 | <> 7 | {/* Hint: inspect the markup to see how the classes differ */} 8 | 9 | My Button 10 | 11 | 12 | Super button 13 | 14 | > 15 | ); 16 | } 17 | 18 | export default PrefixesExample; 19 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/Disabled.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; 3 | import Tooltip from 'react-bootstrap/Tooltip'; 4 | 5 | function DisabledExample() { 6 | return ( 7 | Tooltip!}> 8 | 9 | 10 | Disabled button 11 | 12 | 13 | 14 | ); 15 | } 16 | 17 | export default DisabledExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Underline.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function UnderlineExample() { 4 | return ( 5 | 6 | 7 | Active 8 | 9 | 10 | Option 2 11 | 12 | 13 | 14 | Disabled 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default UnderlineExample; 22 | -------------------------------------------------------------------------------- /src/FigureImage.tsx: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import * as React from 'react'; 3 | 4 | import Image, { ImageProps, propTypes as imagePropTypes } from './Image'; 5 | 6 | const FigureImage = React.forwardRef( 7 | ({ className, fluid = true, ...props }, ref) => ( 8 | 14 | ), 15 | ); 16 | 17 | FigureImage.displayName = 'FigureImage'; 18 | FigureImage.propTypes = imagePropTypes; 19 | 20 | export default FigureImage; 21 | -------------------------------------------------------------------------------- /www/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | -------------------------------------------------------------------------------- /www/docs/examples/Card/WithHeader.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Card from 'react-bootstrap/Card'; 3 | 4 | function WithHeaderExample() { 5 | return ( 6 | 7 | Featured 8 | 9 | Special title treatment 10 | 11 | With supporting text below as a natural lead-in to additional content. 12 | 13 | Go somewhere 14 | 15 | 16 | ); 17 | } 18 | 19 | export default WithHeaderExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Form/GridColSizes.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import Form from 'react-bootstrap/Form'; 3 | import Row from 'react-bootstrap/Row'; 4 | 5 | function GridColSizesExample() { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | 23 | export default GridColSizesExample; 24 | -------------------------------------------------------------------------------- /www/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | gap: 1rem; 24 | } 25 | 26 | .carbonads { 27 | margin-top: 1rem; 28 | display: flex; 29 | justify-content: center; 30 | } 31 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/AutoLayoutSizing.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function AutoLayoutSizingExample() { 6 | return ( 7 | 8 | 9 | 1 of 3 10 | 2 of 3 (wider) 11 | 3 of 3 12 | 13 | 14 | 1 of 3 15 | 2 of 3 (wider) 16 | 3 of 3 17 | 18 | 19 | ); 20 | } 21 | 22 | export default AutoLayoutSizingExample; 23 | -------------------------------------------------------------------------------- /www/docs/examples/Pagination/Basic.js: -------------------------------------------------------------------------------- 1 | import Pagination from 'react-bootstrap/Pagination'; 2 | 3 | let active = 2; 4 | let items = []; 5 | for (let number = 1; number <= 5; number++) { 6 | items.push( 7 | 8 | {number} 9 | , 10 | ); 11 | } 12 | 13 | const paginationBasic = ( 14 | 15 | {items} 16 | 17 | 18 | {items} 19 | 20 | 21 | {items} 22 | 23 | ); 24 | 25 | render(paginationBasic); 26 | -------------------------------------------------------------------------------- /src/Switch.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import FormCheck, { FormCheckProps } from './FormCheck'; 3 | import { BsPrefixRefForwardingComponent } from './helpers'; 4 | 5 | type SwitchProps = Omit; 6 | 7 | const Switch: BsPrefixRefForwardingComponent = 8 | React.forwardRef((props, ref) => ( 9 | 10 | )) as typeof Switch; 11 | 12 | Switch.displayName = 'Switch'; 13 | 14 | export default Object.assign(Switch, { 15 | Input: FormCheck.Input, 16 | Label: FormCheck.Label, 17 | }); 18 | -------------------------------------------------------------------------------- /test/ToastBodySpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render } from '@testing-library/react'; 3 | import Toast from '../src/Toast'; 4 | 5 | describe('Toast.Body', () => { 6 | it('will pass all props to the created div and renders its children', () => { 7 | const content = Content; 8 | const { container } = render( 9 | {content}, 10 | ); 11 | expect(container.firstElementChild!.classList).toContain('custom-class'); 12 | expect(container.firstElementChild!.classList).toContain('toast-body'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /www/docs/examples/Card/ListGroupWithHeader.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | import ListGroup from 'react-bootstrap/ListGroup'; 3 | 4 | function ListGroupWithHeaderExample() { 5 | return ( 6 | 7 | Featured 8 | 9 | Cras justo odio 10 | Dapibus ac facilisis in 11 | Vestibulum at eros 12 | 13 | 14 | ); 15 | } 16 | 17 | export default ListGroupWithHeaderExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/Basic.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | 3 | function BasicExample() { 4 | return ( 5 | 6 | 7 | Dropdown Button 8 | 9 | 10 | 11 | Action 12 | Another action 13 | Something else 14 | 15 | 16 | ); 17 | } 18 | 19 | export default BasicExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Placeholder/Color.js: -------------------------------------------------------------------------------- 1 | import Placeholder from 'react-bootstrap/Placeholder'; 2 | 3 | function ColorExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | > 17 | ); 18 | } 19 | 20 | export default ColorExample; 21 | -------------------------------------------------------------------------------- /www/docs/getting-started/server-side-rendering.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Server-side Rendering 3 | sidebar_position: 7 4 | --- 5 | 6 | React-Bootstrap automatically generates an `id` for some 7 | components (such as `DropdownToggle`) if they are not provided. 8 | This is done for accessibility purposes. 9 | 10 | In server-side rendered applications, a `SSRProvider` must wrap 11 | the application in order to ensure that the auto-generated ids 12 | are consistent between the server and client. 13 | 14 | ```jsx 15 | import SSRProvider from 'react-bootstrap/SSRProvider'; 16 | 17 | 18 | 19 | ; 20 | ``` 21 | -------------------------------------------------------------------------------- /www/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "esModuleInterop": true, 5 | "jsx": "preserve", 6 | "lib": ["DOM"], 7 | "moduleResolution": "Bundler", 8 | "module": "ESNext", 9 | "noEmit": true, 10 | "types": [ 11 | "node", 12 | "@docusaurus/module-type-aliases", 13 | "@docusaurus/theme-classic" 14 | ], 15 | "baseUrl": ".", 16 | "paths": { 17 | "@site/*": ["./*"], 18 | "react-bootstrap/*": ["../src/*"] 19 | }, 20 | "skipLibCheck": true, 21 | "resolveJsonModule": true 22 | }, 23 | "include": ["./src", "../src"] 24 | } 25 | -------------------------------------------------------------------------------- /www/docs/components/figures.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Figures 3 | description: Documentation and examples for displaying related images and text with the figure component in Bootstrap. 4 | --- 5 | 6 | import Figure from '!!raw-loader!../examples/Figure'; 7 | 8 | ## Figure 9 | 10 | Displaying related images and text with the Figure component. 11 | 12 | 13 | {Figure} 14 | 15 | 16 | ## API 17 | 18 | ### Figure 19 | 20 | 21 | 22 | ### FigureImage 23 | 24 | 25 | 26 | ### FigureCaption 27 | 28 | 29 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormControlDisabled.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function FormControlDisabledExample() { 4 | return ( 5 | <> 6 | 13 | 14 | 20 | > 21 | ); 22 | } 23 | 24 | export default FormControlDisabledExample; 25 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormGroup.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function FormGroupExample() { 4 | return ( 5 | 6 | 7 | Email address 8 | 9 | 10 | 11 | Password 12 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default FormGroupExample; 19 | -------------------------------------------------------------------------------- /www/docs/examples/Card/WithHeaderStyled.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Card from 'react-bootstrap/Card'; 3 | 4 | function WithHeaderStyledExample() { 5 | return ( 6 | 7 | Featured 8 | 9 | Special title treatment 10 | 11 | With supporting text below as a natural lead-in to additional content. 12 | 13 | Go somewhere 14 | 15 | 16 | ); 17 | } 18 | 19 | export default WithHeaderStyledExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/DropdownItemTags.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | import DropdownButton from 'react-bootstrap/DropdownButton'; 3 | 4 | function DropdownItemTagsExample() { 5 | return ( 6 | 7 | Dropdown item text 8 | Action 9 | Another action 10 | Something else 11 | 12 | ); 13 | } 14 | 15 | export default DropdownItemTagsExample; 16 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormFloatingSelect.js: -------------------------------------------------------------------------------- 1 | import FloatingLabel from 'react-bootstrap/FloatingLabel'; 2 | import Form from 'react-bootstrap/Form'; 3 | 4 | function FormFloatingSelectExample() { 5 | return ( 6 | 7 | 8 | Open this select menu 9 | One 10 | Two 11 | Three 12 | 13 | 14 | ); 15 | } 16 | 17 | export default FormFloatingSelectExample; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormText.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function FormTextExample() { 4 | return ( 5 | <> 6 | Password 7 | 12 | 13 | Your password must be 8-20 characters long, contain letters and numbers, 14 | and must not contain spaces, special characters, or emoji. 15 | 16 | > 17 | ); 18 | } 19 | 20 | export default FormTextExample; 21 | -------------------------------------------------------------------------------- /www/docs/examples/Button/Types.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function TypesExample() { 4 | return ( 5 | <> 6 | Primary 7 | Secondary 8 | Success 9 | Warning 10 | Danger 11 | Info 12 | Light 13 | Dark 14 | Link 15 | > 16 | ); 17 | } 18 | 19 | export default TypesExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Form/TextControls.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function TextControlsExample() { 4 | return ( 5 | 6 | 7 | Email address 8 | 9 | 10 | 11 | Example textarea 12 | 13 | 14 | 15 | ); 16 | } 17 | 18 | export default TextControlsExample; 19 | -------------------------------------------------------------------------------- /www/docs/examples/ButtonGroup/Nested.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import DropdownButton from 'react-bootstrap/DropdownButton'; 3 | import Dropdown from 'react-bootstrap/Dropdown'; 4 | 5 | function NestedExample() { 6 | return ( 7 | 8 | 1 9 | 2 10 | 11 | 12 | Dropdown link 13 | Dropdown link 14 | 15 | 16 | ); 17 | } 18 | 19 | export default NestedExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Navbar/TextLink.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Navbar from 'react-bootstrap/Navbar'; 3 | 4 | function TextLinkExample() { 5 | return ( 6 | 7 | 8 | Navbar with text 9 | 10 | 11 | 12 | Signed in as: Mark Otto 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default TextLinkExample; 21 | -------------------------------------------------------------------------------- /www/docs/examples/Alert/Link.js: -------------------------------------------------------------------------------- 1 | import Alert from 'react-bootstrap/Alert'; 2 | 3 | function LinksExample() { 4 | return ( 5 | <> 6 | {[ 7 | 'primary', 8 | 'secondary', 9 | 'success', 10 | 'danger', 11 | 'warning', 12 | 'info', 13 | 'light', 14 | 'dark', 15 | ].map((variant) => ( 16 | 17 | This is a {variant} alert with{' '} 18 | an example link. Give it a click if 19 | you like. 20 | 21 | ))} 22 | > 23 | ); 24 | } 25 | 26 | export default LinksExample; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Card/Basic.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Card from 'react-bootstrap/Card'; 3 | 4 | function BasicExample() { 5 | return ( 6 | 7 | 8 | 9 | Card Title 10 | 11 | Some quick example text to build on the card title and make up the 12 | bulk of the card's content. 13 | 14 | Go somewhere 15 | 16 | 17 | ); 18 | } 19 | 20 | export default BasicExample; 21 | -------------------------------------------------------------------------------- /www/src/components/CssCodeBlock.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import CodeBlock from '@theme/CodeBlock'; 3 | import useBootstrapMetadata from '@site/src/hooks/useBootstrapMetadata'; 4 | 5 | const CssCodeBlock: React.FC = () => { 6 | const { bootstrapCssHash, bootstrapVersion } = useBootstrapMetadata(); 7 | 8 | return ( 9 | 10 | {` 16 | `} 17 | 18 | ); 19 | }; 20 | 21 | export default CssCodeBlock; 22 | -------------------------------------------------------------------------------- /www/src/theme/CodeBlock.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CodeBlock from '@theme-original/CodeBlock'; 3 | import type CodeBlockType from '@theme/CodeBlock'; 4 | import type { WrapperProps } from '@docusaurus/types'; 5 | 6 | const IGNORE_IMPORTS_EXPORTS_REGEX = /^.*\b(import|export)\b.*$/gim; 7 | 8 | function transformCode(rawCode: string) { 9 | return rawCode.replace(IGNORE_IMPORTS_EXPORTS_REGEX, ''); 10 | } 11 | 12 | type Props = WrapperProps; 13 | 14 | export default function CodeBlockWrapper(props: Props): JSX.Element { 15 | return ( 16 | <> 17 | 18 | > 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Linked.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function LinkedExample() { 4 | const alertClicked = () => { 5 | alert('You clicked the third ListGroupItem'); 6 | }; 7 | 8 | return ( 9 | 10 | 11 | Link 1 12 | 13 | 14 | Link 2 15 | 16 | 17 | This one is a button 18 | 19 | 20 | ); 21 | } 22 | 23 | export default LinkedExample; 24 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/Trigger.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; 3 | import Tooltip from 'react-bootstrap/Tooltip'; 4 | 5 | function TriggerExample() { 6 | const renderTooltip = (props) => ( 7 | 8 | Simple tooltip 9 | 10 | ); 11 | 12 | return ( 13 | 18 | Hover me to see 19 | 20 | ); 21 | } 22 | 23 | export default TriggerExample; 24 | -------------------------------------------------------------------------------- /www/docs/examples/Card/ImgOverlay.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function ImgOverlayExample() { 4 | return ( 5 | 6 | 7 | 8 | Card title 9 | 10 | This is a wider card with supporting text below as a natural lead-in 11 | to additional content. This content is a little bit longer. 12 | 13 | Last updated 3 mins ago 14 | 15 | 16 | ); 17 | } 18 | 19 | export default ImgOverlayExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Card/Text.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function TextExample() { 4 | return ( 5 | 6 | 7 | Card Title 8 | Card Subtitle 9 | 10 | Some quick example text to build on the card title and make up the 11 | bulk of the card's content. 12 | 13 | Card Link 14 | Another Link 15 | 16 | 17 | ); 18 | } 19 | 20 | export default TextExample; 21 | -------------------------------------------------------------------------------- /www/docs/examples/Form/CheckApi.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function CheckApiExample() { 4 | return ( 5 | 6 | {['checkbox', 'radio'].map((type) => ( 7 | 8 | 9 | 10 | {`Custom api ${type}`} 11 | 12 | You did it! 13 | 14 | 15 | 16 | ))} 17 | 18 | ); 19 | } 20 | 21 | export default CheckApiExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/InputGroup/Checkboxes.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | import InputGroup from 'react-bootstrap/InputGroup'; 3 | 4 | function CheckboxesExample() { 5 | return ( 6 | <> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | > 16 | ); 17 | } 18 | 19 | export default CheckboxesExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/HorizontalResponsive.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function HorizontalResponsiveExample() { 4 | return ( 5 | <> 6 | {['sm', 'md', 'lg', 'xl', 'xxl'].map((breakpoint) => ( 7 | 8 | This ListGroup 9 | renders horizontally 10 | on {breakpoint} 11 | and above! 12 | 13 | ))} 14 | > 15 | ); 16 | } 17 | 18 | export default HorizontalResponsiveExample; 19 | -------------------------------------------------------------------------------- /www/docs/examples/Button/OutlineTypes.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function OutlineTypesExample() { 4 | return ( 5 | <> 6 | Primary 7 | Secondary 8 | Success 9 | Warning 10 | Danger 11 | Info 12 | Light 13 | Dark 14 | > 15 | ); 16 | } 17 | 18 | export default OutlineTypesExample; 19 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Fill.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function FillExample() { 4 | return ( 5 | 6 | 7 | Active 8 | 9 | 10 | Loooonger NavLink 11 | 12 | 13 | Link 14 | 15 | 16 | 17 | Disabled 18 | 19 | 20 | 21 | ); 22 | } 23 | 24 | export default FillExample; 25 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormFloatingBasic.js: -------------------------------------------------------------------------------- 1 | import FloatingLabel from 'react-bootstrap/FloatingLabel'; 2 | import Form from 'react-bootstrap/Form'; 3 | 4 | function FormFloatingBasicExample() { 5 | return ( 6 | <> 7 | 12 | 13 | 14 | 15 | 16 | 17 | > 18 | ); 19 | } 20 | 21 | export default FormFloatingBasicExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/Tabs/Uncontrolled.js: -------------------------------------------------------------------------------- 1 | import Tab from 'react-bootstrap/Tab'; 2 | import Tabs from 'react-bootstrap/Tabs'; 3 | 4 | function UncontrolledExample() { 5 | return ( 6 | 11 | 12 | Tab content for Home 13 | 14 | 15 | Tab content for Profile 16 | 17 | 18 | Tab content for Contact 19 | 20 | 21 | ); 22 | } 23 | 24 | export default UncontrolledExample; 25 | -------------------------------------------------------------------------------- /www/docs/components/breadcrumb.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Breadcrumbs 3 | description: Indicate the current page’s location within a navigational hierarchy that automatically adds separators via CSS. 4 | --- 5 | 6 | import Breadcrumb from '!!raw-loader!../examples/Breadcrumb'; 7 | 8 | ## Example 9 | 10 | Add `active` prop to the active `Breadcrumb.Item`. Do not set both `active` and `href` attributes. `active` overrides `href` and `span` element is rendered instead of `a`. 11 | 12 | 13 | {Breadcrumb} 14 | 15 | 16 | ## API 17 | 18 | ### Breadcrumb 19 | 20 | 21 | 22 | ### BreadcrumbItem 23 | 24 | 25 | -------------------------------------------------------------------------------- /www/docs/getting-started/color-modes.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Color modes 3 | sidebar_position: 4 4 | --- 5 | 6 | import ColorMode from '!!raw-loader!../examples/ColorMode'; 7 | 8 | # Color modes 9 | 10 | Bootstrap v5.3 now supports color modes such as dark mode. Color modes can be 11 | toggled globally on the `` element, or on specific components and elements, 12 | thanks to the `data-bs-theme` attribute. 13 | 14 | ## Example 15 | 16 | 17 | {ColorMode} 18 | 19 | 20 | ## Customizing 21 | 22 | For more information on how colors modes work or how to customize colors, check out 23 | the Bootstrap color mode docs. 24 | -------------------------------------------------------------------------------- /www/docs/examples/Form/Check.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function CheckExample() { 4 | return ( 5 | 6 | {['checkbox', 'radio'].map((type) => ( 7 | 8 | 13 | 14 | 20 | 21 | ))} 22 | 23 | ); 24 | } 25 | 26 | export default CheckExample; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Justified.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function JustifiedExample() { 4 | return ( 5 | 6 | 7 | Active 8 | 9 | 10 | Loooonger NavLink 11 | 12 | 13 | Link 14 | 15 | 16 | 17 | Disabled 18 | 19 | 20 | 21 | ); 22 | } 23 | 24 | export default JustifiedExample; 25 | -------------------------------------------------------------------------------- /www/docs/examples/Tabs/NoAnimation.js: -------------------------------------------------------------------------------- 1 | import Tab from 'react-bootstrap/Tab'; 2 | import Tabs from 'react-bootstrap/Tabs'; 3 | 4 | function NoAnimationExample() { 5 | return ( 6 | 12 | 13 | Tab content for Home 14 | 15 | 16 | Tab content for Profile 17 | 18 | 19 | Tab content for Contact 20 | 21 | 22 | ); 23 | } 24 | 25 | export default NoAnimationExample; 26 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/RowColLayout.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function RowColLayoutExample() { 6 | return ( 7 | 8 | 9 | 1 of 2 10 | 2 of 2 11 | 12 | 13 | 1 of 3 14 | 2 of 3 15 | 3 of 3 16 | 17 | 18 | 1 of 3 19 | 2 of 3 20 | 3 of 3 21 | 22 | 23 | ); 24 | } 25 | 26 | export default RowColLayoutExample; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Button/Sizes.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | 3 | function SizesExample() { 4 | return ( 5 | <> 6 | 7 | 8 | Large button 9 | 10 | 11 | Large button 12 | 13 | 14 | 15 | 16 | Small button 17 | 18 | 19 | Small button 20 | 21 | 22 | > 23 | ); 24 | } 25 | 26 | export default SizesExample; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Card/HeaderAndFooter.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Card from 'react-bootstrap/Card'; 3 | 4 | function HeaderAndFooterExample() { 5 | return ( 6 | 7 | Featured 8 | 9 | Special title treatment 10 | 11 | With supporting text below as a natural lead-in to additional content. 12 | 13 | Go somewhere 14 | 15 | 2 days ago 16 | 17 | ); 18 | } 19 | 20 | export default HeaderAndFooterExample; 21 | -------------------------------------------------------------------------------- /www/docs/examples/Card/WithHeaderAndQuote.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function WithHeaderAndQuoteExample() { 4 | return ( 5 | 6 | Quote 7 | 8 | 9 | 10 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer 11 | posuere erat a ante. 12 | 13 | 16 | 17 | 18 | 19 | ); 20 | } 21 | 22 | export default WithHeaderAndQuoteExample; 23 | -------------------------------------------------------------------------------- /www/docs/examples/Image/Shape.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import Container from 'react-bootstrap/Container'; 3 | import Image from 'react-bootstrap/Image'; 4 | import Row from 'react-bootstrap/Row'; 5 | 6 | function ShapeExample() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | } 23 | 24 | export default ShapeExample; 25 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/PopoverBasic.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; 3 | import Popover from 'react-bootstrap/Popover'; 4 | 5 | const popover = ( 6 | 7 | Popover right 8 | 9 | And here's some amazing content. It's very engaging. 10 | right? 11 | 12 | 13 | ); 14 | 15 | const Example = () => ( 16 | 17 | Click me to see 18 | 19 | ); 20 | 21 | render(); 22 | -------------------------------------------------------------------------------- /test/helpers.ts: -------------------------------------------------------------------------------- 1 | let style: any; 2 | let seen: string[] = []; 3 | 4 | // eslint-disable-next-line import/prefer-default-export 5 | export function injectCss(rules: string) { 6 | if (seen.indexOf(rules) !== -1) { 7 | return; 8 | } 9 | 10 | style = 11 | style || 12 | (function iife() { 13 | const _style = document.createElement('style'); 14 | _style.appendChild(document.createTextNode('')); 15 | document.head.appendChild(_style); 16 | return _style; 17 | })(); 18 | 19 | seen.push(rules); 20 | style.innerHTML += `\n${rules}`; 21 | } 22 | 23 | injectCss.reset = () => { 24 | if (style) { 25 | document.head.removeChild(style); 26 | } 27 | style = null; 28 | seen = []; 29 | }; 30 | -------------------------------------------------------------------------------- /www/docs/examples/Badge/Variations.js: -------------------------------------------------------------------------------- 1 | import Badge from 'react-bootstrap/Badge'; 2 | import Stack from 'react-bootstrap/Stack'; 3 | 4 | function VariationsExample() { 5 | return ( 6 | 7 | Primary 8 | Secondary 9 | Success 10 | Danger 11 | 12 | Warning 13 | 14 | Info 15 | 16 | Light 17 | 18 | Dark 19 | 20 | ); 21 | } 22 | 23 | export default VariationsExample; 24 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/MenuAlignEnd.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | import DropdownButton from 'react-bootstrap/DropdownButton'; 3 | 4 | function MenuAlignEndExample() { 5 | return ( 6 | 11 | Action 12 | Another action 13 | Something else here 14 | 15 | Separated link 16 | 17 | ); 18 | } 19 | 20 | export default MenuAlignEndExample; 21 | -------------------------------------------------------------------------------- /www/docs/forms/select.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Select 3 | description: Customize the native with custom CSS that changes the element’s initial appearance. 4 | sidebar_position: 4 5 | --- 6 | 7 | import SelectBasic from '!!raw-loader!../examples/Form/SelectBasic'; 8 | import SelectSizes from '!!raw-loader!../examples/Form/SelectSizes'; 9 | 10 | ## Default 11 | 12 | 13 | {SelectBasic} 14 | 15 | 16 | ## Sizing 17 | 18 | You may also choose from small and large custom selects to match our 19 | similarly sized text inputs. 20 | 21 | 22 | {SelectSizes} 23 | 24 | 25 | ## API 26 | 27 | ### FormSelect 28 | 29 | 30 | -------------------------------------------------------------------------------- /www/src/theme/ColorModeToggle/styles.module.css: -------------------------------------------------------------------------------- 1 | .toggle { 2 | width: 2rem; 3 | height: 2rem; 4 | } 5 | 6 | .toggleButton { 7 | -webkit-tap-highlight-color: transparent; 8 | align-items: center; 9 | display: flex; 10 | justify-content: center; 11 | width: 100%; 12 | height: 100%; 13 | border-radius: 50%; 14 | transition: background var(--ifm-transition-fast); 15 | } 16 | 17 | .toggleButton:hover { 18 | background: var(--ifm-color-emphasis-500); 19 | } 20 | 21 | [data-theme='light'] .darkToggleIcon, 22 | [data-theme='dark'] .lightToggleIcon { 23 | display: none; 24 | } 25 | 26 | .toggleButtonDisabled { 27 | cursor: not-allowed; 28 | } 29 | 30 | .toggleIcon { 31 | color: var(--ifm-navbar-link-color); 32 | } 33 | -------------------------------------------------------------------------------- /test/TooltipSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render, screen } from '@testing-library/react'; 3 | import Tooltip from '../src/Tooltip'; 4 | 5 | describe('Tooltip', () => { 6 | it('Should output a tooltip with content', () => { 7 | render( 8 | 9 | Tooltip Content 10 | , 11 | ); 12 | 13 | const classList = screen.getByTestId('test-tooltip').classList; 14 | expect(classList).toContain('tooltip'); 15 | expect(classList).toContain('bs-tooltip-end'); 16 | 17 | expect( 18 | screen.getByTestId('test-tooltip').getAttribute('x-placement')!, 19 | ).toEqual('right'); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /www/docs/examples/Nav/Basic.js: -------------------------------------------------------------------------------- 1 | import Nav from 'react-bootstrap/Nav'; 2 | 3 | function BasicExample() { 4 | return ( 5 | alert(`selected ${selectedKey}`)} 8 | > 9 | 10 | Active 11 | 12 | 13 | Link 14 | 15 | 16 | Link 17 | 18 | 19 | 20 | Disabled 21 | 22 | 23 | 24 | ); 25 | } 26 | 27 | export default BasicExample; 28 | -------------------------------------------------------------------------------- /www/docs/examples/Alert/AdditionalContent.js: -------------------------------------------------------------------------------- 1 | import Alert from 'react-bootstrap/Alert'; 2 | 3 | function AdditionalContentExample() { 4 | return ( 5 | 6 | Hey, nice to see you 7 | 8 | Aww yeah, you successfully read this important alert message. This 9 | example text is going to run a bit longer so that you can see how 10 | spacing within an alert works with this kind of content. 11 | 12 | 13 | 14 | Whenever you need to, be sure to use margin utilities to keep things 15 | nice and tidy. 16 | 17 | 18 | ); 19 | } 20 | 21 | export default AdditionalContentExample; 22 | -------------------------------------------------------------------------------- /www/src/theme/Admonition/styles.module.css: -------------------------------------------------------------------------------- 1 | .admonition { 2 | margin-bottom: 1em; 3 | } 4 | 5 | .admonitionHeading { 6 | font: var(--ifm-heading-font-weight) var(--ifm-h5-font-size) / 7 | var(--ifm-heading-line-height) var(--ifm-heading-font-family); 8 | text-transform: uppercase; 9 | margin-bottom: 0.3rem; 10 | } 11 | 12 | .admonitionHeading code { 13 | text-transform: none; 14 | } 15 | 16 | .admonitionIcon { 17 | display: inline-block; 18 | vertical-align: middle; 19 | margin-right: 0.4em; 20 | } 21 | 22 | .admonitionIcon svg { 23 | display: inline-block; 24 | height: 1.6em; 25 | width: 1.6em; 26 | /* fill: var(--ifm-alert-foreground-color); */ 27 | } 28 | 29 | .admonitionContent > :last-child { 30 | margin-bottom: 0; 31 | } 32 | -------------------------------------------------------------------------------- /www/docs/examples/Badge/Basic.js: -------------------------------------------------------------------------------- 1 | import Badge from 'react-bootstrap/Badge'; 2 | 3 | function BasicExample() { 4 | return ( 5 | 6 | 7 | Example heading New 8 | 9 | 10 | Example heading New 11 | 12 | 13 | Example heading New 14 | 15 | 16 | Example heading New 17 | 18 | 19 | Example heading New 20 | 21 | 22 | Example heading New 23 | 24 | 25 | ); 26 | } 27 | 28 | export default BasicExample; 29 | -------------------------------------------------------------------------------- /test/getInitialPopperStylesSpec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import getInitialPopperStyles from '../src/getInitialPopperStyles'; 3 | 4 | describe('getInitialPopperStyles', () => { 5 | it('defaults to absolute positioning when no strategy is provided', () => { 6 | expect(getInitialPopperStyles()).toEqual({ 7 | position: 'absolute', 8 | top: '0', 9 | left: '0', 10 | opacity: '0', 11 | pointerEvents: 'none', 12 | }); 13 | }); 14 | 15 | it('sets the position to the provided strategy', () => { 16 | expect(getInitialPopperStyles('fixed')).toEqual({ 17 | position: 'fixed', 18 | top: '0', 19 | left: '0', 20 | opacity: '0', 21 | pointerEvents: 'none', 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /www/docs/examples/InputGroup/MultipleAddons.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | import InputGroup from 'react-bootstrap/InputGroup'; 3 | 4 | function MultipleAddonsExample() { 5 | return ( 6 | <> 7 | 8 | $ 9 | 0.00 10 | 11 | 12 | 13 | 14 | $ 15 | 0.00 16 | 17 | > 18 | ); 19 | } 20 | 21 | export default MultipleAddonsExample; 22 | -------------------------------------------------------------------------------- /www/docs/forms/range.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Range 3 | description: Use our custom range inputs for consistent cross-browser styling and built-in customization. 4 | sidebar_position: 6 5 | --- 6 | 7 | import Range from '!!raw-loader!../examples/Form/Range'; 8 | 9 | ## Overview 10 | 11 | Create custom `` controls with ``. The track 12 | (the background) and thumb (the value) are both styled to appear the same 13 | across browsers. As only Firefox supports “filling” their track from the left 14 | or right of the thumb as a means to visually indicate progress, we do not 15 | currently support it. 16 | 17 | 18 | {Range} 19 | 20 | 21 | ## API 22 | 23 | ### FormRange 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/helpersSpec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { getOverlayDirection } from '../src/helpers'; 3 | 4 | describe('Helpers', () => { 5 | describe('getOverlayDirection', () => { 6 | it('should return start for left', () => { 7 | expect(getOverlayDirection('left', false)).toEqual('start'); 8 | }); 9 | 10 | it('should return end for left in RTL', () => { 11 | expect(getOverlayDirection('left', true)).toEqual('end'); 12 | }); 13 | 14 | it('should return end for right', () => { 15 | expect(getOverlayDirection('right', false)).toEqual('end'); 16 | }); 17 | 18 | it('should return start for right in RTL', () => { 19 | expect(getOverlayDirection('right', true)).toEqual('start'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/SplitBasic.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import ButtonGroup from 'react-bootstrap/ButtonGroup'; 3 | import Dropdown from 'react-bootstrap/Dropdown'; 4 | 5 | function SplitBasicExample() { 6 | return ( 7 | 8 | Split Button 9 | 10 | 11 | 12 | 13 | Action 14 | Another action 15 | Something else 16 | 17 | 18 | ); 19 | } 20 | 21 | export default SplitBasicExample; 22 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormDisabledInputs.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function FormDisabledInputExample() { 4 | return ( 5 | <> 6 | 7 | Disabled input 8 | 9 | 10 | 11 | Disabled select menu 12 | 13 | Disabled select 14 | 15 | 16 | 17 | 18 | 19 | > 20 | ); 21 | } 22 | 23 | export default FormDisabledInputExample; 24 | -------------------------------------------------------------------------------- /www/docs/getting-started/rtl.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RTL 3 | sidebar_position: 6 4 | --- 5 | 6 | import DismissibleControlled from '!!raw-loader!../examples/Alert/DismissibleControlled'; 7 | 8 | We recommend first reading Bootstrap's documentation 9 | to become familiar with how Bootstrap's RTL support works. 10 | 11 | In order to enable RTL support with React-Bootstrap, follow these steps: 12 | 13 | 1. Set `dir="rtl"` on the `` element. 14 | 2. Add an appropriate lang attribute, like `lang="ar"`, on the `` element. 15 | 3. Include the RTL version of the CSS `bootstrap.rtl.min.css` in your project. 16 | 4. Set `dir="rtl"` in a `ThemeProvider`: 17 | 18 | ```jsx 19 | 20 | 21 | 22 | ``` 23 | -------------------------------------------------------------------------------- /www/src/theme/MDXContent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MDXContent from '@theme-original/MDXContent'; 3 | import { useDoc } from '@docusaurus/plugin-content-docs/client'; 4 | import type MDXContentType from '@theme/MDXContent'; 5 | import type { WrapperProps } from '@docusaurus/types'; 6 | import CarbonAds from '../components/CarbonAds'; 7 | 8 | type Props = WrapperProps; 9 | 10 | export default function MDXContentWrapper(props: Props): JSX.Element { 11 | const { frontMatter } = useDoc(); 12 | 13 | return ( 14 | <> 15 | {frontMatter.description && ( 16 | {frontMatter.description} 17 | )} 18 | 19 | 20 | 21 | 22 | > 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormFloatingCustom.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function FormFloatingCustom() { 4 | return ( 5 | <> 6 | 7 | 12 | Email address 13 | 14 | 15 | 20 | Password 21 | 22 | > 23 | ); 24 | } 25 | 26 | export default FormFloatingCustom; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/Offsetting.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function OffsettingExample() { 6 | return ( 7 | 8 | 9 | md=4 10 | {`md={{ span: 4, offset: 4 }}`} 11 | 12 | 13 | {`md={{ span: 3, offset: 3 }}`} 14 | {`md={{ span: 3, offset: 3 }}`} 15 | 16 | 17 | {`md={{ span: 6, offset: 3 }}`} 18 | 19 | 20 | ); 21 | } 22 | 23 | export default OffsettingExample; 24 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/TooltipOverlay.js: -------------------------------------------------------------------------------- 1 | import { useState, useRef } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | import Overlay from 'react-bootstrap/Overlay'; 4 | import Tooltip from 'react-bootstrap/Tooltip'; 5 | 6 | function Example() { 7 | const [show, setShow] = useState(false); 8 | const target = useRef(null); 9 | 10 | return ( 11 | <> 12 | setShow(!show)}> 13 | Click me! 14 | 15 | 16 | {(props) => ( 17 | 18 | My Tooltip 19 | 20 | )} 21 | 22 | > 23 | ); 24 | } 25 | 26 | export default Example; 27 | -------------------------------------------------------------------------------- /www/docs/components/images.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Images 3 | description: Documentation and examples for opting images into responsive behavior (so they never become wider than their parent) and add lightweight styles to them—all via classes. 4 | --- 5 | 6 | import Fluid from '!!raw-loader!../examples/Image/Fluid'; 7 | import Shape from '!!raw-loader!../examples/Image/Shape'; 8 | 9 | ## Shape 10 | 11 | Use the `rounded`, `roundedCircle` and `thumbnail` props to customise 12 | the image. 13 | 14 | 15 | {Shape} 16 | 17 | 18 | ## Fluid 19 | 20 | Use the `fluid` to scale image nicely to the parent element. 21 | 22 | 23 | {Fluid} 24 | 25 | 26 | ## API 27 | 28 | ### Image 29 | 30 | 31 | -------------------------------------------------------------------------------- /www/src/components/PropsTable/defaultPropDescriptions.ts: -------------------------------------------------------------------------------- 1 | const DEFAULT_PROP_DESCRIPTIONS = { 2 | bsPrefix: 3 | 'Change the underlying component CSS base class name and modifier class names prefix. **This is an escape hatch** for working with heavily customized bootstrap css.', 4 | 5 | variant: 'Component visual or contextual style variants.', 6 | 7 | size: 'Component size variations.', 8 | 9 | as: 'You can use a custom element type for this component.', 10 | 11 | eventKey: 12 | 'A unique identifier for the Component, the `eventKey` makes it distinguishable from others in a set. ' + 13 | "Similar to React's `key` prop, in that it only needs to be " + 14 | 'unique amongst the Components siblings, not globally. ', 15 | }; 16 | 17 | export default DEFAULT_PROP_DESCRIPTIONS; 18 | -------------------------------------------------------------------------------- /www/docs/examples/Tabs/Fill.js: -------------------------------------------------------------------------------- 1 | import Tab from 'react-bootstrap/Tab'; 2 | import Tabs from 'react-bootstrap/Tabs'; 3 | 4 | function FillExample() { 5 | return ( 6 | 12 | 13 | Tab content for Home 14 | 15 | 16 | Tab content for Profile 17 | 18 | 19 | Tab content for Loooonger Tab 20 | 21 | 22 | Tab content for Contact 23 | 24 | 25 | ); 26 | } 27 | 28 | export default FillExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormFloatingTextarea.js: -------------------------------------------------------------------------------- 1 | import FloatingLabel from 'react-bootstrap/FloatingLabel'; 2 | import Form from 'react-bootstrap/Form'; 3 | 4 | function FormFloatingTextareaExample() { 5 | return ( 6 | <> 7 | 12 | 13 | 14 | 15 | 20 | 21 | > 22 | ); 23 | } 24 | 25 | export default FormFloatingTextareaExample; 26 | -------------------------------------------------------------------------------- /www/docs/examples/Grid/AutoLayoutVariable.js: -------------------------------------------------------------------------------- 1 | import Container from 'react-bootstrap/Container'; 2 | import Row from 'react-bootstrap/Row'; 3 | import Col from 'react-bootstrap/Col'; 4 | 5 | function AutoLayoutVariableExample() { 6 | return ( 7 | 8 | 9 | 10 | 1 of 3 11 | 12 | Variable width content 13 | 14 | 3 of 3 15 | 16 | 17 | 18 | 1 of 3 19 | Variable width content 20 | 21 | 3 of 3 22 | 23 | 24 | 25 | ); 26 | } 27 | 28 | export default AutoLayoutVariableExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Pagination/Advanced.js: -------------------------------------------------------------------------------- 1 | import Pagination from 'react-bootstrap/Pagination'; 2 | 3 | function AdvancedExample() { 4 | return ( 5 | 6 | 7 | 8 | {1} 9 | 10 | 11 | {10} 12 | {11} 13 | {12} 14 | {13} 15 | {14} 16 | 17 | 18 | {20} 19 | 20 | 21 | 22 | ); 23 | } 24 | 25 | export default AdvancedExample; 26 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Style.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function StyleExample() { 4 | return ( 5 | 6 | No style 7 | Primary 8 | Secondary 9 | Success 10 | Danger 11 | Warning 12 | Info 13 | Light 14 | Dark 15 | 16 | ); 17 | } 18 | 19 | export default StyleExample; 20 | -------------------------------------------------------------------------------- /www/docs/examples/Modal/Static.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Modal from 'react-bootstrap/Modal'; 3 | 4 | function StaticExample() { 5 | return ( 6 | 10 | 11 | 12 | Modal title 13 | 14 | 15 | 16 | Modal body text goes here. 17 | 18 | 19 | 20 | Close 21 | Save changes 22 | 23 | 24 | 25 | ); 26 | } 27 | 28 | export default StaticExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Tabs/Controlled.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Tab from 'react-bootstrap/Tab'; 3 | import Tabs from 'react-bootstrap/Tabs'; 4 | 5 | function ControlledTabsExample() { 6 | const [key, setKey] = useState('home'); 7 | 8 | return ( 9 | setKey(k)} 13 | className="mb-3" 14 | > 15 | 16 | Tab content for Home 17 | 18 | 19 | Tab content for Profile 20 | 21 | 22 | Tab content for Contact 23 | 24 | 25 | ); 26 | } 27 | 28 | export default ControlledTabsExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/ButtonGroup/Sizes.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import ButtonGroup from 'react-bootstrap/ButtonGroup'; 3 | 4 | function SizesExample() { 5 | return ( 6 | <> 7 | 8 | Left 9 | Middle 10 | Right 11 | 12 | 13 | 14 | Left 15 | Middle 16 | Right 17 | 18 | 19 | 20 | Left 21 | Middle 22 | Right 23 | 24 | > 25 | ); 26 | } 27 | 28 | export default SizesExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Tabs/Justified.js: -------------------------------------------------------------------------------- 1 | import Tab from 'react-bootstrap/Tab'; 2 | import Tabs from 'react-bootstrap/Tabs'; 3 | 4 | function JustifiedExample() { 5 | return ( 6 | 12 | 13 | Tab content for Home 14 | 15 | 16 | Tab content for Profile 17 | 18 | 19 | Tab content for Loooonger Tab 20 | 21 | 22 | Tab content for Contact 23 | 24 | 25 | ); 26 | } 27 | 28 | export default JustifiedExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/TooltipPositioned.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; 3 | import Tooltip from 'react-bootstrap/Tooltip'; 4 | 5 | function TooltipPositionedExample() { 6 | return ( 7 | <> 8 | {['top', 'right', 'bottom', 'left'].map((placement) => ( 9 | 14 | Tooltip on {placement}. 15 | 16 | } 17 | > 18 | Tooltip on {placement} 19 | 20 | ))} 21 | > 22 | ); 23 | } 24 | 25 | export default TooltipPositionedExample; 26 | -------------------------------------------------------------------------------- /www/docs/examples/Spinner/Buttons.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Spinner from 'react-bootstrap/Spinner'; 3 | 4 | function ButtonExample() { 5 | return ( 6 | <> 7 | 8 | 15 | Loading... 16 | 17 | 18 | 25 | Loading... 26 | 27 | > 28 | ); 29 | } 30 | 31 | export default ButtonExample; 32 | -------------------------------------------------------------------------------- /www/plugins/react-resolver-plugin.js: -------------------------------------------------------------------------------- 1 | // This ensures we only load a single copy of React from the Docusaurus node_modules 2 | // directory. Without this, importing aliased modules from another directory with React 3 | // installed would result in the "Invalid Hooks" error due to multiple copies of React 4 | // being used. 5 | module.exports = () => ({ 6 | name: 'react-resolver-plugin', 7 | configureWebpack() { 8 | return { 9 | resolve: { 10 | alias: { 11 | react$: require.resolve('react'), 12 | 'react/jsx-runtime': require.resolve('react/jsx-runtime'), 13 | 'react/jsx-dev-runtime': require.resolve('react/jsx-dev-runtime'), 14 | 'react-dom$': require.resolve('react-dom'), 15 | 'react-dom/server': require.resolve('react-dom/server'), 16 | }, 17 | }, 18 | }; 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /www/docs/examples/Fade.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | import Fade from 'react-bootstrap/Fade'; 4 | 5 | function Example() { 6 | const [open, setOpen] = useState(false); 7 | 8 | return ( 9 | <> 10 | setOpen(!open)} 12 | aria-controls="example-fade-text" 13 | aria-expanded={open} 14 | > 15 | Toggle text 16 | 17 | 18 | 19 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus 20 | terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer 21 | labore wes anderson cred nesciunt sapiente ea proident. 22 | 23 | 24 | > 25 | ); 26 | } 27 | 28 | export default Example; 29 | -------------------------------------------------------------------------------- /src/AccordionContext.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export type AccordionEventKey = string | string[] | null | undefined; 4 | 5 | export declare type AccordionSelectCallback = ( 6 | eventKey: AccordionEventKey, 7 | e: React.SyntheticEvent, 8 | ) => void; 9 | 10 | export interface AccordionContextValue { 11 | activeEventKey?: AccordionEventKey; 12 | onSelect?: AccordionSelectCallback; 13 | alwaysOpen?: boolean; 14 | } 15 | 16 | export function isAccordionItemSelected( 17 | activeEventKey: AccordionEventKey, 18 | eventKey: string, 19 | ): boolean { 20 | return Array.isArray(activeEventKey) 21 | ? activeEventKey.includes(eventKey) 22 | : activeEventKey === eventKey; 23 | } 24 | 25 | const context = React.createContext({}); 26 | context.displayName = 'AccordionContext'; 27 | 28 | export default context; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Alert/Dismissible.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Alert from 'react-bootstrap/Alert'; 3 | import Button from 'react-bootstrap/Button'; 4 | 5 | function AlertDismissibleExample() { 6 | const [show, setShow] = useState(true); 7 | 8 | if (show) { 9 | return ( 10 | setShow(false)} dismissible> 11 | Oh snap! You got an error! 12 | 13 | Change this and that and try again. Duis mollis, est non commodo 14 | luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. 15 | Cras mattis consectetur purus sit amet fermentum. 16 | 17 | 18 | ); 19 | } 20 | return setShow(true)}>Show Alert; 21 | } 22 | 23 | export default AlertDismissibleExample; 24 | -------------------------------------------------------------------------------- /www/docs/examples/Button/Loading.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | 4 | function LoadingButton() { 5 | const [isLoading, setLoading] = useState(false); 6 | 7 | useEffect(() => { 8 | function simulateNetworkRequest() { 9 | return new Promise((resolve) => setTimeout(resolve, 2000)); 10 | } 11 | 12 | if (isLoading) { 13 | simulateNetworkRequest().then(() => { 14 | setLoading(false); 15 | }); 16 | } 17 | }, [isLoading]); 18 | 19 | const handleClick = () => setLoading(true); 20 | 21 | return ( 22 | 27 | {isLoading ? 'Loading…' : 'Click to load'} 28 | 29 | ); 30 | } 31 | 32 | export default LoadingButton; 33 | -------------------------------------------------------------------------------- /src/transitionEndListener.ts: -------------------------------------------------------------------------------- 1 | import css from 'dom-helpers/css'; 2 | import transitionEnd from 'dom-helpers/transitionEnd'; 3 | 4 | function parseDuration( 5 | node: HTMLElement, 6 | property: 'transitionDuration' | 'transitionDelay', 7 | ) { 8 | const str = css(node, property) || ''; 9 | const mult = str.indexOf('ms') === -1 ? 1000 : 1; 10 | return parseFloat(str) * mult; 11 | } 12 | 13 | export default function transitionEndListener( 14 | element: HTMLElement, 15 | handler: (e: TransitionEvent) => void, 16 | ) { 17 | const duration = parseDuration(element, 'transitionDuration'); 18 | const delay = parseDuration(element, 'transitionDelay'); 19 | const remove = transitionEnd( 20 | element, 21 | (e) => { 22 | if (e.target === element) { 23 | remove(); 24 | handler(e); 25 | } 26 | }, 27 | duration + delay, 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /www/docs/examples/Collapse.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | import Collapse from 'react-bootstrap/Collapse'; 4 | 5 | function Example() { 6 | const [open, setOpen] = useState(false); 7 | 8 | return ( 9 | <> 10 | setOpen(!open)} 12 | aria-controls="example-collapse-text" 13 | aria-expanded={open} 14 | > 15 | click 16 | 17 | 18 | 19 | Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus 20 | terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer 21 | labore wes anderson cred nesciunt sapiente ea proident. 22 | 23 | 24 | > 25 | ); 26 | } 27 | 28 | export default Example; 29 | -------------------------------------------------------------------------------- /www/src/components/CarbonAds.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { useEffect, useRef } from 'react'; 3 | 4 | const CarbonAds = (props) => { 5 | const ref = useRef(); 6 | 7 | useEffect(() => { 8 | if (typeof document !== 'undefined') { 9 | const script = document.createElement('script'); 10 | script.async = true; 11 | script.id = '_carbonads_js'; 12 | script.type = 'text/javascript'; 13 | script.src = 14 | '//cdn.carbonads.com/carbon.js?serve=CE7IP2QY&placement=react-bootstrapgithubio'; 15 | 16 | ref.current.appendChild(script); 17 | } 18 | 19 | return () => { 20 | while (ref.current?.firstChild) { 21 | ref.current.removeChild(ref.current.firstChild); 22 | } 23 | }; 24 | }, []); 25 | 26 | return ; 27 | }; 28 | 29 | export default CarbonAds; 30 | -------------------------------------------------------------------------------- /src/createChainedFunction.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Safe chained function 3 | * 4 | * Will only create a new function if needed, 5 | * otherwise will pass back existing functions or null. 6 | * 7 | * @param {function} functions to chain 8 | * @returns {function|null} 9 | */ 10 | function createChainedFunction(...funcs) { 11 | return funcs 12 | .filter((f) => f != null) 13 | .reduce((acc, f) => { 14 | if (typeof f !== 'function') { 15 | throw new Error( 16 | 'Invalid Argument Type, must only provide functions, undefined, or null.', 17 | ); 18 | } 19 | 20 | if (acc === null) return f; 21 | 22 | return function chainedFunction(...args) { 23 | // @ts-ignore 24 | acc.apply(this, args); 25 | // @ts-ignore 26 | f.apply(this, args); 27 | }; 28 | }, null); 29 | } 30 | 31 | export default createChainedFunction; 32 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { coverageConfigDefaults, defineConfig } from 'vitest/config'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | export default defineConfig({ 5 | define: { 6 | // eslint-disable-next-line @typescript-eslint/naming-convention 7 | __DEV__: true, 8 | }, 9 | plugins: [react()], 10 | test: { 11 | include: ['test/**/*Spec.ts', 'test/**/*Spec.tsx'], 12 | setupFiles: ['vitest.setup.ts'], 13 | browser: { 14 | enabled: true, 15 | name: 'chromium', 16 | provider: 'playwright', 17 | providerOptions: { 18 | context: { 19 | hasTouch: true, 20 | }, 21 | }, 22 | }, 23 | coverage: { 24 | provider: 'istanbul', 25 | exclude: [ 26 | ...coverageConfigDefaults.exclude, 27 | 'www/**', 28 | 'tools/**', 29 | '**/*.js', 30 | ], 31 | }, 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /src/NavItem.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface NavItemProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const NavItem: BsPrefixRefForwardingComponent<'div', NavItemProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'nav-item'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof NavItem; 23 | 24 | NavItem.displayName = 'NavItem'; 25 | 26 | export default NavItem; 27 | -------------------------------------------------------------------------------- /test/PlaceholderButtonSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render } from '@testing-library/react'; 3 | import PlaceholderButton from '../src/PlaceholderButton'; 4 | 5 | describe('', () => { 6 | it('should render a placeholder', () => { 7 | const { container } = render(); 8 | expect(container.firstElementChild!.className).toContain('placeholder'); 9 | }); 10 | 11 | it('should render size', () => { 12 | const { container } = render(); 13 | expect(container.firstElementChild!.className).toContain('placeholder-lg'); 14 | }); 15 | 16 | it('should render animation', () => { 17 | const { container } = render(); 18 | expect(container.firstElementChild!.className).toContain( 19 | 'placeholder-glow', 20 | ); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /www/docs/examples/Card/ImageAndText.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function ImageAndTextExample() { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | 10 | Some quick example text to build on the card title and make up the 11 | bulk of the card's content. 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Some quick example text to build on the card title and make up the 20 | bulk of the card's content. 21 | 22 | 23 | 24 | 25 | > 26 | ); 27 | } 28 | 29 | export default ImageAndTextExample; 30 | -------------------------------------------------------------------------------- /www/docs/examples/Badge/Pill.js: -------------------------------------------------------------------------------- 1 | import Badge from 'react-bootstrap/Badge'; 2 | import Stack from 'react-bootstrap/Stack'; 3 | 4 | function PillExample() { 5 | return ( 6 | 7 | 8 | Primary 9 | 10 | 11 | Secondary 12 | 13 | 14 | Success 15 | 16 | 17 | Danger 18 | 19 | 20 | Warning 21 | 22 | 23 | Info 24 | 25 | 26 | Light 27 | 28 | 29 | Dark 30 | 31 | 32 | ); 33 | } 34 | 35 | export default PillExample; 36 | -------------------------------------------------------------------------------- /www/docs/examples/Card/Grid.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | import Col from 'react-bootstrap/Col'; 3 | import Row from 'react-bootstrap/Row'; 4 | 5 | function GridExample() { 6 | return ( 7 | 8 | {Array.from({ length: 4 }).map((_, idx) => ( 9 | 10 | 11 | 12 | 13 | Card title 14 | 15 | This is a longer card with supporting text below as a natural 16 | lead-in to additional content. This content is a little bit 17 | longer. 18 | 19 | 20 | 21 | 22 | ))} 23 | 24 | ); 25 | } 26 | 27 | export default GridExample; 28 | -------------------------------------------------------------------------------- /src/CardBody.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CardBodyProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const CardBody: BsPrefixRefForwardingComponent<'div', CardBodyProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-body'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof CardBody; 23 | 24 | CardBody.displayName = 'CardBody'; 25 | 26 | export default CardBody; 27 | -------------------------------------------------------------------------------- /src/CardText.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CardTextProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const CardText: BsPrefixRefForwardingComponent<'p', CardTextProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'p', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-text'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof CardText; 23 | 24 | CardText.displayName = 'CardText'; 25 | 26 | export default CardText; 27 | -------------------------------------------------------------------------------- /src/CardLink.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CardLinkProps 7 | extends BsPrefixProps, 8 | React.AnchorHTMLAttributes {} 9 | 10 | const CardLink: BsPrefixRefForwardingComponent<'a', CardLinkProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'a', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-link'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof CardLink; 23 | 24 | CardLink.displayName = 'CardLink'; 25 | 26 | export default CardLink; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Table/Basic.js: -------------------------------------------------------------------------------- 1 | import Table from 'react-bootstrap/Table'; 2 | 3 | function BasicExample() { 4 | return ( 5 | 6 | 7 | 8 | # 9 | First Name 10 | Last Name 11 | Username 12 | 13 | 14 | 15 | 16 | 1 17 | Mark 18 | Otto 19 | @mdo 20 | 21 | 22 | 2 23 | Jacob 24 | Thornton 25 | @fat 26 | 27 | 28 | 3 29 | Larry the Bird 30 | @twitter 31 | 32 | 33 | 34 | ); 35 | } 36 | 37 | export default BasicExample; 38 | -------------------------------------------------------------------------------- /www/docs/examples/Table/StripedRow.js: -------------------------------------------------------------------------------- 1 | import Table from 'react-bootstrap/Table'; 2 | 3 | function StripedRowExample() { 4 | return ( 5 | 6 | 7 | 8 | # 9 | First Name 10 | Last Name 11 | Username 12 | 13 | 14 | 15 | 16 | 1 17 | Mark 18 | Otto 19 | @mdo 20 | 21 | 22 | 2 23 | Jacob 24 | Thornton 25 | @fat 26 | 27 | 28 | 3 29 | Larry the Bird 30 | @twitter 31 | 32 | 33 | 34 | ); 35 | } 36 | 37 | export default StripedRowExample; 38 | -------------------------------------------------------------------------------- /src/CardGroup.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CardGroupProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const CardGroup: BsPrefixRefForwardingComponent<'div', CardGroupProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-group'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof CardGroup; 23 | 24 | CardGroup.displayName = 'CardGroup'; 25 | 26 | export default CardGroup; 27 | -------------------------------------------------------------------------------- /src/ModalBody.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface ModalBodyProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const ModalBody: BsPrefixRefForwardingComponent<'div', ModalBodyProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'modal-body'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof ModalBody; 23 | 24 | ModalBody.displayName = 'ModalBody'; 25 | 26 | export default ModalBody; 27 | -------------------------------------------------------------------------------- /src/ToastBody.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface ToastBodyProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const ToastBody: BsPrefixRefForwardingComponent<'div', ToastBodyProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'toast-body'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof ToastBody; 23 | 24 | ToastBody.displayName = 'ToastBody'; 25 | 26 | export default ToastBody; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Offcanvas/StaticBackdrop.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | import Offcanvas from 'react-bootstrap/Offcanvas'; 4 | 5 | function Example() { 6 | const [show, setShow] = useState(false); 7 | 8 | const handleClose = () => setShow(false); 9 | const handleShow = () => setShow(true); 10 | 11 | return ( 12 | <> 13 | 14 | Toggle static offcanvas 15 | 16 | 17 | 18 | 19 | Offcanvas 20 | 21 | 22 | I will not close if you click outside of me. 23 | 24 | 25 | > 26 | ); 27 | } 28 | 29 | export default Example; 30 | -------------------------------------------------------------------------------- /www/docs/components/pagination.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Pagination 3 | description: A set of presentational components for building pagination UI. 4 | --- 5 | 6 | import PaginationAdvanced from '!!raw-loader!../examples/Pagination/Advanced'; 7 | import PaginationBasic from '!!raw-loader!../examples/Pagination/Basic'; 8 | 9 | ## Example 10 | 11 | 12 | {PaginationBasic} 13 | 14 | 15 | ## More options 16 | 17 | For building more complex pagination UI, there are few convenient 18 | sub-components for adding "First", "Previous", "Next", and "Last" 19 | buttons, as well as an "Ellipsis" item for indicating 20 | previous or continuing results. 21 | 22 | 23 | {PaginationAdvanced} 24 | 25 | 26 | ## API 27 | 28 | ### Pagination 29 | 30 | 31 | 32 | ### PageItem 33 | 34 | 35 | -------------------------------------------------------------------------------- /www/docs/examples/ButtonGroup/ToolbarBasic.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import ButtonGroup from 'react-bootstrap/ButtonGroup'; 3 | import ButtonToolbar from 'react-bootstrap/ButtonToolbar'; 4 | 5 | function ToolbarBasicExample() { 6 | return ( 7 | 8 | 9 | 1 10 | 2 11 | 3 12 | 4 13 | 14 | 15 | 5 16 | 6 17 | 7 18 | 19 | 20 | 8 21 | 22 | 23 | ); 24 | } 25 | 26 | export default ToolbarBasicExample; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Table/Dark.js: -------------------------------------------------------------------------------- 1 | import Table from 'react-bootstrap/Table'; 2 | 3 | function DarkExample() { 4 | return ( 5 | 6 | 7 | 8 | # 9 | First Name 10 | Last Name 11 | Username 12 | 13 | 14 | 15 | 16 | 1 17 | Mark 18 | Otto 19 | @mdo 20 | 21 | 22 | 2 23 | Jacob 24 | Thornton 25 | @fat 26 | 27 | 28 | 3 29 | Larry the Bird 30 | @twitter 31 | 32 | 33 | 34 | ); 35 | } 36 | 37 | export default DarkExample; 38 | -------------------------------------------------------------------------------- /www/docs/examples/Table/Small.js: -------------------------------------------------------------------------------- 1 | import Table from 'react-bootstrap/Table'; 2 | 3 | function SmallExample() { 4 | return ( 5 | 6 | 7 | 8 | # 9 | First Name 10 | Last Name 11 | Username 12 | 13 | 14 | 15 | 16 | 1 17 | Mark 18 | Otto 19 | @mdo 20 | 21 | 22 | 2 23 | Jacob 24 | Thornton 25 | @fat 26 | 27 | 28 | 3 29 | Larry the Bird 30 | @twitter 31 | 32 | 33 | 34 | ); 35 | } 36 | 37 | export default SmallExample; 38 | -------------------------------------------------------------------------------- /www/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | sidebar: [{ type: 'autogenerated', dirName: '.' }], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | 'intro', 23 | 'hello', 24 | { 25 | type: 'category', 26 | label: 'Tutorial', 27 | items: ['tutorial-basics/create-a-document'], 28 | }, 29 | ], 30 | */ 31 | }; 32 | 33 | module.exports = sidebars; 34 | -------------------------------------------------------------------------------- /src/CardFooter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CardFooterProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const CardFooter: BsPrefixRefForwardingComponent<'div', CardFooterProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-footer'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof CardFooter; 23 | 24 | CardFooter.displayName = 'CardFooter'; 25 | 26 | export default CardFooter; 27 | -------------------------------------------------------------------------------- /src/TabContent.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface TabContentProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const TabContent: BsPrefixRefForwardingComponent<'div', TabContentProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'tab-content'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof TabContent; 23 | 24 | TabContent.displayName = 'TabContent'; 25 | 26 | export default TabContent; 27 | -------------------------------------------------------------------------------- /src/NavbarText.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface NavbarTextProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const NavbarText: BsPrefixRefForwardingComponent<'span', NavbarTextProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'span', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'navbar-text'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof NavbarText; 23 | 24 | NavbarText.displayName = 'NavbarText'; 25 | 26 | export default NavbarText; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Table/StripedColumns.js: -------------------------------------------------------------------------------- 1 | import Table from 'react-bootstrap/Table'; 2 | 3 | function StripedColumnsExample() { 4 | return ( 5 | 6 | 7 | 8 | # 9 | First Name 10 | Last Name 11 | Username 12 | 13 | 14 | 15 | 16 | 1 17 | Mark 18 | Otto 19 | @mdo 20 | 21 | 22 | 2 23 | Jacob 24 | Thornton 25 | @fat 26 | 27 | 28 | 3 29 | Larry the Bird 30 | @twitter 31 | 32 | 33 | 34 | ); 35 | } 36 | 37 | export default StripedColumnsExample; 38 | -------------------------------------------------------------------------------- /src/ModalFooter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface ModalFooterProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const ModalFooter: BsPrefixRefForwardingComponent<'div', ModalFooterProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'modal-footer'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof ModalFooter; 23 | 24 | ModalFooter.displayName = 'ModalFooter'; 25 | 26 | export default ModalFooter; 27 | -------------------------------------------------------------------------------- /src/PopoverBody.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface PopoverBodyProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const PopoverBody: BsPrefixRefForwardingComponent<'div', PopoverBodyProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'popover-body'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof PopoverBody; 23 | 24 | PopoverBody.displayName = 'PopoverBody'; 25 | 26 | export default PopoverBody; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Form/Plaintext.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import Form from 'react-bootstrap/Form'; 3 | import Row from 'react-bootstrap/Row'; 4 | 5 | function PlaintextExample() { 6 | return ( 7 | 8 | 9 | 10 | Email 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Password 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | } 28 | 29 | export default PlaintextExample; 30 | -------------------------------------------------------------------------------- /www/src/components/ExampleCarouselImage.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface ExampleCarouselImageProps { 4 | title?: string | undefined; 5 | text: string; 6 | } 7 | 8 | const ExampleCarouselImage: React.FC = ({ 9 | title = 'Placeholder', 10 | text, 11 | }) => ( 12 | 22 | {title} 23 | 24 | 25 | {text} 26 | 27 | 28 | ); 29 | 30 | ExampleCarouselImage.displayName = 'ExampleCarouselImage'; 31 | 32 | export default ExampleCarouselImage; 33 | -------------------------------------------------------------------------------- /test/ButtonToolbarSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render, screen } from '@testing-library/react'; 3 | 4 | import Button from '../src/Button'; 5 | import ButtonToolbar from '../src/ButtonToolbar'; 6 | 7 | describe('ButtonToolbar', () => { 8 | it('Should output a button toolbar', () => { 9 | render( 10 | 11 | Title 12 | , 13 | ); 14 | 15 | expect(screen.getByRole('toolbar').classList).toContain('btn-toolbar'); 16 | }); 17 | 18 | it('Should allow a custom prefix', () => { 19 | render( 20 | 21 | Title 22 | , 23 | ); 24 | 25 | const toolbar = screen.getByRole('toolbar'); 26 | expect(toolbar.classList).toContain('my-custom-toolbar'); 27 | expect(toolbar.classList).not.toContain('btn-toolbar'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/NavbarBrandSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render, screen } from '@testing-library/react'; 3 | import NavbarBrand from '../src/NavbarBrand'; 4 | 5 | describe('', () => { 6 | it('Should create NavbarBrand SPAN element', () => { 7 | render(Brand); 8 | const navbarBrandElem = screen.getByTestId('test'); 9 | expect(navbarBrandElem.tagName).toEqual('SPAN'); 10 | expect(navbarBrandElem.classList).toContain('navbar-brand'); 11 | }); 12 | 13 | it('Should create NavbarBrand A (link) element', () => { 14 | render( 15 | 16 | BrandLink 17 | , 18 | ); 19 | const navbarBrandElem = screen.getByTestId('test'); 20 | expect(navbarBrandElem.tagName).toEqual('A'); 21 | expect(navbarBrandElem.classList).toContain('navbar-brand'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/TriggerRenderProp.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Image from 'react-bootstrap/Image'; 3 | import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; 4 | 5 | function TriggerRendererProp() { 6 | return ( 7 | Check out this avatar} 10 | > 11 | {({ ref, ...triggerHandler }) => ( 12 | 17 | 22 | Hover to see 23 | 24 | )} 25 | 26 | ); 27 | } 28 | 29 | export default TriggerRendererProp; 30 | -------------------------------------------------------------------------------- /www/docs/getting-started/support.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting help 3 | description: Stay up to date on the development of React-Bootstrap and reach out to the community with these helpful resources. 4 | sidebar_position: 5 5 | --- 6 | 7 | ## Stack Overflow 8 | 9 | [Ask questions][0] about specific problems you have faced, including details about what exactly 10 | you are trying to do. Make sure you tag your question with 11 | `react-bootstrap`. You can also read through [existing React-Bootstrap questions][1]. 12 | 13 | ## GitHub issues 14 | 15 | The issue tracker is the preferred channel for bug reports, features 16 | requests and submitting pull requests. See more about how we use issues 17 | in the [contribution guidelines][2]. 18 | 19 | [0]: http://stackoverflow.com/questions/ask 20 | [1]: http://stackoverflow.com/questions/tagged/react-bootstrap 21 | [2]: https://github.com/react-bootstrap/react-bootstrap/blob/master/CONTRIBUTING.md#issues 22 | -------------------------------------------------------------------------------- /src/FormFloating.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface FormFloatingProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const FormFloating: BsPrefixRefForwardingComponent<'div', FormFloatingProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'form-floating'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof FormFloating; 23 | 24 | FormFloating.displayName = 'FormFloating'; 25 | 26 | export default FormFloating; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Form/CheckInline.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function CheckInlineExample() { 4 | return ( 5 | 6 | {['checkbox', 'radio'].map((type) => ( 7 | 8 | 15 | 22 | 29 | 30 | ))} 31 | 32 | ); 33 | } 34 | 35 | export default CheckInlineExample; 36 | -------------------------------------------------------------------------------- /src/OffcanvasBody.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface OffcanvasBodyProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const OffcanvasBody: BsPrefixRefForwardingComponent<'div', OffcanvasBodyProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'offcanvas-body'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof OffcanvasBody; 23 | 24 | OffcanvasBody.displayName = 'OffcanvasBody'; 25 | 26 | export default OffcanvasBody; 27 | -------------------------------------------------------------------------------- /src/PopoverHeader.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface PopoverHeaderProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const PopoverHeader: BsPrefixRefForwardingComponent<'div', PopoverHeaderProps> = 11 | React.forwardRef( 12 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 13 | bsPrefix = useBootstrapPrefix(bsPrefix, 'popover-header'); 14 | return ( 15 | 20 | ); 21 | }, 22 | ) as typeof PopoverHeader; 23 | 24 | PopoverHeader.displayName = 'PopoverHeader'; 25 | 26 | export default PopoverHeader; 27 | -------------------------------------------------------------------------------- /www/docs/examples/Form/CheckReverse.js: -------------------------------------------------------------------------------- 1 | import Form from 'react-bootstrap/Form'; 2 | 3 | function CheckReverseExample() { 4 | return ( 5 | 6 | {['checkbox', 'radio'].map((type) => ( 7 | 8 | 15 | 22 | 29 | 30 | ))} 31 | 32 | ); 33 | } 34 | 35 | export default CheckReverseExample; 36 | -------------------------------------------------------------------------------- /www/docs/examples/Offcanvas/Basic.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | import Offcanvas from 'react-bootstrap/Offcanvas'; 4 | 5 | function Example() { 6 | const [show, setShow] = useState(false); 7 | 8 | const handleClose = () => setShow(false); 9 | const handleShow = () => setShow(true); 10 | 11 | return ( 12 | <> 13 | 14 | Launch 15 | 16 | 17 | 18 | 19 | Offcanvas 20 | 21 | 22 | Some text as placeholder. In real life you can have the elements you 23 | have chosen. Like, text, images, lists, etc. 24 | 25 | 26 | > 27 | ); 28 | } 29 | 30 | export default Example; 31 | -------------------------------------------------------------------------------- /src/CardImgOverlay.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CardImgOverlayProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const CardImgOverlay: BsPrefixRefForwardingComponent< 11 | 'div', 12 | CardImgOverlayProps 13 | > = React.forwardRef( 14 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 15 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-img-overlay'); 16 | return ( 17 | 22 | ); 23 | }, 24 | ) as typeof CardImgOverlay; 25 | 26 | CardImgOverlay.displayName = 'CardImgOverlay'; 27 | 28 | export default CardImgOverlay; 29 | -------------------------------------------------------------------------------- /src/InputGroupText.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface InputGroupTextProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const InputGroupText: BsPrefixRefForwardingComponent< 11 | 'span', 12 | InputGroupTextProps 13 | > = React.forwardRef( 14 | ({ className, bsPrefix, as: Component = 'span', ...props }, ref) => { 15 | bsPrefix = useBootstrapPrefix(bsPrefix, 'input-group-text'); 16 | return ( 17 | 22 | ); 23 | }, 24 | ) as typeof InputGroupText; 25 | 26 | InputGroupText.displayName = 'InputGroupText'; 27 | 28 | export default InputGroupText; 29 | -------------------------------------------------------------------------------- /src/FigureCaption.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface FigureCaptionProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const FigureCaption: BsPrefixRefForwardingComponent< 11 | 'figcaption', 12 | FigureCaptionProps 13 | > = React.forwardRef( 14 | ({ className, bsPrefix, as: Component = 'figcaption', ...props }, ref) => { 15 | bsPrefix = useBootstrapPrefix(bsPrefix, 'figure-caption'); 16 | return ( 17 | 22 | ); 23 | }, 24 | ) as typeof FigureCaption; 25 | 26 | FigureCaption.displayName = 'FigureCaption'; 27 | 28 | export default FigureCaption; 29 | -------------------------------------------------------------------------------- /src/useWrappedRefWithWarning.tsx: -------------------------------------------------------------------------------- 1 | import invariant from 'invariant'; 2 | import { useCallback } from 'react'; 3 | import useMergedRefs from '@restart/hooks/useMergedRefs'; 4 | 5 | export default function useWrappedRefWithWarning(ref, componentName) { 6 | // @ts-ignore 7 | if (!__DEV__) return ref; 8 | 9 | // eslint-disable-next-line react-hooks/rules-of-hooks 10 | const warningRef = useCallback( 11 | (refValue) => { 12 | invariant( 13 | refValue == null || !refValue.isReactComponent, 14 | `${componentName} injected a ref to a provided \`as\` component that resolved to a component instance instead of a DOM element. ` + 15 | 'Use `React.forwardRef` to provide the injected ref to the class component as a prop in order to pass it directly to a DOM element', 16 | ); 17 | }, 18 | [componentName], 19 | ); 20 | // eslint-disable-next-line react-hooks/rules-of-hooks 21 | return useMergedRefs(warningRef, ref); 22 | } 23 | -------------------------------------------------------------------------------- /src/AlertLink.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import Anchor from '@restart/ui/Anchor'; 4 | import { useBootstrapPrefix } from './ThemeProvider'; 5 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 6 | 7 | export interface AlertLinkProps 8 | extends BsPrefixProps, 9 | React.AnchorHTMLAttributes {} 10 | 11 | const AlertLink: BsPrefixRefForwardingComponent<'a', AlertLinkProps> = 12 | React.forwardRef( 13 | ({ className, bsPrefix, as: Component = Anchor, ...props }, ref) => { 14 | bsPrefix = useBootstrapPrefix(bsPrefix, 'alert-link'); 15 | return ( 16 | 21 | ); 22 | }, 23 | ) as typeof AlertLink; 24 | 25 | AlertLink.displayName = 'AlertLink'; 26 | 27 | export default AlertLink; 28 | -------------------------------------------------------------------------------- /src/CarouselCaption.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface CarouselCaptionProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const CarouselCaption: BsPrefixRefForwardingComponent< 11 | 'div', 12 | CarouselCaptionProps 13 | > = React.forwardRef( 14 | ({ className, bsPrefix, as: Component = 'div', ...props }, ref) => { 15 | bsPrefix = useBootstrapPrefix(bsPrefix, 'carousel-caption'); 16 | return ( 17 | 22 | ); 23 | }, 24 | ) as typeof CarouselCaption; 25 | 26 | CarouselCaption.displayName = 'CarouselCaption'; 27 | 28 | export default CarouselCaption; 29 | -------------------------------------------------------------------------------- /src/DropdownItemText.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface DropdownItemTextProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const DropdownItemText: BsPrefixRefForwardingComponent< 11 | 'span', 12 | DropdownItemTextProps 13 | > = React.forwardRef( 14 | ({ className, bsPrefix, as: Component = 'span', ...props }, ref) => { 15 | bsPrefix = useBootstrapPrefix(bsPrefix, 'dropdown-item-text'); 16 | return ( 17 | 22 | ); 23 | }, 24 | ) as typeof DropdownItemText; 25 | 26 | DropdownItemText.displayName = 'DropdownItemText'; 27 | 28 | export default DropdownItemText; 29 | -------------------------------------------------------------------------------- /src/NavbarOffcanvas.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { useContext } from 'react'; 3 | import useEventCallback from '@restart/hooks/useEventCallback'; 4 | import Offcanvas, { OffcanvasProps } from './Offcanvas'; 5 | import NavbarContext from './NavbarContext'; 6 | 7 | export type NavbarOffcanvasProps = Omit; 8 | 9 | const NavbarOffcanvas = React.forwardRef( 10 | ({ onHide, ...props }, ref) => { 11 | const context = useContext(NavbarContext); 12 | 13 | const handleHide = useEventCallback(() => { 14 | context?.onToggle?.(); 15 | onHide?.(); 16 | }); 17 | 18 | return ( 19 | 26 | ); 27 | }, 28 | ); 29 | 30 | NavbarOffcanvas.displayName = 'NavbarOffcanvas'; 31 | 32 | export default NavbarOffcanvas; 33 | -------------------------------------------------------------------------------- /test/StackSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render } from '@testing-library/react'; 3 | import Stack from '../src/Stack'; 4 | 5 | describe('', () => { 6 | it('should render a vertical stack by default', () => { 7 | const { container } = render(); 8 | expect(container.firstElementChild!.className).toContain('vstack'); 9 | }); 10 | 11 | it('should render direction', () => { 12 | const { container } = render(); 13 | expect(container.firstElementChild!.className).toContain('hstack'); 14 | }); 15 | 16 | it('should render gap', () => { 17 | const { container } = render(); 18 | expect(container.firstElementChild!.classList).toContain('gap-2'); 19 | }); 20 | 21 | it('should render responsive gap', () => { 22 | const { container } = render(); 23 | expect(container.firstElementChild!.classList).toContain('gap-md-2'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/usePlaceholder.ts: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import { useBootstrapPrefix } from './ThemeProvider'; 3 | import { useCol, ColProps } from './Col'; 4 | import { Variant } from './types'; 5 | 6 | export type PlaceholderAnimation = 'glow' | 'wave'; 7 | export type PlaceholderSize = 'xs' | 'sm' | 'lg'; 8 | 9 | export interface UsePlaceholderProps extends Omit { 10 | animation?: PlaceholderAnimation; 11 | bg?: Variant; 12 | size?: PlaceholderSize; 13 | } 14 | 15 | export default function usePlaceholder({ 16 | animation, 17 | bg, 18 | bsPrefix, 19 | size, 20 | ...props 21 | }: UsePlaceholderProps) { 22 | bsPrefix = useBootstrapPrefix(bsPrefix, 'placeholder'); 23 | const [{ className, ...colProps }] = useCol(props); 24 | 25 | return { 26 | ...colProps, 27 | className: classNames( 28 | className, 29 | animation ? `${bsPrefix}-${animation}` : bsPrefix, 30 | size && `${bsPrefix}-${size}`, 31 | bg && `bg-${bg}`, 32 | ), 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /www/docs/examples/Alert/DismissibleControlled.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Alert from 'react-bootstrap/Alert'; 3 | import Button from 'react-bootstrap/Button'; 4 | 5 | function AlertDismissible() { 6 | const [show, setShow] = useState(true); 7 | 8 | return ( 9 | <> 10 | 11 | My Alert 12 | 13 | Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget 14 | lacinia odio sem nec elit. Cras mattis consectetur purus sit amet 15 | fermentum. 16 | 17 | 18 | 19 | setShow(false)} variant="outline-success"> 20 | Close me 21 | 22 | 23 | 24 | 25 | {!show && setShow(true)}>Show Alert} 26 | > 27 | ); 28 | } 29 | 30 | export default AlertDismissible; 31 | -------------------------------------------------------------------------------- /www/plugins/webpack-plugin.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = () => ({ 5 | name: 'webpack-plugin', 6 | configureWebpack(_, isServer, { getJSLoader }) { 7 | return { 8 | devtool: 'inline-cheap-module-source-map', 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.(j|t)sx?$/, 13 | include: [path.resolve(__dirname, '../../src')], 14 | use: [ 15 | getJSLoader( 16 | isServer, 17 | path.resolve(__dirname, '../babel.config.js'), 18 | ), 19 | ], 20 | }, 21 | ], 22 | }, 23 | resolve: { 24 | alias: { 25 | 'react-bootstrap': path.resolve(__dirname, '../../src'), 26 | }, 27 | }, 28 | plugins: [ 29 | new webpack.DefinePlugin({ 30 | __DEV__: process.env.NODE_ENV === 'development', 31 | }), 32 | ], 33 | }; 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/Tabs.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import ListGroup from 'react-bootstrap/ListGroup'; 3 | import Row from 'react-bootstrap/Row'; 4 | import Tab from 'react-bootstrap/Tab'; 5 | 6 | function TabsExample() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | Link 1 14 | 15 | 16 | Link 2 17 | 18 | 19 | 20 | 21 | 22 | Tab pane content 1 23 | Tab pane content 2 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | 31 | export default TabsExample; 32 | -------------------------------------------------------------------------------- /src/DropdownHeader.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface DropdownHeaderProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const DropdownHeader: BsPrefixRefForwardingComponent< 11 | 'div', 12 | DropdownHeaderProps 13 | > = React.forwardRef( 14 | ( 15 | { className, bsPrefix, as: Component = 'div', role = 'heading', ...props }, 16 | ref, 17 | ) => { 18 | bsPrefix = useBootstrapPrefix(bsPrefix, 'dropdown-header'); 19 | return ( 20 | 26 | ); 27 | }, 28 | ) as typeof DropdownHeader; 29 | 30 | DropdownHeader.displayName = 'DropdownHeader'; 31 | 32 | export default DropdownHeader; 33 | -------------------------------------------------------------------------------- /www/docs/examples/Overlays/PopoverPositioned.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; 3 | import Popover from 'react-bootstrap/Popover'; 4 | 5 | function PopoverPositionedExample() { 6 | return ( 7 | <> 8 | {['top', 'right', 'bottom', 'left'].map((placement) => ( 9 | 15 | {`Popover ${placement}`} 16 | 17 | Holy guacamole! Check this info. 18 | 19 | 20 | } 21 | > 22 | Popover on {placement} 23 | 24 | ))} 25 | > 26 | ); 27 | } 28 | 29 | export default PopoverPositionedExample; 30 | -------------------------------------------------------------------------------- /www/docs/examples/Dropdown/SplitVariants.js: -------------------------------------------------------------------------------- 1 | import Dropdown from 'react-bootstrap/Dropdown'; 2 | import SplitButton from 'react-bootstrap/SplitButton'; 3 | 4 | function SplitVariantExample() { 5 | return ( 6 | <> 7 | {['Primary', 'Secondary', 'Success', 'Info', 'Warning', 'Danger'].map( 8 | (variant) => ( 9 | 15 | Action 16 | Another action 17 | 18 | Active Item 19 | 20 | 21 | Separated link 22 | 23 | ), 24 | )} 25 | > 26 | ); 27 | } 28 | 29 | export default SplitVariantExample; 30 | -------------------------------------------------------------------------------- /src/CardTitle.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | import divWithClassName from './divWithClassName'; 6 | 7 | const DivStyledAsH5 = divWithClassName('h5'); 8 | 9 | export interface CardTitleProps 10 | extends BsPrefixProps, 11 | React.HTMLAttributes {} 12 | 13 | const CardTitle: BsPrefixRefForwardingComponent<'div', CardTitleProps> = 14 | React.forwardRef( 15 | ({ className, bsPrefix, as: Component = DivStyledAsH5, ...props }, ref) => { 16 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-title'); 17 | return ( 18 | 23 | ); 24 | }, 25 | ) as typeof CardTitle; 26 | 27 | CardTitle.displayName = 'CardTitle'; 28 | 29 | export default CardTitle; 30 | -------------------------------------------------------------------------------- /src/DropdownDivider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | 6 | export interface DropdownDividerProps 7 | extends BsPrefixProps, 8 | React.HTMLAttributes {} 9 | 10 | const DropdownDivider: BsPrefixRefForwardingComponent< 11 | 'hr', 12 | DropdownDividerProps 13 | > = React.forwardRef( 14 | ( 15 | { className, bsPrefix, as: Component = 'hr', role = 'separator', ...props }, 16 | ref, 17 | ) => { 18 | bsPrefix = useBootstrapPrefix(bsPrefix, 'dropdown-divider'); 19 | return ( 20 | 26 | ); 27 | }, 28 | ) as typeof DropdownDivider; 29 | 30 | DropdownDivider.displayName = 'DropdownDivider'; 31 | 32 | export default DropdownDivider; 33 | -------------------------------------------------------------------------------- /src/ModalTitle.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import divWithClassName from './divWithClassName'; 4 | import { useBootstrapPrefix } from './ThemeProvider'; 5 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 6 | 7 | const DivStyledAsH4 = divWithClassName('h4'); 8 | 9 | export interface ModalTitleProps 10 | extends BsPrefixProps, 11 | React.HTMLAttributes {} 12 | 13 | const ModalTitle: BsPrefixRefForwardingComponent<'span', ModalTitleProps> = 14 | React.forwardRef( 15 | ({ className, bsPrefix, as: Component = DivStyledAsH4, ...props }, ref) => { 16 | bsPrefix = useBootstrapPrefix(bsPrefix, 'modal-title'); 17 | return ( 18 | 23 | ); 24 | }, 25 | ) as typeof ModalTitle; 26 | 27 | ModalTitle.displayName = 'ModalTitle'; 28 | 29 | export default ModalTitle; 30 | -------------------------------------------------------------------------------- /www/docs/examples/Tabs/LeftTabs.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import Nav from 'react-bootstrap/Nav'; 3 | import Row from 'react-bootstrap/Row'; 4 | import Tab from 'react-bootstrap/Tab'; 5 | 6 | function LeftTabsExample() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | Tab 1 14 | 15 | 16 | Tab 2 17 | 18 | 19 | 20 | 21 | 22 | First tab content 23 | Second tab content 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | 31 | export default LeftTabsExample; 32 | -------------------------------------------------------------------------------- /.babelrc.js: -------------------------------------------------------------------------------- 1 | module.exports = (api) => { 2 | const env = api.env(); 3 | 4 | let dev = false; 5 | let setUseClient = false; 6 | let modules; 7 | 8 | switch (env) { 9 | case 'docs': 10 | case 'test': 11 | case 'dist-dev': 12 | dev = true; 13 | modules = false; 14 | break; 15 | case 'dist-prod': 16 | modules = false; 17 | break; 18 | case 'esm': 19 | modules = false; 20 | setUseClient = true; 21 | break; 22 | case 'cjs': 23 | default: 24 | modules = 'commonjs'; 25 | setUseClient = true; 26 | break; 27 | } 28 | 29 | return { 30 | presets: [ 31 | [ 32 | '@react-bootstrap', 33 | { 34 | dev, 35 | modules, 36 | removePropTypes: !dev, 37 | setUseClient, 38 | customClientImports: ['useBootstrapPrefix', 'createWithBsPrefix'], 39 | }, 40 | ], 41 | '@babel/preset-typescript', 42 | ], 43 | plugins: [env === 'test' && 'istanbul'].filter(Boolean), 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /test/PlaceholderSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render } from '@testing-library/react'; 3 | import Placeholder from '../src/Placeholder'; 4 | 5 | describe('', () => { 6 | it('should render a placeholder', () => { 7 | const { container } = render(); 8 | expect(container.firstElementChild!.className).toContain('placeholder'); 9 | }); 10 | 11 | it('should render size', () => { 12 | const { container } = render(); 13 | expect(container.firstElementChild!.className).toContain('placeholder-lg'); 14 | }); 15 | 16 | it('should render animation', () => { 17 | const { container } = render(); 18 | expect(container.firstElementChild!.className).toContain( 19 | 'placeholder-glow', 20 | ); 21 | }); 22 | 23 | it('should render bg', () => { 24 | const { container } = render(); 25 | expect(container.firstElementChild!.className).toContain('bg-primary'); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /www/docs/examples/Form/Basic.js: -------------------------------------------------------------------------------- 1 | import Button from 'react-bootstrap/Button'; 2 | import Form from 'react-bootstrap/Form'; 3 | 4 | function BasicExample() { 5 | return ( 6 | 7 | 8 | Email address 9 | 10 | 11 | We'll never share your email with anyone else. 12 | 13 | 14 | 15 | 16 | Password 17 | 18 | 19 | 20 | 21 | 22 | 23 | Submit 24 | 25 | 26 | ); 27 | } 28 | 29 | export default BasicExample; 30 | -------------------------------------------------------------------------------- /www/docs/examples/ListGroup/StyleActions.js: -------------------------------------------------------------------------------- 1 | import ListGroup from 'react-bootstrap/ListGroup'; 2 | 3 | function StyleActionsExample() { 4 | return ( 5 | 6 | No style 7 | Primary 8 | 9 | Secondary 10 | 11 | 12 | Success 13 | 14 | 15 | Danger 16 | 17 | 18 | Warning 19 | 20 | 21 | Info 22 | 23 | 24 | Light 25 | 26 | 27 | Dark 28 | 29 | 30 | ); 31 | } 32 | 33 | export default StyleActionsExample; 34 | -------------------------------------------------------------------------------- /www/docs/examples/Card/BgColor.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | 3 | function BgColorExample() { 4 | return ( 5 | <> 6 | {[ 7 | 'Primary', 8 | 'Secondary', 9 | 'Success', 10 | 'Danger', 11 | 'Warning', 12 | 'Info', 13 | 'Light', 14 | 'Dark', 15 | ].map((variant) => ( 16 | 23 | Header 24 | 25 | {variant} Card Title 26 | 27 | Some quick example text to build on the card title and make up the 28 | bulk of the card's content. 29 | 30 | 31 | 32 | ))} 33 | > 34 | ); 35 | } 36 | 37 | export default BgColorExample; 38 | -------------------------------------------------------------------------------- /www/docs/examples/Toast/Stacking.js: -------------------------------------------------------------------------------- 1 | import Toast from 'react-bootstrap/Toast'; 2 | import ToastContainer from 'react-bootstrap/ToastContainer'; 3 | 4 | function StackingExample() { 5 | return ( 6 | 7 | 8 | 9 | 10 | Bootstrap 11 | just now 12 | 13 | See? Just like this. 14 | 15 | 16 | 17 | 18 | Bootstrap 19 | 2 seconds ago 20 | 21 | Heads up, toasts will stack automatically 22 | 23 | 24 | ); 25 | } 26 | 27 | export default StackingExample; 28 | -------------------------------------------------------------------------------- /src/CardSubtitle.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import { useBootstrapPrefix } from './ThemeProvider'; 4 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 5 | import divWithClassName from './divWithClassName'; 6 | 7 | const DivStyledAsH6 = divWithClassName('h6'); 8 | 9 | export interface CardSubtitleProps 10 | extends BsPrefixProps, 11 | React.HTMLAttributes {} 12 | 13 | const CardSubtitle: BsPrefixRefForwardingComponent<'div', CardSubtitleProps> = 14 | React.forwardRef( 15 | ({ className, bsPrefix, as: Component = DivStyledAsH6, ...props }, ref) => { 16 | bsPrefix = useBootstrapPrefix(bsPrefix, 'card-subtitle'); 17 | return ( 18 | 23 | ); 24 | }, 25 | ) as typeof CardSubtitle; 26 | 27 | CardSubtitle.displayName = 'CardSubtitle'; 28 | 29 | export default CardSubtitle; 30 | -------------------------------------------------------------------------------- /www/docs/examples/Card/KitchenSink.js: -------------------------------------------------------------------------------- 1 | import Card from 'react-bootstrap/Card'; 2 | import ListGroup from 'react-bootstrap/ListGroup'; 3 | 4 | function KitchenSinkExample() { 5 | return ( 6 | 7 | 8 | 9 | Card Title 10 | 11 | Some quick example text to build on the card title and make up the 12 | bulk of the card's content. 13 | 14 | 15 | 16 | Cras justo odio 17 | Dapibus ac facilisis in 18 | Vestibulum at eros 19 | 20 | 21 | Card Link 22 | Another Link 23 | 24 | 25 | ); 26 | } 27 | 28 | export default KitchenSinkExample; 29 | -------------------------------------------------------------------------------- /www/docs/examples/Form/FormLabelSizing.js: -------------------------------------------------------------------------------- 1 | import Col from 'react-bootstrap/Col'; 2 | import Form from 'react-bootstrap/Form'; 3 | import Row from 'react-bootstrap/Row'; 4 | 5 | function FormLabelSizingExample() { 6 | return ( 7 | <> 8 | 9 | 10 | Large Text 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Normal Text 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Small Text 29 | 30 | 31 | 32 | 33 | 34 | > 35 | ); 36 | } 37 | 38 | export default FormLabelSizingExample; 39 | -------------------------------------------------------------------------------- /src/Figure.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import FigureImage from './FigureImage'; 4 | import FigureCaption from './FigureCaption'; 5 | import { useBootstrapPrefix } from './ThemeProvider'; 6 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 7 | 8 | export interface FigureProps 9 | extends BsPrefixProps, 10 | React.AnchorHTMLAttributes {} 11 | 12 | const Figure: BsPrefixRefForwardingComponent<'figure', FigureProps> = 13 | React.forwardRef( 14 | ({ className, bsPrefix, as: Component = 'figure', ...props }, ref) => { 15 | bsPrefix = useBootstrapPrefix(bsPrefix, 'figure'); 16 | return ( 17 | 22 | ); 23 | }, 24 | ) as typeof Figure; 25 | 26 | Figure.displayName = 'Figure'; 27 | 28 | export default Object.assign(Figure, { 29 | Image: FigureImage, 30 | Caption: FigureCaption, 31 | }); 32 | -------------------------------------------------------------------------------- /src/OffcanvasTitle.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import classNames from 'classnames'; 3 | import divWithClassName from './divWithClassName'; 4 | import { useBootstrapPrefix } from './ThemeProvider'; 5 | import type { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers'; 6 | 7 | const DivStyledAsH5 = divWithClassName('h5'); 8 | 9 | export interface OffcanvasTitleProps 10 | extends BsPrefixProps, 11 | React.HTMLAttributes {} 12 | 13 | const OffcanvasTitle: BsPrefixRefForwardingComponent< 14 | 'div', 15 | OffcanvasTitleProps 16 | > = React.forwardRef( 17 | ({ className, bsPrefix, as: Component = DivStyledAsH5, ...props }, ref) => { 18 | bsPrefix = useBootstrapPrefix(bsPrefix, 'offcanvas-title'); 19 | return ( 20 | 25 | ); 26 | }, 27 | ) as typeof OffcanvasTitle; 28 | 29 | OffcanvasTitle.displayName = 'OffcanvasTitle'; 30 | 31 | export default OffcanvasTitle; 32 | -------------------------------------------------------------------------------- /www/docs/examples/Button/ToggleButtonGroupControlled.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import ToggleButton from 'react-bootstrap/ToggleButton'; 3 | import ToggleButtonGroup from 'react-bootstrap/ToggleButtonGroup'; 4 | 5 | function ToggleButtonGroupControlled() { 6 | const [value, setValue] = useState([1, 3]); 7 | 8 | /* 9 | * The second argument that will be passed to 10 | * `handleChange` from `ToggleButtonGroup` 11 | * is the SyntheticEvent object, but we are 12 | * not using it in this example so we will omit it. 13 | */ 14 | const handleChange = (val) => setValue(val); 15 | 16 | return ( 17 | 18 | 19 | Option 1 20 | 21 | 22 | Option 2 23 | 24 | 25 | Option 3 26 | 27 | 28 | ); 29 | } 30 | 31 | export default ToggleButtonGroupControlled; 32 | -------------------------------------------------------------------------------- /www/docs/examples/Table/Responsive.js: -------------------------------------------------------------------------------- 1 | import Table from 'react-bootstrap/Table'; 2 | 3 | function ResponsiveExample() { 4 | return ( 5 | 6 | 7 | 8 | # 9 | {Array.from({ length: 12 }).map((_, index) => ( 10 | Table heading 11 | ))} 12 | 13 | 14 | 15 | 16 | 1 17 | {Array.from({ length: 12 }).map((_, index) => ( 18 | Table cell {index} 19 | ))} 20 | 21 | 22 | 2 23 | {Array.from({ length: 12 }).map((_, index) => ( 24 | Table cell {index} 25 | ))} 26 | 27 | 28 | 3 29 | {Array.from({ length: 12 }).map((_, index) => ( 30 | Table cell {index} 31 | ))} 32 | 33 | 34 | 35 | ); 36 | } 37 | 38 | export default ResponsiveExample; 39 | -------------------------------------------------------------------------------- /test/ToastHeaderSpec.tsx: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { render } from '@testing-library/react'; 3 | import Toast from '../src/Toast'; 4 | 5 | describe('Toast.Header', () => { 6 | it('will pass all props to the created div and renders its children', () => { 7 | const { container } = render( 8 | 9 | content 10 | , 11 | ); 12 | expect(container.firstElementChild!.tagName).toEqual('DIV'); 13 | 14 | expect(container.firstElementChild!.firstElementChild!.tagName).toEqual( 15 | 'STRONG', 16 | ); 17 | 18 | expect(container.firstElementChild!.classList).toContain('toast-header'); 19 | }); 20 | 21 | it('should render close button variant', () => { 22 | const { container } = render( 23 | 24 | content 25 | , 26 | ); 27 | expect( 28 | container.firstElementChild!.getElementsByTagName('button')[0].classList, 29 | ).toContain('btn-close-white'); 30 | }); 31 | }); 32 | --------------------------------------------------------------------------------
7 | 8 |
9 | 10 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer 11 | posuere erat a ante. 12 | 13 | 16 |
10 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer 11 | posuere erat a ante. 12 |
8 | Aww yeah, you successfully read this important alert message. This 9 | example text is going to run a bit longer so that you can see how 10 | spacing within an alert works with this kind of content. 11 |
14 | Whenever you need to, be sure to use margin utilities to keep things 15 | nice and tidy. 16 |
{frontMatter.description}
Modal body text goes here.
13 | Change this and that and try again. Duis mollis, est non commodo 14 | luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. 15 | Cras mattis consectetur purus sit amet fermentum. 16 |
13 | Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget 14 | lacinia odio sem nec elit. Cras mattis consectetur purus sit amet 15 | fermentum. 16 |