Skip to content

Commit 2d71114

Browse files
authored
Merge pull request #4 from mconf/fixes-1
Enhance documentation and some fixes
2 parents f38dc9c + ddd9cb5 commit 2d71114

File tree

24 files changed

+187
-113
lines changed

24 files changed

+187
-113
lines changed

README.md

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
This repository contains a library of reusable React components extracted from the main [**BigBlueButton (BBB)**](https://github.com/bigbluebutton/bigbluebutton) project. These components provide a consistent and customizable interface that can be reused in other projects, allowing them to easily adopt the BBB visual identity.
44

5-
65
## Peer Dependencies
76

87
This library requires the following peer dependencies to be installed in your project:
@@ -22,6 +21,64 @@ react-icons ^5.5.0
2221

2322
Make sure to install these dependencies to avoid runtime errors and ensure compatibility.
2423

24+
## Color Customization with CSS Variables
25+
26+
This library supports overriding component colors using CSS custom properties (variables). You can define these variables in your project's global CSS or stylesheets to customize the appearance of components without modifying the library code. This is particularly useful for theming and maintaining consistency with your application's design system.
27+
28+
To use this feature:
29+
1. Define the CSS variables in your project's root styles (e.g., in a global CSS file or via styled-components' `createGlobalStyle`).
30+
2. The library's components will automatically pick up these variables if they are set on the `:root` element or a parent container.
31+
32+
**Note**: These variables are optional. If not defined, the components will fall back to their default styled-components theme values, which are derived from the project's `src/stylesheets/palette.ts` file.
33+
34+
### Available CSS Variables
35+
36+
The following table lists the supported CSS variables for color overriding, extracted from `src/stylesheets/palette.ts`. Each variable corresponds to a specific color aspect used in the components (e.g., neutrals, brands, semantics). The "Maps to BBB Core Variable" column indicates if the variable aligns with a standard BBB core color (based on the file's comments). The "Default Value" column shows the fallback color used if the variable is not set.
37+
38+
| Variable Name | Maps to BBB Core Variable | Default Value |
39+
|----------------------------|----------------------------|---------------|
40+
| `--color-neutral-2` | No | #717C91 |
41+
| `--color-neutral-3` | No | #B0BDC9 |
42+
| `--color-neutral-4` | No | #DCE4EC |
43+
| `--color-neutral-white` | No | #FFFFFF |
44+
| `--color-light-gray` | No | #F4F6FA |
45+
| `--color-gray` | No | #4E5A66 |
46+
| `--color-dark-gray` | No | #393C48 |
47+
| `--color-brand-1` | No | #1D65D4 |
48+
| `--color-brand-2` | No | #1D65D4 |
49+
| `--color-brand-3` | No | #1D65D4 |
50+
| `--color-brand-light` | Yes (`--color-blue-aux`) | #E5EFFB |
51+
| `--color-brand-aux` | Yes (`--color-brand-aux`) | #E5EFFB |
52+
| `--color-success` | No | #2DD36F |
53+
| `--color-warning` | No | #F59240 |
54+
| `--color-error` | Yes (`--color-danger`) | #D6232D |
55+
| `--color-error-dark` | Yes (`--color-danger-dark`)| #B91C25 |
56+
| `--color-background-white` | No | #FFFFFF |
57+
| `--color-background-light` | No | #F4F6FA |
58+
| `--color-background-blue` | No | #E5EFFB |
59+
| `--color-border-default` | No | #B0BDC9 |
60+
| `--color-border-selected` | No | #1D65D4 |
61+
| `--color-border-error` | No | #D6232D |
62+
| `--color-border-default` | Yes (`--default-border`) | #B0BDC9 |
63+
| `--color-text-default` | No | #393C48 |
64+
| `--color-text-light` | No | #717C91 |
65+
| `--color-icon-default` | No | #717C91 |
66+
| `--color-icon-blue` | No | #1D65D4 |
67+
| `--color-icon-white` | No | #FFFFFF |
68+
| `--color-hover-dark` | No | #1E53AF |
69+
| `--color-hover-light` | No | #D4E5FA |
70+
| `--color-hover-neutral` | No | #DCE4EC |
71+
72+
**Example Usage**:
73+
```css
74+
:root {
75+
--color-primary: #ff5733; /* Override primary brand color to a custom orange */
76+
--color-text-default: #333333; /* Darker text for better contrast */
77+
}
78+
```
79+
80+
If you need to override colors for specific components or add new variables, refer to the component's `styles.ts` file for implementation details.
81+
2582
## Installation
2683

2784
This library is under active development and has not yet been published on npm. For now, you can clone the repository and install it locally.
@@ -30,7 +87,7 @@ This library is under active development and has not yet been published on npm.
3087

3188
```
3289
npm install
33-
npm run build-bundle
90+
npm run build
3491
```
3592

3693
### Using npm link

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@mconf/bbb-ui-components-react",
33
"version": "1.0.0",
4-
"main": "dist/index.ts",
4+
"main": "dist/components/index.js",
55
"types": "dist/types/index.d.ts",
66
"files": [
77
"dist",

src/components/Button/component.tsx

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@ function Button(props: ButtonProps): JSX.Element {
7171
'aria-labelledby'?: string;
7272
'aria-describedby'?: string;
7373
} = {};
74-
if (ariaLabel) accessibilityProps['aria-label'] = ariaLabel;
75-
if (ariaLabelledBy) accessibilityProps['aria-labelledby'] = ariaLabelledBy;
74+
const generatedId = useId();
75+
const defaultLabelId = `${id || generatedId}-label`;
76+
accessibilityProps['aria-label'] = ariaLabel || label;
77+
accessibilityProps['aria-labelledby'] = ariaLabelledBy || defaultLabelId;
7678
if (ariaDescribedBy) accessibilityProps['aria-describedby'] = ariaDescribedBy;
7779

7880
const buttonElement = (() => {
@@ -87,10 +89,10 @@ function Button(props: ButtonProps): JSX.Element {
8789
onClick={onClick}
8890
onKeyDown={onKeyDown}
8991
{...accessibilityProps}
90-
color={color}
91-
variant={variant}
92-
size={size}
93-
layout={layout}
92+
$color={color}
93+
$variant={variant}
94+
$size={size}
95+
$layout={layout}
9496
disabled={disabled}
9597
>
9698
{icon}
@@ -108,27 +110,28 @@ function Button(props: ButtonProps): JSX.Element {
108110
const testId = dataTest || `${LAYOUTS.STACKED}-button-${id || label || 'default'}`;
109111

110112
return (
111-
<Styled.ButtonWrapper data-test={testId} layout={layout}>
113+
<Styled.ButtonWrapper data-test={testId} $layout={layout}>
112114
<Styled.Button
113115
id={id}
114116
onClick={onClick}
115117
onKeyDown={onKeyDown}
116118
{...accessibilityProps}
117-
color={color}
118-
variant={variant}
119-
size={size}
120-
layout={layout}
119+
$color={color}
120+
$variant={variant}
121+
$size={size}
122+
$layout={layout}
121123
disabled={disabled}
122124
>
123125
{!hideHelperIcon && (
124-
<Styled.helperIconContainer
126+
<Styled.HelperIconContainer
125127
// Add this property only when there is a onClick function for the auxiliary icon.
126128
// It controls whether the auxiliary button is going to have an independent hover state.
127129
{...(helperOnClick && { 'data-is-aux-icon': true })}
128-
role="button"
129-
hover={helperOnClick !== null}
130-
color={color}
131-
variant={variant}
130+
{...(helperOnClick && { 'aria-label': accessibilityProps['aria-label'] + ' helper' })}
131+
{...(helperOnClick && { role: "button" })}
132+
$hover={helperOnClick !== null}
133+
$color={color}
134+
$variant={variant}
132135
onClick={(event) => {
133136
if (helperOnClick) {
134137
helperOnClick(event);
@@ -137,12 +140,12 @@ function Button(props: ButtonProps): JSX.Element {
137140
}
138141
}}
139142
>
140-
<Styled.helperIcon>{helperIcon}</Styled.helperIcon>
141-
</Styled.helperIconContainer>
143+
<Styled.HelperIcon>{helperIcon}</Styled.HelperIcon>
144+
</Styled.HelperIconContainer>
142145
)}
143146
{icon && <Styled.IconWrapper>{icon}</Styled.IconWrapper>}
144147
</Styled.Button>
145-
<Styled.ButtonText>{label}</Styled.ButtonText>
148+
<Styled.ButtonText id={defaultLabelId}>{label}</Styled.ButtonText>
146149
</Styled.ButtonWrapper>
147150
);
148151
}
@@ -157,14 +160,14 @@ function Button(props: ButtonProps): JSX.Element {
157160
onClick={onClick}
158161
onKeyDown={onKeyDown}
159162
{...accessibilityProps}
160-
color={color}
161-
variant={variant}
162-
size={size}
163-
layout={layout}
163+
$color={color}
164+
$variant={variant}
165+
$size={size}
166+
$layout={layout}
164167
disabled={disabled}
165168
>
166169
{iconStart && iconStart}
167-
{label && <span>{label}</span>}
170+
{label && <span id={defaultLabelId}>{label}</span>}
168171
{children}
169172
{iconEnd && iconEnd}
170173
</Styled.Button>

src/components/Button/styles.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
LAYOUTS,
1111
} from './constants';
1212
import {
13-
StyledhelperIconContainer, StyledButtonProps,
13+
StyledHelperIconContainer, StyledButtonProps,
1414
StyledButtonWrapperProps,
1515
} from './type';
1616
import {
@@ -31,15 +31,15 @@ const commonButtonStyles = css<StyledButtonProps>`
3131
position: relative;
3232
transition: opacity 0.2s ease-in-out;
3333
34-
${({ size }) => {
35-
return CSS_SIZE_PROPERTIES[size]
36-
? `padding: ${CSS_SIZE_PROPERTIES[size].padding};`
34+
${({ $size }) => {
35+
return CSS_SIZE_PROPERTIES[$size]
36+
? `padding: ${CSS_SIZE_PROPERTIES[$size].padding};`
3737
: `padding: ${CSS_SIZE_PROPERTIES[DEFAULT_SIZE].padding};`;
3838
}}
3939
40-
${({ color, variant }) => {
41-
const safeColor = color || DEFAULT_COLOR;
42-
const safeVariant = variant || DEFAULT_VARIANT;
40+
${({ $color, $variant }) => {
41+
const safeColor = $color || DEFAULT_COLOR;
42+
const safeVariant = $variant || DEFAULT_VARIANT;
4343
const {
4444
color: contentColor,
4545
iconColor,
@@ -72,8 +72,8 @@ const commonButtonStyles = css<StyledButtonProps>`
7272
`;
7373
}}
7474
75-
${({ variant }) =>
76-
variant === VARIANTS.SUBTLE &&
75+
${({ $variant }) =>
76+
$variant === VARIANTS.SUBTLE &&
7777
`
7878
text-decoration: underline;
7979
`}
@@ -139,7 +139,7 @@ const defaultLayoutStyles = css`
139139
`;
140140

141141
export const ButtonWrapper = styled.div<StyledButtonWrapperProps>`
142-
${({ layout }) => layout === LAYOUTS.STACKED && `
142+
${({ $layout }) => $layout === LAYOUTS.STACKED && `
143143
width: 5rem;
144144
display: flex;
145145
flex-direction: column;
@@ -151,8 +151,8 @@ export const ButtonWrapper = styled.div<StyledButtonWrapperProps>`
151151
export const Button = styled.button<StyledButtonProps>`
152152
${commonButtonStyles}
153153
154-
${({ layout }) => {
155-
switch (layout) {
154+
${({ $layout }) => {
155+
switch ($layout) {
156156
case LAYOUTS.STACKED:
157157
return stackedLayoutStyles;
158158
case LAYOUTS.CIRCLE:
@@ -163,16 +163,22 @@ export const Button = styled.button<StyledButtonProps>`
163163
}}
164164
`;
165165

166-
export const helperIconContainer = styled.div<StyledhelperIconContainer>`
167-
${({ hover, variant, color }) => hover && `
168-
&&:hover,
169-
&&:active,
170-
background-color: ${CSS_COLOR_PROPERTIES[variant][color].hoverBackground};
171-
}
172-
&&:focus {
173-
outline: 1px solid ${CSS_COLOR_PROPERTIES[variant][color].outline};
174-
}
175-
`}
166+
export const HelperIconContainer = styled.div<StyledHelperIconContainer>`
167+
${({ $hover, $variant, $color }) => {
168+
if (!$hover) return null;
169+
170+
return css`
171+
&&:hover,
172+
&&:active {
173+
${CSS_COLOR_PROPERTIES[$variant][$color].hoverBackground &&
174+
`background-color: ${CSS_COLOR_PROPERTIES[$variant][$color].hoverBackground};`}
175+
}
176+
177+
&&:focus {
178+
outline: 1px solid ${CSS_COLOR_PROPERTIES[$variant][$color].outline};
179+
}
180+
`;
181+
}}
176182
border-radius: 50%;
177183
padding: 0.2rem;
178184
position: absolute;
@@ -183,7 +189,7 @@ export const helperIconContainer = styled.div<StyledhelperIconContainer>`
183189
}
184190
`;
185191

186-
export const helperIcon = styled.div`
192+
export const HelperIcon = styled.div`
187193
display: flex;
188194
align-items: center;
189195
justify-content: center;

src/components/Button/type.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,21 @@ type SizeType = typeof SIZE_VALUES[number];
4242
type LayoutType = typeof LAYOUT_VALUES[number];
4343
type TooltipPlacementType = typeof TOOLTIP_PLACEMENT_VALUES[number];
4444

45-
export interface StyledhelperIconContainer {
46-
hover: boolean;
47-
variant: VariantType;
48-
color: ColorType;
45+
export interface StyledHelperIconContainer {
46+
$hover: boolean;
47+
$variant: VariantType;
48+
$color: ColorType;
4949
}
5050

5151
export interface StyledButtonWrapperProps {
52-
layout: LayoutType;
52+
$layout: LayoutType;
5353
}
5454

5555
export interface StyledButtonProps {
56-
variant?: VariantType;
57-
color?: ColorType;
58-
size?: SizeType;
59-
layout?: LayoutType;
56+
$variant?: VariantType;
57+
$color?: ColorType;
58+
$size?: SizeType;
59+
$layout?: LayoutType;
6060
disabled: boolean;
6161
}
6262

src/components/Modal/component.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const Modal: React.FC<ModalProps> = ({
7272
{showDividers && <BBBDivider />}
7373

7474
<Styled.ModalBody
75-
allowScroll={allowScroll}
75+
$allowScroll={allowScroll}
7676
>
7777
{children}
7878
</Styled.ModalBody>
@@ -81,7 +81,7 @@ const Modal: React.FC<ModalProps> = ({
8181
{showDividers && (<BBBDivider />)}
8282

8383
<Styled.ModalFooter
84-
stickyFooter={stickyFooter}
84+
$stickyFooter={stickyFooter}
8585
>
8686
{footerContent}
8787
</Styled.ModalFooter>

src/components/Modal/styles.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export const CloseButton = styled.button`
5555

5656
export const ModalBody = styled.div<StyledModalBodyProps>`
5757
flex-grow: 1;
58-
overflow-y: ${({ allowScroll }) => allowScroll ? 'auto' : 'hidden'};
58+
overflow-y: ${({ $allowScroll }) => $allowScroll ? 'auto' : 'hidden'};
5959
overflow-x: hidden;
6060
display: flex;
6161
flex-direction: column;
@@ -68,4 +68,12 @@ export const ModalFooter = styled.div<StyledModalFooterProps>`
6868
display: flex;
6969
justify-content: flex-end;
7070
gap: ${spacingMedium};
71+
72+
${({ $stickyFooter }) =>
73+
$stickyFooter &&
74+
`
75+
position: sticky;
76+
bottom: 0;
77+
background-color: #fff;
78+
`}
7179
`;

src/components/Modal/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React from 'react';
22

33
export interface StyledModalBodyProps {
4-
allowScroll: boolean;
4+
$allowScroll: boolean;
55
}
66

77
export interface StyledModalFooterProps {
8-
stickyFooter: boolean;
8+
$stickyFooter: boolean;
99
}
1010

1111
export interface ModalProps {

0 commit comments

Comments
 (0)