Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Slider component #164

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions apps/next/src/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export { QueryBuilder } from './query-builder.css';
export { Radio } from './radio.css';
export { SearchField } from './search-field.css';
export { Select } from './select.css';
export { Slider } from './slider.css';
export { Switch } from './switch.css';
export { Tabs } from './tabs.css';
export { TextArea } from './textarea.css';
Expand Down
2 changes: 2 additions & 0 deletions packages/design-system/.ladle/components.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
Radio,
SearchField,
Select,
Slider,
Switch,
Tabs,
TextArea,
Expand Down Expand Up @@ -76,6 +77,7 @@ export const theme: ThemeContext = {
Radio,
SearchField,
Select,
Slider,
Switch,
Tabs,
TextArea,
Expand Down
1 change: 1 addition & 0 deletions packages/design-system/.ladle/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export { QueryBuilder } from './query-builder.css';
export { Radio } from './radio.css';
export { SearchField } from './search-field.css';
export { Select } from './select.css';
export { Slider } from './slider.css';
export { Switch } from './switch.css';
export { Tabs } from './tabs.css';
export { TextArea } from './textarea.css';
Expand Down
145 changes: 145 additions & 0 deletions packages/design-system/.ladle/theme/slider.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { style } from '@vanilla-extract/css';
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I eyeballed all the styles from the pic, so I doubt they're fully accurate. If anything should be tweaked, I am happy to do so!

import {
type SliderState,
// type SliderThumbState,
applyThemeVars,
assignPartialVars,
defaultRadiusVarValues,
defaultSizesVarValues,
genericColorVars,
semanticColorVars,
sliderColorVars,
sliderSpaceVars,
sliderStateVars,
sliderThumbStateVars,
sliderTrackStateVars,
type ThemeContext,
} from '../../src';
import type { SliderThumbState } from '../../src/components/slider/types';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason you're not importing from root? I see it commented out above


export const Slider: ThemeContext['Slider'] = {
slider: {
container: style(
applyThemeVars<SliderState>(sliderStateVars, [
{
vars: assignPartialVars(sliderSpaceVars, {
gridGap: defaultSizesVarValues.v04,
raechelo marked this conversation as resolved.
Show resolved Hide resolved
}),
},
]),
),
min: style(
applyThemeVars<SliderState>(sliderStateVars, [
{
vars: assignPartialVars(
{
color: sliderColorVars,
space: sliderSpaceVars,
},
{
color: {
color: genericColorVars.condition.base.v2,
},
space: {
margin: 'auto 0',
},
},
),
},
]),
),
max: style(
applyThemeVars<SliderState>(sliderStateVars, [
{
vars: assignPartialVars(
{
color: sliderColorVars,
space: sliderSpaceVars,
},
{
color: {
color: genericColorVars.condition.base.v2,
},
space: {
margin: 'auto 0',
},
},
),
},
]),
),
},
thumb: {
container: style(
applyThemeVars<SliderThumbState>(sliderThumbStateVars, [
{
vars: assignPartialVars(sliderSpaceVars, {
width: defaultSizesVarValues.v05,
}),
},
]),
),
thumb: style(
applyThemeVars<SliderThumbState>(sliderThumbStateVars, [
{
vars: assignPartialVars(
{
color: sliderColorVars,
space: sliderSpaceVars,
},
{
color: {
color: semanticColorVars.background.highlight.bold,
},
space: {
height: defaultSizesVarValues.v05,
width: defaultSizesVarValues.v05,
borderRadius: defaultRadiusVarValues.round,
},
},
),
},
{
query: { isHovered: true },
vars: assignPartialVars(sliderColorVars, {
boxShadow: `0px 0px 0 6px rgb(from ${semanticColorVars.background.highlight.bold} r g b / 0.25)`,
raechelo marked this conversation as resolved.
Show resolved Hide resolved
}),
},
]),
),
},
track: {
container: style(
applyThemeVars<SliderState>(sliderTrackStateVars, [
{
vars: assignPartialVars(
{
color: sliderColorVars,
space: sliderSpaceVars,
},
{
color: {
color: semanticColorVars.background.surface.overlay,
},
space: {
trackHeight: defaultSizesVarValues.v02,
trackMargin: `${defaultSizesVarValues.v04} 0`,
},
},
),
},
]),
),
},
input: {
container: style(
applyThemeVars<SliderState>(sliderStateVars, [
{
vars: assignPartialVars(sliderSpaceVars, {
gap: defaultSizesVarValues.v03,
}),
},
]),
),
},
};
17 changes: 17 additions & 0 deletions packages/design-system/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,23 @@ export {
type SelectRenderProps,
type SelectState,
} from './select';
export {
Slider,
SliderContext,
SliderThumb,
SliderTrack,
sliderColorVars,
sliderSpaceVars,
sliderStateVars,
sliderThumbStateVars,
sliderTrackStateVars,
type LabelAlignment,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be prefixed with Slider to not cause a naming conflict

type SliderClassNames,
type SliderProps,
type SliderRenderProps,
type SliderState,
type SliderThumbProps,
} from './slider';
export {
Switch,
SwitchContext,
Expand Down
22 changes: 22 additions & 0 deletions packages/design-system/src/components/slider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// __private-exports
export {
Slider,
SliderContext,
SliderThumb,
SliderTrack,
} from './slider';
export {
sliderColorVars,
sliderSpaceVars,
sliderStateVars,
sliderThumbStateVars,
sliderTrackStateVars,
} from './slider.css';
export {
type LabelAlignment,
type SliderClassNames,
type SliderProps,
type SliderRenderProps,
type SliderState,
type SliderThumbProps,
} from './types';
167 changes: 167 additions & 0 deletions packages/design-system/src/components/slider/slider.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import {
createContainer,
createThemeContract,
style,
} from '@vanilla-extract/css';
import type { SliderClassNames } from './types';
import { layers, typographyVars } from '../../styles';
import { containerQueries } from '@/utils';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's hold off on using import aliases for the moment


const sliderContainers = {
input: createContainer(),
};

export const sliderColorVars = createThemeContract({
color: '',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If fontColor maps to the CSS color, what does color map to? Note to investigate further

thumb: '',
fontColor: '',
boxShadow: '',
});

export const sliderSpaceVars = createThemeContract({
gap: '',
gridGap: '',
height: '',
width: '',
borderRadius: '',
trackHeight: '',
trackMargin: '',
margin: '',
});

export const sliderStateVars = createThemeContract({
alignLabel: '',
orientation: '',
isDisabled: '',
});

export const sliderThumbStateVars = createThemeContract({
isDisabled: '',
isFocused: '',
isHovered: '',
isDragging: '',
isFocusVisible: '',
alignLabel: '',
orientation: '',
});

export const sliderTrackStateVars = createThemeContract({
alignLabel: '',
isDisabled: '',
isHovered: '',
orientation: '',
});

export const sliderClassNames: SliderClassNames = {
slider: {
container: style({
'@layer': {
[layers.components.l1]: {
display: 'grid',
gridTemplateAreas: `'label input'
'track track'
'min max'`,
gridTemplateColumns: '1fr auto',
'@container': containerQueries(sliderStateVars, {
query: { alignLabel: 'left' },
display: 'grid',
raechelo marked this conversation as resolved.
Show resolved Hide resolved
gridTemplateAreas: `'label min track max input'`,
gridTemplateColumns: 'auto auto 4fr auto auto',
raechelo marked this conversation as resolved.
Show resolved Hide resolved
gap: sliderSpaceVars.gridGap,
margin: 'auto 0',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious about why you've hardcoded this here and others were variable. We'll want to look at other components to see which way it should be

}),
},
},
}),
label: style({
'@layer': {
[layers.components.l1]: {
gridArea: 'label',
},
},
}),
min: style({
'@layer': {
[layers.components.l1]: {
gridArea: 'min',
fontFamily: typographyVars.mono,
color: sliderColorVars.color,
'@container': containerQueries(sliderStateVars, {
query: { alignLabel: 'left' },
margin: sliderSpaceVars.margin,
}),
},
},
}),
max: style({
'@layer': {
[layers.components.l1]: {
gridArea: 'max',
fontFamily: typographyVars.mono,
marginLeft: 'auto',
color: sliderColorVars.color,
'@container': containerQueries(sliderStateVars, {
query: { alignLabel: 'left' },
margin: sliderSpaceVars.margin,
}),
},
},
}),
},
track: {
container: style({
'@layer': {
[layers.components.l1]: {
gridArea: 'track',
background: sliderColorVars.color,
height: sliderSpaceVars.trackHeight,
margin: sliderSpaceVars.trackMargin,
'@container': containerQueries(sliderTrackStateVars, {
query: { alignLabel: 'left' },
margin: 'auto 0',
}),
},
},
}),
},
thumb: {
container: style({
' input': {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this is the line that is causing the build to fail. I wasn't sure how to properly address this issue, because the RAC component has an grandchild element of input, which holds a 90px width. The tooltip in the story is hovering over the input rather than the main level component, thus the width change. Below are a few pictures to better explain.

Screenshot 2025-01-13 at 2 48 00 PM Screenshot 2025-01-13 at 2 47 05 PM Screenshot 2025-01-13 at 2 46 51 PM

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, this is how RAC implements the component. You can see the same input width in this screenshot:

Screenshot 2025-01-13 at 2 54 40 PM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll look at this together. But the rule that you appear to be breaking is that (aside from pseudo selectors), styles can only target the current element:
https://vanilla-extract.style/documentation/styling/#complex-selectors

width: sliderSpaceVars.width,
},
}),
thumb: style({
'@layer': {
[layers.components.l1]: {
width: sliderSpaceVars.width,
height: sliderSpaceVars.height,
borderRadius: sliderSpaceVars.borderRadius,
backgroundColor: sliderColorVars.color,
boxShadow: sliderColorVars.boxShadow,
},
},
}),
},
input: {
container: style({
'@layer': {
[layers.components.l1]: {
containerName: sliderContainers.input,
gridArea: 'input',
display: 'flex',
flexDirection: 'row',
gap: sliderSpaceVars.gap,
},
},
}),
},
group: {
container: style({
'@layer': {
[layers.components.l1]: {
gridArea: 'input',
},
},
}),
},
};
Loading
Loading