Skip to content

Commit

Permalink
Ported Alert, Box, Button stories
Browse files Browse the repository at this point in the history
The stories were ported from the old webui. The stories were chosen
since they only rely on the `primer` CSS-library. Also ported the
`rucio.d.ts` file containing the rucio webui story components proptype
definitions.

In the process, sass support was activated for the Storybook server. In
addition, `@primer/css` was installed (as a depency for the story).
  • Loading branch information
ThePhisch committed Feb 16, 2023
1 parent c9bfc86 commit 4a5be75
Show file tree
Hide file tree
Showing 15 changed files with 1,017 additions and 38 deletions.
3 changes: 2 additions & 1 deletion .storybook/main.js
Expand Up @@ -6,7 +6,8 @@ module.exports = {
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions"
"@storybook/addon-interactions",
"@storybook/preset-scss"
],
"framework": "@storybook/react",
"core": {
Expand Down
559 changes: 523 additions & 36 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion package.json
Expand Up @@ -13,6 +13,7 @@
},
"dependencies": {
"@next/font": "13.1.6",
"@primer/css": "^20.8.2",
"@types/react": "18.0.27",
"@types/react-dom": "18.0.10",
"eslint": "8.33.0",
Expand All @@ -36,14 +37,19 @@
"@storybook/addon-links": "^6.5.16",
"@storybook/builder-webpack5": "^6.5.16",
"@storybook/manager-webpack5": "^6.5.16",
"@storybook/preset-scss": "^1.0.3",
"@storybook/react": "^6.5.16",
"@storybook/testing-library": "^0.0.13",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"babel-loader": "^8.3.0",
"css-loader": "^6.7.3",
"eslint-plugin-storybook": "^0.6.10",
"jest": "^29.4.1",
"jest-environment-jsdom": "^29.4.1",
"node-mocks-http": "^1.12.1"
"node-mocks-http": "^1.12.1",
"sass": "^1.58.1",
"sass-loader": "^13.2.0",
"style-loader": "^3.3.1"
}
}
149 changes: 149 additions & 0 deletions rucio.d.ts
@@ -0,0 +1,149 @@
/************************ Rucio WebUI Story Components PropType Definitions ************************/

interface AlertProps {
open?: boolean
leftIcon?: ReactElement | undefined
rightIcon?: ReactElement | undefined
message?: string | any
variant?: 'primary' | 'warn' | 'success' | 'error'
onClose?: () => void
}

interface BoxProps {
title?: string
type?: 'condensed' | 'spacious' | 'blue' | 'danger'
background?: string
children?: any
}

interface ButtonProps {
icon?: ReactNode
kind?: 'primary' | 'secondary' | 'outline'
show?: 'danger' | 'block' | 'invisible' | 'normal'
size?: 'small' | 'medium' | 'large'
label: string
type?: 'button' | 'submit' | 'reset'
selected?: boolean
disabled?: boolean
onClick?: (args: unknown) => void
}

interface CardProps {
img?: any
header?: ReactElement | string
content: ReactElement
footer?: Array<any>
onCardClick?: (args: unknown) => void
hoverable?: boolean
}

interface CheckboxProps {
isChecked?: boolean
label: string
kind?: 'danger' | 'warning' | 'success' | 'info'
size?: 'small' | 'normal' | 'medium' | 'large'
style?: 'rounded_checkbox' | 'block' | 'no_border' | 'background-color'
type?: 'checkbox' | 'radio'
name?: string
handleChange?: (args: any) => void
}

interface DropdownProps {
label?: string
options?: Array<string>
handleChange?: (args: any) => void
}

interface FormProps {
title?: string
subtitle?: string
children?: any
onSubmit?: (args: unknown) => void
}

interface HeaderProps {
menuActive?: boolean
menuCollapsible?: boolean
user?: {
name: string
}
onLogin?: () => void
onLogout?: () => void
onCreateAccount?: () => void
}

interface ImageProps {
src: string
type?: string
height?: number
width?: number
}

interface InputProps {
type?: string
label?: string
name?: string
placeholder?: string
kind?: 'primary' | 'info' | 'link' | 'normal'
show?: 'danger' | 'warning' | 'success' | 'rounded'
size?: 'small' | 'medium' | 'large'
value?: any
min?: number
max?: number
width?: string | number
focusByDefault?: boolean
onChange?: (args: any) => void
}

