-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Web: Modify components, define new types for yaml parse/stringify endpoints #40974
Changes from all commits
61c324f
0cf4c0c
4cb0b65
012bf87
f9ce26e
f0cd924
7858881
68db1dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,40 +16,44 @@ | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
import React, { useEffect, useState } from 'react'; | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
|
||
function SlideTabs({ | ||
import { Indicator, Text } from '..'; | ||
|
||
export function SlideTabs({ | ||
appearance = 'square', | ||
initialSelected = 0, | ||
activeIndex = 0, | ||
name = 'slide-tab', | ||
onChange, | ||
size = 'xlarge', | ||
tabs, | ||
isProcessing = false, | ||
}: props) { | ||
const [activeIndex, setActiveIndex] = useState(initialSelected); | ||
|
||
useEffect(() => { | ||
onChange(activeIndex); | ||
}, [activeIndex]); | ||
|
||
return ( | ||
<Wrapper> | ||
<TabNav role="tablist" appearance={appearance} size={size}> | ||
{tabs.map((tabData, tabIndex) => { | ||
const tabDataType = typeof tabData === 'string'; | ||
const tabName = tabDataType ? tabData : tabData.name; | ||
const tabContent = tabDataType ? tabData : tabData.component; | ||
{tabs.map((tabName, tabIndex) => { | ||
const selected = tabIndex === activeIndex; | ||
return ( | ||
<TabLabel | ||
role="tab" | ||
htmlFor={`${name}-${tabName}`} | ||
onClick={() => setActiveIndex(tabIndex)} | ||
onClick={e => { | ||
e.preventDefault(); | ||
onChange(tabIndex); | ||
}} | ||
itemCount={tabs.length} | ||
key={`${tabName}-${tabIndex}`} | ||
className={tabIndex === activeIndex && 'selected'} | ||
processing={isProcessing} | ||
> | ||
{tabContent} | ||
<Box> | ||
{selected && isProcessing && ( | ||
<Spinner delay="none" size="25px" /> | ||
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. Because of the absolute positioning, the spinner will get rendered outside of the given tab when the browser width is narrow enough. Though I understand that this will be used only in a single place, so I guess it's good enough for now. I suppose the issue was that you didn't want the text of the tab to jump when the spinner gets shown? I wonder if a horizontal progress bar would work here. Connect has one in 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.
yes i'll add a note on this component to look into horizontal progress bar |
||
)} | ||
<Text ml={2}>{tabName}</Text> | ||
</Box> | ||
<TabInput type="radio" name={name} id={`${name}-${tabName}`} /> | ||
</TabLabel> | ||
); | ||
|
@@ -66,19 +70,39 @@ function SlideTabs({ | |
} | ||
|
||
type props = { | ||
// The style to render the selector in. | ||
/** | ||
* The style to render the selector in. | ||
*/ | ||
appearance?: 'square' | 'round'; | ||
// The index that you'd like to select on the initial render. | ||
initialSelected?: number; | ||
// The name you'd like to use for the form if using multiple tabs on the page. | ||
// Default: "slide-tab" | ||
/** | ||
* The index that you'd like to select on the initial render. | ||
*/ | ||
activeIndex: number; | ||
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 change. 👍 I mean controlling the current tab from outside of the component. Could you update the comment and turn all comments into JSDocs? |
||
/** | ||
* The name you'd like to use for the form if using multiple tabs on the page. | ||
* Default: "slide-tab" | ||
*/ | ||
name?: string; | ||
// To be notified when the selected tab changes supply it with this fn. | ||
/** | ||
* To be notified when the selected tab changes supply it with this fn. | ||
*/ | ||
onChange: (selectedTab: number) => void; | ||
// The size to render the selector in. | ||
/** | ||
* The size to render the selector in. | ||
*/ | ||
size?: 'xlarge' | 'medium'; | ||
// A list of tab names that you'd like displayed in the list of tabs. | ||
tabs: string[] | TabComponent[]; | ||
/** | ||
* A list of tab names that you'd like displayed in the list of tabs. | ||
*/ | ||
tabs: string[]; | ||
/** | ||
* If true, renders a spinner and disables clicking on the tabs. | ||
* | ||
* Currently, a spinner is used in absolute positioning which can render | ||
* outside of the given tab when browser width is narrow enough. | ||
* Look into horizontal progress bar (connect has one in LinearProgress.tsx) | ||
*/ | ||
isProcessing?: boolean; | ||
}; | ||
|
||
export type TabComponent = { | ||
|
@@ -97,6 +121,8 @@ const TabLabel = styled.label` | |
padding: 10px; | ||
width: ${props => 100 / props.itemCount}%; | ||
z-index: 1; /* Ensures that the label is above the background slider. */ | ||
opacity: ${p => (p.processing ? 0.5 : 1)}; | ||
pointer-events: ${p => (p.processing ? 'none' : 'auto')}; | ||
`; | ||
|
||
const TabInput = styled.input` | ||
|
@@ -131,4 +157,12 @@ const TabNav = styled.nav` | |
} | ||
`; | ||
|
||
export default SlideTabs; | ||
const Spinner = styled(Indicator)` | ||
color: ${p => p.theme.colors.levels.deep}; | ||
position: absolute; | ||
left: -${p => p.theme.space[4]}px; | ||
`; | ||
|
||
const Box = styled.div` | ||
position: relative; | ||
`; |
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.
Is this
e.preventDefault()
necessary? From what I see, this is just a<label>
, so there's no extra behavior on click. Pointer events are turned off when it's processing too.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.
yeah i was confused by it to, but without the
e.preventDefault
, onChange gets called twice for some reason