Skip to content

Commit

Permalink
Add docs & demos
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert committed Jun 7, 2024
1 parent 3f1b132 commit 2883b65
Show file tree
Hide file tree
Showing 49 changed files with 2,692 additions and 2,388 deletions.
301 changes: 301 additions & 0 deletions docs/data/base/components/slider/CustomSubcomponents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
import * as React from 'react';
import { useTheme } from '@mui/system';
import * as Slider from '@base_ui/react/Slider';
import * as Tooltip from '@base_ui/react/Tooltip';

function useIsDarkMode() {
const theme = useTheme();
return theme.palette.mode === 'dark';
}

export default function CustomSubcomponents() {
const [valueLabelOpen, setValueLabelOpen] = React.useState(false);

const handleGlobalPointerUp = () => {
if (valueLabelOpen) {
setValueLabelOpen(false);
}
};

return (
<div className="App">
<Slider.Root className="JoySlider" defaultValue={40}>
<Slider.Track className="JoySlider-track">
<SliderTrackFill className="JoySlider-track-fill" />
{Array.from(Array(10), (_, x) => x).map((v) => {
return <SliderMark key={v} index={v} className="JoySlider-mark" />;
})}
<Tooltip.Root delay={0} open={valueLabelOpen}>
<Slider.Thumb
className="JoySlider-thumb"
onFocus={() => {
if (!valueLabelOpen) {
setValueLabelOpen(true);
}
}}
onBlur={() => {
if (valueLabelOpen) {
setValueLabelOpen(false);
}
}}
onPointerOver={() => {
if (!valueLabelOpen) {
setValueLabelOpen(true);
}
}}
onPointerLeave={(event) => {
if (event.buttons !== 1) {
setValueLabelOpen(false);
} else {
document.addEventListener('pointerup', handleGlobalPointerUp, {
once: true,
});
}
}}
>
<Tooltip.Trigger className="SliderTooltip-trigger" />
</Slider.Thumb>
<Tooltip.Positioner sideOffset={10} alignment="center">
<Tooltip.Popup
className="SliderTooltip-popup"
data-open={String(valueLabelOpen)}
>
<Slider.Output />
<Tooltip.Arrow className="SliderTooltip-arrow" />
</Tooltip.Popup>
</Tooltip.Positioner>
</Tooltip.Root>
</Slider.Track>
</Slider.Root>
<Styles />
</div>
);
}

const SliderMark = React.forwardRef(function SliderMark(props, ref) {
const { index, style, ...otherProps } = props;
const { percentageValues } = Slider.useSliderContext();
const isFilled = percentageValues[0] >= index * 10;
return (
<span
ref={ref}
data-mark-active={String(isFilled)}
style={{
...style,
left: `${(100 / 10) * (index + 0)}%`,
visibility: index === 0 ? 'hidden' : 'inherit',
}}
{...otherProps}
/>
);
});

const SliderTrackFill = React.forwardRef(function SliderTrackFill(props, ref) {
const { style, ...otherProps } = props;

const { axis, disabled, isRtl, orientation, percentageValues } =
Slider.useSliderContext();

const isRange = percentageValues.length > 1;

let internalStyles;

if (isRange) {
const trackOffset = percentageValues[0];
const trackLeap = percentageValues[percentageValues.length - 1] - trackOffset;
internalStyles = getRangeStyles(axis, trackOffset, trackLeap);
} else if (orientation === 'vertical') {
internalStyles = {
bottom: 0,
height: `${percentageValues[0]}%`,
};
} else {
internalStyles = {
width: `${percentageValues[0]}%`,
[isRtl ? 'right' : 'left']: 0,
};
}

return (
<span
data-disabled={disabled}
ref={ref}
style={{
...internalStyles,
...style,
}}
{...otherProps}
/>
);
});

function getRangeStyles(axis, trackOffset, trackLeap) {
const axisProps = {
horizontal: {
offset: (percent) => ({ left: `${percent}%` }),
leap: (percent) => ({ width: `${percent}%` }),
},
'horizontal-reverse': {
offset: (percent) => ({ right: `${percent}%` }),
leap: (percent) => ({ width: `${percent}%` }),
},
vertical: {
offset: (percent) => ({ bottom: `${percent}%` }),
leap: (percent) => ({ height: `${percent}%` }),
},
};

return {
...axisProps[axis].offset(trackOffset),
...axisProps[axis].leap(trackLeap),
};
}

function Styles() {
// Replace this with your app logic for determining dark mode
const isDarkMode = useIsDarkMode();
return (
<style suppressHydrationWarning>
{`
.App {
width: 20rem;
padding: 1rem;
}
.JoySlider {
width: 100%;
margin: 16px 0;
position: relative;
-webkit-tap-highlight-color: transparent;
}
.JoySlider-track {
display: flex;
align-items: center;
position: relative;
width: 100%;
height: 16px;
border-radius: 9999px;
touch-action: none;
margin-top: 2rem;
}
.JoySlider-track:hover {
cursor: pointer;
}
.JoySlider-track::before {
content: '';
width: 100%;
height: 6px;
border-radius: 9999px;
touch-action: none;
background-color: ${isDarkMode ? '#dde7ee' : '#32383e'};
}
.JoySlider-track-fill {
display: block;
position: absolute;
height: 6px;
border-radius: 9999px;
background-color: #0b6bcb;
}
.JoySlider-mark {
position: absolute;
height: 6px;
width: 6px;
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
transform: translateX(-50%);
}
.JoySlider-mark::before {
content: '';
display: inline-block;
width: 2px;
height: 2px;
border-radius: 2px;
background-color: ${isDarkMode ? '#9fa6ad' : '#555e68'};
}
.JoySlider-mark[data-mark-active='true']::before {
background-color: white;
}
.JoySlider-thumb {
position: absolute;
width: 18px;
height: 18px;
box-sizing: border-box;
border-radius: 50%;
background-color: #fefefe;
transform: translateX(-50%);
touch-action: none;
}
.JoySlider-thumb::before {
position: absolute;
content: '';
box-sizing: border-box;
border: 2px solid #0b6bcb;
border-radius: inherit;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.JoySlider-thumb[data-dragging],
.JoySlider-thumb:focus-visible {
outline-offset: 0;
outline: 2px solid #0b6bcb;
outline-width: max(4px, 18px / 3.6);
outline-color: color-mix(in srgb, #0b6bcb 32%, transparent);
}
.SliderTooltip-trigger {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 0;
border-radius: 9999px;
opacity: 0;
cursor: pointer;
}
.SliderTooltip-popup {
font-family: system-ui, sans-serif;
font-size: .875rem;
line-height: 1.5;
background-color: #636B74;
color: white;
padding-inline: .375rem;
border-radius: 2px;
opacity: 0;
}
.SliderTooltip-popup[data-open='true'] {
opacity: 1;
}
.SliderTooltip-arrow {
color: #555e68;
bottom: 0;
border: 4px solid;
border-color: currentColor;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
left: 50%;
transform: translateY(100%);
background-color: transparent;
}
`}
</style>
);
}
Loading

0 comments on commit 2883b65

Please sign in to comment.