interface ModalProps {
active?: boolean
body?: ReactElement
title?: string
onClose?: () => void
}

interface NavProps {
active?: boolean
menuItems?: any
}

interface ProgressBarProps {
title?: string
size?: 'small' | 'medium' | 'large'
type?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'
value?: number
max?: number
}

interface StepsProps {
steps: Array<any>
active?: number
size?: 'small' | 'medium' | 'large'
}

interface TableProps {
id?: string
columns?: string[]
rows?: any[]
footer?: string[]
}

interface TabsProps {
tabs: Array<string>
active: number
alignment?: 'right' | 'centered'
size?: 'small' | 'medium' | 'large'
rounded?: 'toggle' | 'toggle-rounded'
boxed?: 'boxed'
fullwidth?: 'fullwidth'
handleClick: (args: any) => void
}

interface ToggleSwitchProps {
label?: string
kind?: 'danger' | 'warning' | 'success' | 'info'
size?: 'small' | 'normal' | 'medium' | 'large'
style?: 'rounded' | 'outlined'
checked?: boolean
handleChange?: (event: any) => void
}
16 changes: 16 additions & 0 deletions src/component-library/Alert/Alert.stories.tsx
@@ -0,0 +1,16 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'

import { Alert } from './Alert'

export default {
title: 'Components/Alert',
component: Alert,
argTypes: {
background: { control: 'color' },
},
} as ComponentMeta<typeof Alert>

const Template: ComponentStory<typeof Alert> = args => <Alert {...args} />

export const Standard = Template.bind({})
Standard.args = {}
66 changes: 66 additions & 0 deletions src/component-library/Alert/Alert.tsx
@@ -0,0 +1,66 @@
import './alert.scss'

import { useEffect } from 'react'

export const Alert = ({
open = true,
message = 'Flash banner message.',
variant = 'primary',
onClose,
leftIcon = (
<svg
className="octicon octicon-shield-check v-align-bottom"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M11.9275 3.55567C11.9748 3.54134 12.0252 3.54134 12.0725 3.55567L19.3225 5.75264C19.4292 5.78497 19.5 5.88157 19.5 5.99039V11C19.5 13.4031 18.7773 15.3203 17.5164 16.847C16.246 18.3853 14.3925 19.5706 12.0703 20.4278C12.0253 20.4444 11.9746 20.4444 11.9297 20.4278C9.60747 19.5706 7.75398 18.3853 6.48358 16.847C5.2227 15.3203 4.5 13.4031 4.5 11L4.5 5.9904C4.5 5.88158 4.57082 5.78496 4.6775 5.75264L11.9275 3.55567ZM12.5075 2.12013C12.1766 2.01985 11.8234 2.01985 11.4925 2.12013L4.24249 4.3171C3.50587 4.54032 3 5.21807 3 5.9904L3 11C3 13.7306 3.83104 15.9908 5.32701 17.8022C6.81347 19.6021 8.91996 20.9157 11.4102 21.835C11.7904 21.9753 12.2095 21.9753 12.5897 21.835C15.08 20.9157 17.1865 19.6021 18.673 17.8022C20.169 15.9908 21 13.7306 21 11V5.99039C21 5.21804 20.4941 4.54031 19.7575 4.3171L12.5075 2.12013ZM16.2803 9.78033C16.5732 9.48744 16.5732 9.01256 16.2803 8.71967C15.9874 8.42678 15.5126 8.42678 15.2197 8.71967L11 12.9393L9.28033 11.2197C8.98744 10.9268 8.51256 10.9268 8.21967 11.2197C7.92678 11.5126 7.92678 11.9874 8.21967 12.2803L10.4697 14.5303C10.7626 14.8232 11.2374 14.8232 11.5303 14.5303L16.2803 9.78033Z"
></path>
</svg>
),
rightIcon = (
<button
className="flash-close js-flash-close"
type="button"
aria-label="Close"
onClick={onClose}
style={{ marginLeft: 'auto' }}
>
<svg
className="octicon octicon-x"
xmlns="http://www.w3.org/2000/svg"
viewBox="-5 -5 30 30"
width="30"
height="30"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3.72 3.72C3.86062 3.57955 4.05125 3.50066 4.25 3.50066C4.44875 3.50066 4.63937 3.57955 4.78 3.72L8 6.94L11.22 3.72C11.2887 3.64631 11.3715 3.58721 11.4635 3.54622C11.5555 3.50523 11.6548 3.48319 11.7555 3.48141C11.8562 3.47963 11.9562 3.49816 12.0496 3.53588C12.143 3.5736 12.2278 3.62974 12.299 3.70096C12.3703 3.77218 12.4264 3.85702 12.4641 3.9504C12.5018 4.04379 12.5204 4.14382 12.5186 4.24452C12.5168 4.34523 12.4948 4.44454 12.4538 4.53654C12.4128 4.62854 12.3537 4.71134 12.28 4.78L9.06 8L12.28 11.22C12.3537 11.2887 12.4128 11.3715 12.4538 11.4635C12.4948 11.5555 12.5168 11.6548 12.5186 11.7555C12.5204 11.8562 12.5018 11.9562 12.4641 12.0496C12.4264 12.143 12.3703 12.2278 12.299 12.299C12.2278 12.3703 12.143 12.4264 12.0496 12.4641C11.9562 12.5018 11.8562 12.5204 11.7555 12.5186C11.6548 12.5168 11.5555 12.4948 11.4635 12.4538C11.3715 12.4128 11.2887 12.3537 11.22 12.28L8 9.06L4.78 12.28C4.63782 12.4125 4.44977 12.4846 4.25547 12.4812C4.06117 12.4777 3.87579 12.399 3.73837 12.2616C3.60096 12.1242 3.52225 11.9388 3.51882 11.7445C3.51539 11.5502 3.58752 11.3622 3.72 11.22L6.94 8L3.72 4.78C3.57955 4.63938 3.50066 4.44875 3.50066 4.25C3.50066 4.05125 3.57955 3.86063 3.72 3.72Z"
></path>
</svg>
</button>
),
}: AlertProps) => {
useEffect(() => {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
}, [])
return (
<>
{open ? (
<div className={`rucio-alert ${variant} m-l-10 m-r-100`}>
{leftIcon}
{message}
{rightIcon}
</div>
) : null}
</>
)
}
46 changes: 46 additions & 0 deletions src/component-library/Alert/alert.scss
@@ -0,0 +1,46 @@
@import '@primer/css/alerts/index.scss';

