-
Notifications
You must be signed in to change notification settings - Fork 0
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
30 react-aria poc #34
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
@import "../styles/theme.css"; | ||
|
||
.react-aria-Toolbar { | ||
display: flex; | ||
flex-wrap: wrap; | ||
gap: 5px; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that most, if not all of these hard-coded pixel values should either be set globally e.g., |
||
|
||
&[data-orientation=horizontal] { | ||
flex-direction: row; | ||
} | ||
|
||
.react-aria-Group { | ||
display: contents; | ||
} | ||
|
||
.react-aria-ToggleButton { | ||
width: 32px; | ||
} | ||
} | ||
|
||
.react-aria-Separator { | ||
align-self: stretch; | ||
background-color: var(--border-color); | ||
|
||
&[aria-orientation=vertical] { | ||
width: 1px; | ||
margin: 0px 10px; | ||
} | ||
} | ||
|
||
.react-aria-Button { | ||
color: var(--text-color); | ||
background: var(--button-background); | ||
border: 1px solid var(--border-color); | ||
border-radius: 4px; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be a global var, or a property. Some applications won't need rounded buttons. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right. Everything here so far has been taken straight from the react-aria example documentation. We'll need to put more thought into what is specific to each component vs what is applied across all components in the library. We'll provide some level of customization through a design tokens file and css variables but we'll need to put some thought into the level of customization that will be required (it could potentially be very overwhelming so we'll need to strike a balance) |
||
appearance: none; | ||
vertical-align: middle; | ||
font-size: 1rem; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a very small font size. Again should be inherited. |
||
text-align: center; | ||
margin: 0; | ||
outline: none; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good to know. Again, this is from an example in the docs but can be changed easily There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this removal is to resolve some janky issues that outlines can have with borders,.It looks like it's addressed in the following rules. |
||
padding: 6px 10px; | ||
text-decoration: none; | ||
min-width: 34.5px; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if decimal pixel values are supported in all browsers, or if they'll behave in a way that makes sense to devs. I would round for clarity. |
||
|
||
&[data-pressed] { | ||
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1); | ||
background: var(--button-background-pressed); | ||
border-color: var(--border-color-pressed); | ||
} | ||
|
||
&[data-focus-visible] { | ||
outline: 2px solid var(--focus-ring-color); | ||
outline-offset: -1px; | ||
} | ||
|
||
&[data-disabled]{ | ||
border-color: var(--border-color-disabled); | ||
color: var(--text-color-disabled); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import PropTypes, { string } from "prop-types"; | ||
import React from "react"; | ||
import {Button, Toolbar} from 'react-aria-components' | ||
import { Icon } from "../core/Icon"; | ||
|
||
import "./LayerButtonReel.css"; | ||
|
||
export const LayerButtonReel = ({ buttons, label }) => ( | ||
<Toolbar aria-label={label}> | ||
{buttons && | ||
Object.keys(buttons).map((key) => ( | ||
<Button onClick={buttons[key]}><Icon iconName={key} /></Button> | ||
))} | ||
</Toolbar> | ||
); | ||
|
||
LayerButtonReel.propTypes = { | ||
buttons: PropTypes.objectOf(PropTypes.func), | ||
label: string.isRequired, | ||
}; | ||
|
||
LayerButtonReel.defaultProps = { | ||
buttons: null, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
@import "../styles/theme.css"; | ||
|
||
.layerCardWrapper { | ||
padding: 0 8px; | ||
} | ||
|
||
.react-aria-Switch { | ||
display: flex; | ||
align-items: center; | ||
gap: 0.571rem; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where do these values come from? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All from examples in the docs |
||
font-size: 1.143rem; | ||
color: var(--text-color); | ||
forced-color-adjust: none; | ||
|
||
.indicator { | ||
width: 2rem; | ||
height: 1.143rem; | ||
border: 2px solid var(--border-color); | ||
background: var(--background-color); | ||
border-radius: 1.143rem; | ||
transition: all 200ms; | ||
|
||
&:before { | ||
content: ''; | ||
display: block; | ||
margin: 0.143rem; | ||
width: 0.857rem; | ||
height: 0.857rem; | ||
background: var(--highlight-background); | ||
border-radius: 16px; | ||
transition: all 200ms; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe needs a prefers-reduced-motion media query. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it essentially be the same, but with no transition? |
||
} | ||
} | ||
|
||
&[data-pressed] .indicator { | ||
border-color: var(--border-color-pressed); | ||
|
||
&:before { | ||
background: var(--highlight-background-pressed); | ||
} | ||
} | ||
|
||
&[data-selected] { | ||
.indicator { | ||
border-color: var(--highlight-background); | ||
background: var(--highlight-background); | ||
|
||
&:before { | ||
background: var(--field-background); | ||
transform: translateX(100%); | ||
} | ||
} | ||
|
||
&[data-pressed] { | ||
.indicator { | ||
border-color: var(--highlight-background-pressed); | ||
background: var(--highlight-background-pressed); | ||
} | ||
} | ||
} | ||
|
||
&[data-focus-visible] .indicator { | ||
outline: 2px solid var(--focus-ring-color); | ||
outline-offset: 2px; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import PropTypes from "prop-types"; | ||
import React from "react"; | ||
import {Switch} from 'react-aria-components'; | ||
import { LayerButtonReel } from "./LayerButtonReel"; | ||
import "./LayerCard.css"; | ||
|
||
export const LayerCard = ({ layerName, isActive, onChange, buttons }) => ( | ||
<div className="layerCard"> | ||
<div className="layerCardWrapper"> | ||
<Switch | ||
isSelected={isActive} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is from the react-aria library. It related to making it a "controlled component" in react terms.
I think if we go with this library there are a few quirks like this. They're well documented but deviate from traditional HTML. We'll need to decide if it's worth the tradeoff. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can change the isActive prop to isSelected for consistency if we want. As @JBurkinshaw says we will have to catch and update a bunch of these inconsistencies when adopting the library. |
||
onChange={onChange} | ||
> | ||
<div className="indicator" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self-closing div? Is this a react thing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I think so. The auto formatting changes this |
||
{layerName} | ||
</Switch> | ||
<LayerButtonReel buttons={buttons} /> | ||
</div> | ||
</div> | ||
); | ||
|
||
LayerCard.propTypes = { | ||
layerName: PropTypes.string.isRequired, | ||
isActive: PropTypes.bool, | ||
onChange: PropTypes.func.isRequired, | ||
buttons: PropTypes.objectOf(PropTypes.func), | ||
}; | ||
|
||
LayerCard.defaultProps = { | ||
isActive: false, | ||
buttons: null, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
@import "../styles/theme.css"; | ||
|
||
.react-aria-Slider { | ||
display: grid; | ||
grid-template-areas: "label output" | ||
"track track"; | ||
grid-template-columns: 1fr auto; | ||
max-width: 300px; | ||
color: var(--text-color); | ||
|
||
.react-aria-Label { | ||
grid-area: label; | ||
} | ||
|
||
.react-aria-SliderOutput { | ||
grid-area: output; | ||
} | ||
|
||
.react-aria-SliderTrack { | ||
grid-area: track; | ||
position: relative; | ||
|
||
/* track line */ | ||
&:before { | ||
content: ''; | ||
display: block; | ||
position: absolute; | ||
background: var(--border-color); | ||
} | ||
} | ||
|
||
.react-aria-SliderThumb { | ||
width: 1.429rem; | ||
height: 1.429rem; | ||
border-radius: 50%; | ||
background: var(--highlight-background); | ||
border: 2px solid var(--background-color); | ||
forced-color-adjust: none; | ||
|
||
&[data-dragging] { | ||
background: var(--highlight-background-pressed); | ||
} | ||
|
||
&[data-focus-visible] { | ||
outline: 2px solid var(--focus-ring-color); | ||
} | ||
} | ||
|
||
&[data-orientation=horizontal] { | ||
flex-direction: column; | ||
width: 300px; | ||
|
||
.react-aria-SliderTrack { | ||
height: 30px; | ||
width: 100%; | ||
|
||
&:before { | ||
height: 3px; | ||
width: 100%; | ||
top: 50%; | ||
transform: translateY(-50%); | ||
} | ||
} | ||
|
||
.react-aria-SliderThumb { | ||
top: 50%; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Label, Slider, SliderOutput, SliderThumb, SliderTrack } from 'react-aria-components'; | ||
import "./SliderControl.css"; | ||
|
||
export const SliderControl = ({ title, units, sliderConfig }) => ( | ||
<div> | ||
<h3 className="ui-label">{title}</h3> | ||
{sliderConfig && | ||
sliderConfig.map((slider) => { | ||
const { label, min, max, step, value, onChange } = slider; | ||
|
||
return <Slider | ||
minValue={min} | ||
maxValue={max} | ||
step={step} | ||
value={value} | ||
onChange={onChange} | ||
> | ||
<Label>{label}</Label> | ||
<SliderOutput> | ||
{({ state }) => <>{state.getThumbValueLabel(0)}{units}</>} | ||
</SliderOutput> | ||
<SliderTrack> | ||
<SliderThumb name={label}/> | ||
</SliderTrack> | ||
</Slider> | ||
})} | ||
</div> | ||
); | ||
|
||
SliderControl.propTypes = { | ||
title: PropTypes.string.isRequired, | ||
units: PropTypes.string.isRequired, | ||
sliderConfig: PropTypes.arrayOf(PropTypes.objectOf(PropTypes.string)) | ||
.isRequired, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.swatch-legend { | ||
display: grid; | ||
grid-template-columns: auto; | ||
grid-template-rows: auto; | ||
} | ||
|
||
.swatch-container { | ||
margin: 4px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Swatch } from "../core-react-aria/Swatch"; | ||
import "./SwatchLegend.css"; | ||
|
||
export const SwatchLegend = ({ swatches }) => ( | ||
<div className="swatch-legend"> | ||
{swatches && | ||
swatches.map((swatch) => { | ||
const { color, label, value, units } = swatch; | ||
|
||
return ( | ||
<Swatch | ||
key={label} | ||
label={label} | ||
color={color} | ||
value={value} | ||
units={units} | ||
/> | ||
); | ||
})} | ||
</div> | ||
); | ||
|
||
SwatchLegend.propTypes = { | ||
swatches: PropTypes.arrayOf(PropTypes.objectOf(PropTypes.string)) | ||
.isRequired, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* Swatch container */ | ||
.swatch-container { | ||
display: grid; | ||
grid-template-columns: min-content 1fr max-content; | ||
align-items: center; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
/* Swatch label */ | ||
.swatch-label { | ||
font-size: 14px; | ||
margin: 0 8px; | ||
} | ||
|
||
/* Swatch value */ | ||
.swatch-value { | ||
font-size: 14px; | ||
} | ||
|
||
.react-aria-ColorSwatch { | ||
width: 20px; | ||
height: 20px; | ||
border-radius: 4px; | ||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably don't need
react-aria
in the class name.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the default for the components in react-aria