mirror of
https://github.com/quantum5/qcal.git
synced 2025-04-24 09:41:57 -04:00
Factor out reusable MobileTooltip component
Also prevents tabIndex from being generated on desktop
This commit is contained in:
parent
1a7c4915e1
commit
8c238c6625
20
common/src/MobileTooltip.scss
Normal file
20
common/src/MobileTooltip.scss
Normal file
|
@ -0,0 +1,20 @@
|
|||
@media (pointer: coarse), (hover: none) {
|
||||
.MobileTooltip {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
|
||||
&:focus::after {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
top: 90%;
|
||||
left: 0;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border: 1px solid;
|
||||
width: fit-content;
|
||||
padding: 3px;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
31
common/src/MobileTooltip.tsx
Normal file
31
common/src/MobileTooltip.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import * as React from 'react';
|
||||
import {useEffect} from 'react';
|
||||
|
||||
const MobileTooltipContext = React.createContext(false);
|
||||
|
||||
export function MobileTooltipProvider({children}: React.PropsWithChildren<{}>): JSX.Element {
|
||||
const [mobile, setMobile] = React.useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.matchMedia)
|
||||
return;
|
||||
|
||||
const match = window.matchMedia('(pointer: coarse), (hover: none)');
|
||||
const callback = () => setMobile(match.matches);
|
||||
|
||||
callback();
|
||||
match.addEventListener('change', callback);
|
||||
return () => match.removeEventListener('change', callback);
|
||||
}, [setMobile]);
|
||||
|
||||
return <MobileTooltipContext.Provider value={mobile}>
|
||||
{children}
|
||||
</MobileTooltipContext.Provider>;
|
||||
}
|
||||
|
||||
export function useMobileTooltipProps(): { className: string, tabIndex?: number } {
|
||||
return {
|
||||
className: 'MobileTooltip',
|
||||
...React.useContext(MobileTooltipContext) ? {tabIndex: 0} : {},
|
||||
};
|
||||
}
|
|
@ -147,26 +147,6 @@
|
|||
background: $gray-300;
|
||||
}
|
||||
|
||||
@media (pointer: coarse), (hover: none) {
|
||||
.Day-rural {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
text-decoration: underline dashed;
|
||||
}
|
||||
|
||||
.Day-rural:focus::after {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
top: 90%;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border: 1px solid;
|
||||
width: fit-content;
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.Calendar-month-name.input-group {
|
||||
justify-content: center;
|
||||
font-size: 0.75em;
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from '@common/french';
|
||||
import {jdnDate} from '@common/gregorian';
|
||||
import {jdnLongCount} from '@common/longCount';
|
||||
import {useMobileTooltipProps} from '@common/MobileTooltip';
|
||||
|
||||
type MonthProps = {
|
||||
year: number;
|
||||
|
@ -39,10 +40,11 @@ function DayDetail({jdn}: { jdn: number }): JSX.Element {
|
|||
function NormalDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
|
||||
const jdn = frJDN(year, month, day);
|
||||
const rural = dateRuralName(month, day)!;
|
||||
const mobile = useMobileTooltipProps();
|
||||
return <div className={`Day NormalDay ${jdn === todayJDN ? 'Day-today' : ''}`}>
|
||||
<div className="Day-name">{day}</div>
|
||||
<div className="Day-decade">{decadeNames[(day - 1) % 10]}</div>
|
||||
<div className="Day-rural" title={rural.title} tabIndex={0}>{rural.name}</div>
|
||||
<div className="Day-rural"><abbr title={rural.title} {...mobile}>{rural.name}</abbr></div>
|
||||
<DayDetail jdn={jdn}/>
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@import 'bootstrap/scss/forms';
|
||||
@import 'bootstrap/scss/root';
|
||||
@import './consts';
|
||||
@import '@common/MobileTooltip.scss';
|
||||
|
||||
body {
|
||||
padding-top: $spacer * 4;
|
||||
|
|
|
@ -4,12 +4,15 @@ import 'bootstrap/js/dist/collapse';
|
|||
import './index.scss';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import {MobileTooltipProvider} from '@common/MobileTooltip';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
<React.StrictMode>
|
||||
<MobileTooltipProvider>
|
||||
<App/>
|
||||
</MobileTooltipProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
|
|
|
@ -167,24 +167,3 @@
|
|||
.Calendar-today-button {
|
||||
max-width: 5em;
|
||||
}
|
||||
|
||||
@media (pointer: coarse), (hover: none) {
|
||||
.DayDetail abbr {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
|
||||
&:focus::after {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
top: 90%;
|
||||
left: 0;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border: 1px solid;
|
||||
width: fit-content;
|
||||
padding: 3px;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {formatJG, jdnGregorian, JulianDay, JulianMonth, monthName, weekdayNames}
|
|||
import {jdnLongCount} from '@common/longCount';
|
||||
import {jdnJulian, julianJDN, julianMonthDays} from '@common/julian';
|
||||
import {frDateFormat, frEndJD, frStartJD, jdnFrench} from '@common/french';
|
||||
import {useMobileTooltipProps} from '@common/MobileTooltip';
|
||||
|
||||
type MonthProps = {
|
||||
year: number;
|
||||
|
@ -20,18 +21,19 @@ function WeekdayName({name}: { name: string }): JSX.Element {
|
|||
|
||||
function DayDetail({jdn}: { jdn: number }): JSX.Element {
|
||||
const lc = jdnLongCount(jdn);
|
||||
const mobile = useMobileTooltipProps();
|
||||
return <div className="DayDetail">
|
||||
<div className="DayDetail-jdn"><abbr title="Julian day number" tabIndex={0}>JD</abbr> {jdn}</div>
|
||||
<div className="DayDetail-jdn"><abbr title="Julian day number" {...mobile}>JD</abbr> {jdn}</div>
|
||||
<div className="DayDetail-gregorian">
|
||||
<abbr title="Gregorian date" tabIndex={0}>G.</abbr>{' '}
|
||||
<abbr title="Gregorian date" {...mobile}>G.</abbr>{' '}
|
||||
{formatJG(jdnGregorian(jdn))}
|
||||
</div>
|
||||
{lc && <div className="DayDetail-lc">
|
||||
<abbr title="Mesoamerican long count date" tabIndex={0}>LC</abbr>{' '}
|
||||
<abbr title="Mesoamerican long count date" {...mobile}>LC</abbr>{' '}
|
||||
{lc.join('.\u200b')}
|
||||
</div>}
|
||||
{jdn >= frStartJD && jdn <= frEndJD && <div className="DayDetail-fr">
|
||||
<abbr title="French Republican Calendar" tabIndex={0}>FR</abbr>{' '}
|
||||
<abbr title="French Republican Calendar" {...mobile}>FR</abbr>{' '}
|
||||
{frDateFormat(jdnFrench(jdn))}
|
||||
</div>}
|
||||
</div>;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@import 'bootstrap/scss/forms';
|
||||
@import 'bootstrap/scss/root';
|
||||
@import './consts';
|
||||
@import '@common/MobileTooltip.scss';
|
||||
|
||||
body {
|
||||
padding-top: $spacer * 4;
|
||||
|
|
|
@ -4,12 +4,15 @@ import 'bootstrap/js/dist/collapse';
|
|||
import './index.scss';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import {MobileTooltipProvider} from '@common/MobileTooltip';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
<React.StrictMode>
|
||||
<MobileTooltipProvider>
|
||||
<App/>
|
||||
</MobileTooltipProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root'),
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
|
|
Loading…
Reference in a new issue