@mixin animate($animation, $duration, $method, $times) {
animation: $animation $duration $method $times;
}

@mixin keyframes($name) {
@keyframes #{$name} {
@content;
}
}

.rucio-alert {
@extend .flash;
z-index: 999;
display: flex;
flex-direction: row;
opacity: 1;
position: absolute;
width: 98.5%;
top: 10px;
@include keyframes(customAnimation) {
0% {
top: -50px;
opacity: 0;
}
50% {
top: 10px;
opacity: 1;
}
100% {
top: -50px;
opacity: 0;
}
}
@include animate(customAnimation, 5s, ease-in-out, 1);
&.success {
@extend .flash-success;
}
&.warn {
@extend .flash-warn;
}
&.error {
@extend .flash-error;
}
}
20 changes: 20 additions & 0 deletions src/component-library/Box/Box.stories.tsx
@@ -0,0 +1,20 @@
import { ComponentStory, ComponentMeta } from '@storybook/react'

import { Box } from './Box'
import { BoxBody } from './components/BoxBody'
import { BoxFooter } from './components/BoxFooter'

export default {
title: 'Components/Box',
component: Box,
subcomponents: { BoxBody: BoxBody, BoxFooter: BoxFooter },
} as ComponentMeta<typeof Box>

const Template: ComponentStory<typeof Box> = args => (
<Box {...args}>
<BoxBody />
<BoxFooter />
</Box>
)

export const Primary = Template.bind({})
16 changes: 16 additions & 0 deletions src/component-library/Box/Box.tsx
@@ -0,0 +1,16 @@
import './box.scss'

export const Box = ({
title = 'Sample Box',
type = 'spacious',
children,
}: BoxProps) => {
return (
<div className={`rucio-box ${type}`}>
<div className="header">
<h3 className="title">{title}</h3>
</div>
{children}
</div>
)
}

0 comments on commit 4a5be75

Please sign in to comment.