我想在正在构建的日历应用程序的过滤器部分中将文本显示为灰色,但似乎只能将其编码到复选框本身上。
我已经尝试过使用〜语法通过我的SCSS容器和标签将其从父选择器传递给子选择器。在不违反DRY原则的情况下,似乎找不到解决此问题的方法。我设法使它可以在复选框上工作,但不能在同一容器中使用字体。
Checkbox / index.js
import React from 'react'
import './index.css';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import PropTypes from 'prop-types'
/*
based off the fake checkbox styles from here
should still be screen-reader/keyboard accessible
https://www.w3schools.com/howto/howto_css_custom_checkbox.asp
*/
class Checkbox extends React.Component {
render() {
const { name, label, value, checked, onChange, handleClose, dataObject, ...rest } = this.props
return (
<div {...rest}>
<label className="checkbox-container">
<span className="checkbox-label">{label}</span>
<input
type="checkbox"
checked={checked}
value={value}
onChange={onChange} />
<span className="checkmark"></span>
{this.props.handleClose && <FontAwesomeIcon onClick={this.handleClick.bind(this)} className='checkbox-icon' size="1x" icon={['fal', 'times']} />}
</label>
</div>
)
}
handleClick(e) {
e.preventDefault()
this.props.handleClose(this.props.dataObject)
}
}
Checkbox.propTypes = {
handleClose: PropTypes.func, // optional
onChange: PropTypes.func.isRequired,
label: PropTypes.string.isRequired,
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]).isRequired,
dataObject: PropTypes.object, // optional -> used for the 'x' button
checked: PropTypes.bool.isRequired,
}
export default Checkbox
CalendersFiltersSection / index.js
import React from 'react'
import './index.css';
import PropTypes from 'prop-types'
import Checkbox from '../../../Checkbox'
import { defaultCalendarFilters} from '../../../../../constants'
class CalendarFiltersSection extends React.Component {
render() {
const { filters } = this.props
// let orderedFilters = Object.values(filters)
// orderedFilters.sort((a,b) => {
// return a.displayOrder - b.displayOrder
// })
return (
<section className="calendar-filters-section">
<div className='title'>{this.props.title}</div>
{ Object.values(filters).map(filter => {
let className = defaultCalendarFilters[filter.id].label.toLowerCase()
return <Checkbox className={`checkbox-event-type-${className}`} key={filter.id} label={filter.label} name={filter.id} checked={filter.checked} value={filter.id} onChange={this.props.handleInputChange} />
})
}
</section>
)
}
}
CalendarFiltersSection.propTypes = {
handleInputChange: PropTypes.func.isRequired,
filters: PropTypes.object.isRequired,
title: PropTypes.string.isRequired
}
export default CalendarFiltersSection
Checkbox / index.css
.checkbox-container {
display: block;
position: relative;
padding-left: 26px;
margin-bottom: 8px;
cursor: pointer;
font-size: 14px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Hide the browser's default checkbox */
.checkbox-container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
/* Create a custom checkbox */
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 18px;
width: 18px;
background-color: #525259;
}
/* On mouse-over, add a grey background color */
/*.checkbox-container:hover input ~ .checkmark {
background-color: #ccc;
}
*/
/* When the checkbox is checked, add a blue background */
/*.checkbox-container input:checked ~ .checkmark {
background-color: #2196F3;
}*/
/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
content: "";
position: absolute;
display: none;
}
/* Show the checkmark when checked */
.checkbox-container input:checked ~ .checkmark:after {
display: block;
}
/* Style the checkmark/indicator */
.checkbox-container .checkmark:after {
left: 7px;
top: 3px;
width: 3px;
height: 7px;
border: solid black;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
box-sizing: initial;
color: var(--secondary-font-color);
}
.checkbox-event-type-trainings .checkbox-container input:checked ~ .checkmark {
background-color: var(--event-type-trainings-color);
}
.checkbox-event-type-medizinisch .checkbox-container input:checked ~ .checkmark {
background-color: var(--event-type-medizinisch-color);
}
.checkbox-event-type-spiele .checkbox-container input:checked ~ .checkmark {
background-color: var(--event-type-spiele-color);
}
.checkbox-event-type-tests .checkbox-container input:checked ~ .checkmark {
background-color: var(--event-type-tests-color);
}
.checkbox-event-type-andere .checkbox-container input:checked ~ .checkmark {
background-color: var(--event-type-andere-color);
}
.checkbox-label {
color: var(--secondary-font-color);
}
.checkbox-icon {
position:absolute;
right: 0;
top: 4px;
z-index:5;
}
.checkbox-container .checkbox-icon {
visibility: hidden;
}
.checkbox-container:hover .checkbox-icon {
visibility: visible;
}
CalendarFiltersSection / index.css
.calendar-filters-section {
align-self: flex-start;
color: var(--secondary-font-color);
margin-bottom: 4rem;
}
Constants.js
import { history } from './util/history'
export const API_HOST = process.env.REACT_APP_USE_STAGING_API ?
"http://example.com" : "http://127.0.0.1:8000"
export const EVENTS_LIST_URL = `${API_HOST}/events/`
export const CALENDARS_LIST_URL = `${API_HOST}/users/calendars/`
export const USERS_LIST_URL = `${API_HOST}/users/`
export const getTeamsListUrl = (clubId) =>
`${API_HOST}/clubs/${clubId}/teams/`
export const getClubsTeamsPlayersListUrl = (clubId, teamId) =>
`${API_HOST}/clubs/${clubId}/teams/${teamId}/players/`
//TODO combine all of these into one data structure .
export const mapNameToEventTypeNumber = {
0: 'andere',
1: 'trainings',
2: 'tests',
3: 'medizinisch',
4: 'medizinisch',
5: 'medizinisch',
6: 'spiele',
8: 'medizinisch',
}
//TODO combine all of these into one data structure .
// updaet: the backend updated to use strings instead of numbers...
export const mapMainCategoryNameToSubCategoryName = {
social: 'andere',
practice: 'trainings',
assessment: 'tests',
doctor: 'medizinisch',
physio: 'medizinisch',
operation: 'medizinisch',
match: 'spiele',
meeting: 'andere',
}
// 'event_types': ((0, 'SOCIAL'),
// (1, 'PRACTICE'),
// (2, 'ASSESSMENT'),
// (3, 'DOCTOR'),
// (4, 'PHYSIO'),
// (5, 'OPERATION'),
// (6, 'MATCH'),
// (7, 'PRIVATE'),
// (8, 'MEETING'),
// (9, 'SCHOOL/JOB'),
// (10, 'MISC')),
export const mapSpecificEventTypeCategoryToEventTypeNumber = {
0: 'Social',
1: 'Practice',
2: 'Examination',
3: 'Doctor',
4: 'Rehab',
5: 'Physio',
6: 'Match',
7: 'Injury',
8: 'Treatment',
}
export const mappingOfSpecificEventTypeToFilterCategories = {
1: 0,
3: 1,
4: 1,
5: 1,
6: 2,
2: 3,
0: 4
}
export const defaultCalendarFilters = [
{
id: 0,
checked: true,
label: 'Trainings',
eventTypeNumbers: ['practice']
// eventTypeNumbers: ['1']
},
{
id: 1,
checked: true,
label: 'Medizinisch',
eventTypeNumbers: ['doctor','physio','operation']
// eventTypeNumbers: ['3','4','5']
},
{
id: 2,
checked: true,
label: 'Spiele',
eventTypeNumbers: ['match']
// eventTypeNumbers: ['6']
},
{
id: 3,
checked: true,
label: 'Tests',
eventTypeNumbers: ['assessment']
// eventTypeNumbers: ['2']
},
{
id: 4,
checked: true,
label: 'Andere',
eventTypeNumbers: ['meeting', 'misc']
// eventTypeNumbers: ['0']
},
]
export const mapClubRoleNumberToSlug = {
'trainer': 0,
'athletiktrainer': 1,
'torwarttrainer': 2,
'individualtrainer': 3,
'rehabilitationtrainer': 4,
'arzt': 5,
'physiotherapeut': 6,
'videoanalyst': 7,
'athlet': 8,
'betreuer': 9,
'clubadmin': 10,
}
export const clubRolesData = {
'trainer': {
slug: 'trainer',
roleNum: 0,
isStaff: true,
isAthlete: false
},
'athletiktrainer': {
slug: 'athletiktrainer',
roleNum: 1,
isStaff: true,
isAthlete: false
},
'torwarttrainer': {
slug: 'torwarttrainer',
roleNum: 2,
isStaff: true,
isAthlete: false
},
'individualtrainer': {
slug: 'individualtrainer',
roleNum: 3,
isStaff: true,
isAthlete: false
},
'rehabilitationtrainer': {
slug: 'rehabilitationtrainer',
roleNum: 4,
isStaff: true,
isAthlete: false
},
'arzt': {
slug: 'arzt',
roleNum: 5,
isStaff: true,
isAthlete: false
},
'physiotherapeut': {
slug: 'physiotherapeut',
roleNum: 6,
isStaff: true,
isAthlete: false
},
'videoanalyst': {
slug: 'videoanalyst',
roleNum: 7,
isStaff: true,
isAthlete: false
},
'athlet': {
slug: 'athlet',
roleNum: 8,
isStaff: false,
isAthlete: true
},
'betreuer': {
slug: 'betreuer',
roleNum: 9,
isStaff: true,
isAthlete: false
},
'clubadmin': {
slug: 'clubadmin',
roleNum: 10,
isStaff: true,
isAthlete: false
},
}
export const ATHLETE_ROLES = [
'athlet'
]
export const STAFF_ROLES = [
'arzt',
'athletiktrainer',
'betreuer',
// 'clubadmin',
'individualtrainer',
'physiotherapeut',
'rehabilitationtrainer',
'torwarttrainer',
'trainer',
'videoanalyst',
]
export const getUserData = () => {
let userData = null
const userDataJson = localStorage.userData
if(userDataJson) {
userData = JSON.parse(userDataJson)
} else {
history.push('./login')
return
}
return userData
}
export const NAVBAR_TABS = [
{
text: 'Dein Club',
link: '/club-member',
active: false,
icon: 'fa-shield'
},
{
text: 'Kalender',
link: '/calendar',
active: false,
icon: 'fa-calendar-alt'
},
{
text: 'Library',
link: '/library/abilities',
active: false,
icon: 'fa-books'
}
]