diff --git a/.eslintrc b/.eslintrc index f5b072b..98cbdca 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,7 +15,7 @@ "node": true, "es6": true }, - "ignorePatterns": ["dist", "setupTests.ts", "babel.config.js"], + "ignorePatterns": ["dist", "setupTests.ts", "babel.config.js", "www"], "rules": { "comma-dangle": "off", "class-methods-use-this": "off", diff --git a/src/components/Navigation/Horizontal/Divider.tsx b/src/components/Navigation/Horizontal/Divider.tsx new file mode 100644 index 0000000..e24d4ad --- /dev/null +++ b/src/components/Navigation/Horizontal/Divider.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; + +type NavigationDividerProps = React.HTMLAttributes; + +const NavigationDivider = React.forwardRef(( + _, + ref +): React.ReactElement => ( +
+)); + +NavigationDivider.displayName = 'NavigationDivider'; + +export default NavigationDivider; diff --git a/src/components/Navigation/Horizontal/List.tsx b/src/components/Navigation/Horizontal/List.tsx new file mode 100644 index 0000000..01ed89c --- /dev/null +++ b/src/components/Navigation/Horizontal/List.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; + +type NavigationListProps = React.HTMLAttributes; + +const NavigationList = React.forwardRef(( + { + children, + className + }, + ref +): React.ReactElement => ( + +)); + +NavigationList.displayName = 'NavigationList'; +NavigationList.propTypes = { + children: PropTypes.node, + className: PropTypes.string +}; + +export default NavigationList; diff --git a/src/components/Navigation/Horizontal/ListItem.tsx b/src/components/Navigation/Horizontal/ListItem.tsx new file mode 100644 index 0000000..d40b592 --- /dev/null +++ b/src/components/Navigation/Horizontal/ListItem.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; + +interface NavigationListItemProps extends React.HTMLAttributes { + active?: boolean; + icon?: React.ReactElement; +} + +const NavigationListItem = React.forwardRef(( + { + active, + children, + className, + icon + }, + ref +): React.ReactElement => ( +
+ {icon && ( +
+ {icon} +
+ )} + {children} +
+)); + +NavigationListItem.displayName = 'NavigationListItem'; +NavigationListItem.propTypes = { + active: PropTypes.bool, + children: PropTypes.node, + className: PropTypes.string, + icon: PropTypes.element +}; + +export default NavigationListItem; diff --git a/src/components/Navigation/Navigation.tsx b/src/components/Navigation/Navigation.tsx new file mode 100644 index 0000000..ae26fdd --- /dev/null +++ b/src/components/Navigation/Navigation.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { Panel } from '@/components'; +import clsx from 'clsx'; + +interface NavigationProps extends React.HTMLAttributes { + sticky?: boolean; +} + +const Navigation = React.forwardRef(( + { + children, + className, + sticky + }, + ref +): React.ReactElement => ( + +)); + +Navigation.displayName = 'PageNavigation'; +Navigation.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + sticky: PropTypes.bool +} + +export default Navigation; diff --git a/src/components/Navigation/Vertical/Divider.tsx b/src/components/Navigation/Vertical/Divider.tsx new file mode 100644 index 0000000..e24d4ad --- /dev/null +++ b/src/components/Navigation/Vertical/Divider.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; + +type NavigationDividerProps = React.HTMLAttributes; + +const NavigationDivider = React.forwardRef(( + _, + ref +): React.ReactElement => ( +
+)); + +NavigationDivider.displayName = 'NavigationDivider'; + +export default NavigationDivider; diff --git a/src/components/Navigation/Vertical/List.tsx b/src/components/Navigation/Vertical/List.tsx new file mode 100644 index 0000000..01ed89c --- /dev/null +++ b/src/components/Navigation/Vertical/List.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; + +type NavigationListProps = React.HTMLAttributes; + +const NavigationList = React.forwardRef(( + { + children, + className + }, + ref +): React.ReactElement => ( + +)); + +NavigationList.displayName = 'NavigationList'; +NavigationList.propTypes = { + children: PropTypes.node, + className: PropTypes.string +}; + +export default NavigationList; diff --git a/src/components/Navigation/Vertical/ListItem.tsx b/src/components/Navigation/Vertical/ListItem.tsx new file mode 100644 index 0000000..04d82f4 --- /dev/null +++ b/src/components/Navigation/Vertical/ListItem.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { NavigationContext } from './NavigationContext'; + +interface NavigationListItemProps extends React.HTMLAttributes { + active?: boolean; + content?: React.ReactNode; + icon?: React.ReactElement; +} + +const NavigationListItem = React.forwardRef(( + { + active, + children, + className, + icon + }, + ref +): React.ReactElement => { + return ( + + {() => ( +
+ {icon && ( +
+ {icon} +
+ )} + + {children} + +
+ )} +
+ ) +}); + +NavigationListItem.displayName = 'NavigationListItem'; +NavigationListItem.propTypes = { + active: PropTypes.bool, + children: PropTypes.node, + className: PropTypes.string, + icon: PropTypes.element +}; + +export default NavigationListItem; diff --git a/src/components/Navigation/Vertical/NavigationContext.ts b/src/components/Navigation/Vertical/NavigationContext.ts new file mode 100644 index 0000000..2c8c86e --- /dev/null +++ b/src/components/Navigation/Vertical/NavigationContext.ts @@ -0,0 +1,10 @@ +import { createContext } from 'react'; +export interface NavigationContextProps { + tooltipsWhenCollapsed: boolean; + collapsed: boolean; +} + +export const NavigationContext = createContext({ + tooltipsWhenCollapsed: true, + collapsed: false +}); diff --git a/src/components/Navigation/Vertical/Top.tsx b/src/components/Navigation/Vertical/Top.tsx new file mode 100644 index 0000000..df547c1 --- /dev/null +++ b/src/components/Navigation/Vertical/Top.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; + +type NavigationTopProps = React.HTMLAttributes; + +const NavigationTop = React.forwardRef(( + { + children, + className + }, + ref +): React.ReactElement => ( +
+ {children} +
+)); + +NavigationTop.displayName = 'NavigationTop'; +NavigationTop.propTypes = { + children: PropTypes.node, + className: PropTypes.string +} + +export default NavigationTop; diff --git a/src/components/Navigation/Vertical/VerticalNavigationScope.ts b/src/components/Navigation/Vertical/VerticalNavigationScope.ts new file mode 100644 index 0000000..0cacd31 --- /dev/null +++ b/src/components/Navigation/Vertical/VerticalNavigationScope.ts @@ -0,0 +1,4 @@ +export interface VerticalNavigationScope { + collapsed: boolean; + collapse: () => void; +} diff --git a/src/components/Navigation/VerticalNavigation.tsx b/src/components/Navigation/VerticalNavigation.tsx new file mode 100644 index 0000000..9b40ec9 --- /dev/null +++ b/src/components/Navigation/VerticalNavigation.tsx @@ -0,0 +1,110 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { ForwardComponentWithStatics } from '@/components/utils/ForwardComponentWithStatics'; +import { Variant } from '@/components'; +import NavigationTop from '@/components/Navigation/Vertical/Top'; +import NavigationList from '@/components/Navigation/Vertical/List'; +import NavigationListItem from '@/components/Navigation/Vertical/ListItem'; +import NavigationDivider from '@/components/Navigation/Vertical/Divider'; +import { useEffect, useState } from 'react'; +import { VerticalNavigationScope } from '@/components/Navigation/Vertical/VerticalNavigationScope'; +import { NavigationContext } from './Vertical/NavigationContext'; + +export interface VerticalNavigationStatics { + Top: typeof NavigationTop; + List: typeof NavigationList; + Item: typeof NavigationListItem; + Divider: typeof NavigationDivider; +} + +export interface VerticalNavigationProps extends React.HTMLAttributes { + /** + * Variant of the menu. With this prop, the color of the menu can be set. + */ + variant?: Variant | string; + /** + * Indicates whether the menu collapse is controllable. + */ + collapsable?: boolean; + /** + * Indicating whether the menu is collapsed. Can be used to make the navigation a controllable component + */ + collapsed?: boolean; + /** + * Indicates whether a tooltip with the menu text must be shown when menu is collapsed. Default: true + */ + tooltipsWhenCollapsed?: boolean; + /** + * Children of the menu. This can be either a React ChildNode or callback function to access various actions + */ + children: React.ReactNode | ((scope: VerticalNavigationScope) => React.ReactNode); +} + +// @ts-ignore +const VerticalNavigation: ForwardComponentWithStatics = + React.forwardRef(( + { + children, + className, + variant, + collapsed, + tooltipsWhenCollapsed = true + }, + ref + ): React.ReactElement => { + const [isCollapsed, setCollapsed] = useState(false); + + useEffect(() => { + if (collapsed) { + setCollapsed(collapsed); + } + }, [collapsed]) + + const makeScope = (): VerticalNavigationScope => ({ + collapsed: isCollapsed, + collapse: () => setCollapsed(!collapsed) + }); + + children = typeof children === 'function' + ? (children as (scope: VerticalNavigationScope) => React.ReactNode)(makeScope()) + : children; + + return ( + +
+ {children} +
+
+ ) + }); + +VerticalNavigation.displayName = 'VerticalNavigation'; +VerticalNavigation.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + variant: PropTypes.string, + collapsed: PropTypes.bool, + tooltipsWhenCollapsed: PropTypes.bool +} + +VerticalNavigation.Top = NavigationTop; +VerticalNavigation.List = NavigationList; +VerticalNavigation.Item = NavigationListItem; +VerticalNavigation.Divider = NavigationDivider; + + +export default VerticalNavigation; diff --git a/src/components/Navigation/index.ts b/src/components/Navigation/index.ts new file mode 100644 index 0000000..76443bd --- /dev/null +++ b/src/components/Navigation/index.ts @@ -0,0 +1 @@ +export { default as Navigation } from './Navigation'; diff --git a/src/components/Overlay/OverlayTrigger.tsx b/src/components/Overlay/OverlayTrigger.tsx index a6b7630..125eefe 100644 --- a/src/components/Overlay/OverlayTrigger.tsx +++ b/src/components/Overlay/OverlayTrigger.tsx @@ -5,6 +5,7 @@ import Overlay from '@/components/Overlay/index'; import { Placement, PositioningStrategy } from '@popperjs/core'; import { Trigger, triggerPropTypes } from '@/components/Overlay/Trigger'; import { AnimatePresence } from 'framer-motion'; +import { Modifier } from '@popperjs/core/lib/types'; interface OverlayTriggerProps { arrow?: boolean; @@ -15,6 +16,7 @@ interface OverlayTriggerProps { className?: string; trigger?: Trigger | string; motion?: string; + config?: Array>>; } const OverlayTrigger = ({ @@ -25,7 +27,8 @@ const OverlayTrigger = ({ placement, positionStrategy, trigger = 'hover', - motion + motion, + config }: OverlayTriggerProps): React.ReactElement => { const [shown, setShown] = useState(false); const triggerRef = useRef(); @@ -71,6 +74,7 @@ const OverlayTrigger = ({ placement={placement} positionStrategy={positionStrategy} className={className} + config={config} > {overlay} diff --git a/src/components/Overlay/index.tsx b/src/components/Overlay/index.tsx index 14f4840..3a3cb88 100644 --- a/src/components/Overlay/index.tsx +++ b/src/components/Overlay/index.tsx @@ -20,6 +20,7 @@ interface OverlayProps { arrow?: boolean; positionStrategy?: PositioningStrategy; motion?: string; + config?: Array>>; } const Overlay = ({ @@ -29,7 +30,8 @@ const Overlay = ({ placement = 'top', arrow = true, positionStrategy = 'absolute', - motion: triggerMotion + motion: triggerMotion, + config }: React.PropsWithChildren): React.ReactElement => { const ref = useRef(null); const popper = useRef(); @@ -40,7 +42,8 @@ const Overlay = ({ options: { element: '.arrow' } - }] : []) + }] : []), + ...(config || []) ]); const createPopperOptions = (): PopperOptions => ({ diff --git a/src/components/Page/Main.tsx b/src/components/Page/Main.tsx new file mode 100644 index 0000000..ddb57d4 --- /dev/null +++ b/src/components/Page/Main.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; + +type PageMainProps = React.HTMLAttributes; + +const PageMain = React.forwardRef(( + { + children, + className + }, + ref +): React.ReactElement => ( +
+ {children} +
+)); + +PageMain.displayName = 'PageMain'; +PageMain.propTypes = { + children: PropTypes.node, + className: PropTypes.string +} + +export default PageMain; diff --git a/src/components/Page/Page.tsx b/src/components/Page/Page.tsx index 48344b2..19f9bb9 100644 --- a/src/components/Page/Page.tsx +++ b/src/components/Page/Page.tsx @@ -1,14 +1,36 @@ import * as React from 'react'; import clsx from 'clsx'; +import PropTypes from 'prop-types'; import PageHeader from '@/components/Page/Header'; import PageContent from '@/components/Page/Content'; +import PageMain from '@/components/Page/Main'; +import Side from '@/components/Page/Side'; +import PageRight from '@/components/Page/PageRight'; +import PageLeft from '@/components/Page/PageLeft'; +import { ForwardComponentWithStatics } from '@/components/utils/ForwardComponentWithStatics'; +import PageSide from '@/components/Page/Side'; -export type PageProps = React.HTMLAttributes ; +export interface PageProps extends React.HTMLAttributes { + sticky?: boolean; +} -const Page = ({ +export interface PageStatics { + Right: typeof PageRight; + Left: typeof PageLeft; + Header: typeof PageHeader; + Content: typeof PageContent; + Side: typeof PageSide; + Main: typeof PageMain; +} + +// Static properties are not given yet, when declaring the card const. Therefore, the error saying +// that Card is missing above CardStatics properties. These will defined after the card component +// is defined. +// @ts-ignore +const Page: ForwardComponentWithStatics = React.forwardRef(({ children, className, -}: React.PropsWithChildren): React.ReactElement => ( +}): React.ReactElement => (
{children}
-); - +)); +Page.displayName = 'Page'; +Page.Right = PageRight; +Page.Left = PageLeft; Page.Header = PageHeader; Page.Content = PageContent; +Page.Side = Side; +Page.Main = PageMain; + +Page.propTypes = { + children: PropTypes.node, + className: PropTypes.string +} export default Page; diff --git a/src/components/Page/PageContext.ts b/src/components/Page/PageContext.ts new file mode 100644 index 0000000..6a0245b --- /dev/null +++ b/src/components/Page/PageContext.ts @@ -0,0 +1,7 @@ +import { createContext } from 'react'; + +export interface PageContextProps { + +} + +export const PageContext = createContext({}) diff --git a/src/components/Page/PageLeft.tsx b/src/components/Page/PageLeft.tsx new file mode 100644 index 0000000..865d6c7 --- /dev/null +++ b/src/components/Page/PageLeft.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { Variant } from '@/components'; +import PageSide, { Position } from '@/components/Page/Side'; + +export interface PageLeftProps extends React.HTMLAttributes { + fixed?: boolean; + variant?: Variant | string; +} + +const PageLeft = React.forwardRef(( + { + children, + className, + fixed, + }, + ref +): React.ReactElement => ( + + {children} + +)); + +PageLeft.displayName = 'PageLeft'; +PageLeft.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + fixed: PropTypes.bool, + variant: PropTypes.string +} + +export default PageLeft; diff --git a/src/components/Page/PageRight.tsx b/src/components/Page/PageRight.tsx new file mode 100644 index 0000000..ea8fe3c --- /dev/null +++ b/src/components/Page/PageRight.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { Variant } from '@/components'; +import PageSide, { Position } from '@/components/Page/Side'; + +export interface PageRightProps extends React.HTMLAttributes { + spaced?: boolean; + fixed?: boolean; + variant?: Variant | string; +} + +const PageRight = React.forwardRef(( + { + children, + className, + fixed, + }, + ref +): React.ReactElement => ( + + {children} + +)); + +PageRight.displayName = 'PageRight'; +PageRight.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + fixed: PropTypes.bool, + +} + +export default PageRight; diff --git a/src/components/Page/Side.tsx b/src/components/Page/Side.tsx new file mode 100644 index 0000000..614cfd5 --- /dev/null +++ b/src/components/Page/Side.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { Variant } from '@/components'; + +export enum Position { + LEFT = 'left', + RIGHT = 'right' +} + +export interface PageSideProps extends React.HTMLAttributes { + position?: Position | string; + fixed?: boolean; + variant?: Variant | string; +} + +const PageSide = React.forwardRef(( + { + children, + className, + position, + fixed, + }, + ref +): React.ReactElement => ( +
+ {children} +
+)); + +PageSide.displayName = 'Side'; +PageSide.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + position: PropTypes.string, + fixed: PropTypes.bool, + variant: PropTypes.string +} + +export default PageSide; diff --git a/src/components/Panel/Panel.tsx b/src/components/Panel/Panel.tsx index cf4c28a..a52cc41 100644 --- a/src/components/Panel/Panel.tsx +++ b/src/components/Panel/Panel.tsx @@ -1,24 +1,37 @@ import * as React from 'react'; import clsx from 'clsx'; +import PropTypes from 'prop-types'; +import { Variant } from '@/components'; interface PanelProps extends React.HTMLAttributes { spaced?: boolean; + variant?: Variant| string; } -const Panel = ({ +const Panel = React.forwardRef(({ children, className, - spaced -}: React.PropsWithChildren): React.ReactElement => ( + spaced, + variant +}): React.ReactElement => (
{children}
-); +)); + +Panel.displayName = 'Panel'; +Panel.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + spaced: PropTypes.bool, + variant: PropTypes.string +} export default Panel; diff --git a/src/images/coderan/logo.svg b/src/images/coderan/logo.svg new file mode 100644 index 0000000..9a4efe7 --- /dev/null +++ b/src/images/coderan/logo.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/style/base/_typography.scss b/src/style/base/_typography.scss index 77e6cf6..9cd673c 100644 --- a/src/style/base/_typography.scss +++ b/src/style/base/_typography.scss @@ -142,3 +142,7 @@ h6 { .text-secondary { color: variables.color('gray', 'default'); } + +.text-center { + text-align: center; +} diff --git a/src/style/base/_variables.scss b/src/style/base/_variables.scss index 5da7188..9d4beff 100644 --- a/src/style/base/_variables.scss +++ b/src/style/base/_variables.scss @@ -222,9 +222,15 @@ $panel-gutter: 2rem; * 4. Page */ $page-gutter: 2rem; +$page-side-background-color: #fff; +$page-side-border-color: hsl(0, 0%, 88%); +$page-side-gutter: 1rem; :root { --page-gutter: #{$page-gutter}; + --page-side-background-color: #{$page-side-background-color}; + --page-side-border-color: #{$page-side-border-color}; + --page-side-gutter: #{$page-side-gutter}; } /** @@ -568,3 +574,16 @@ $form-field-font-size: 1rem; --form-field-font-weight: #{$form-field-font-weight}; --form-field-font-size: #{$form-field-font-size}; } + +/** + * 9. Navigation + */ +$vertical-navigation-border-color: hsl(0, 0%, 88%); +$vertical-navigation-hover-item-background-color: rgba(0, 0, 0, .05); +$vertical-navigation-active-item-background-color: rgba(0, 0, 0, .1); + +:root { + --vertical-navigation-border-color: #{$vertical-navigation-border-color}; + --vertical-navigation-hover-item-background-color: #{$vertical-navigation-hover-item-background-color}; + --vertical-navigation-active-item-background-color: #{$vertical-navigation-active-item-background-color}; +} diff --git a/src/style/components/_logos.scss b/src/style/components/_logos.scss new file mode 100644 index 0000000..e75bbb4 --- /dev/null +++ b/src/style/components/_logos.scss @@ -0,0 +1,10 @@ +.coderan { + background: url("../images/coderan/logo.svg"); + width: 100px; +} + +.coderan-light { + background: url("../images/coderan/logo-white.svg"); + width: 240px; + height: auto; +} diff --git a/src/style/components/_navigation.scss b/src/style/components/_navigation.scss new file mode 100644 index 0000000..047b9d2 --- /dev/null +++ b/src/style/components/_navigation.scss @@ -0,0 +1,97 @@ +@use "../base/variables"; + +.vertical-navigation-container { + width: 100%; + min-width: 240px; + display: flex; + flex-direction: column; + height: 100vh; + position: relative; + + .vertical-navigation-top { + padding: var(--base-gutter); + display: flex; + align-items: center; + flex-direction: column; + } + + .vertical-navigation-divider { + height: 1px; + background: var(--vertical-navigation-border-color); + width: 100%; + } + + .vertical-navigation-list { + padding: var(--base-gutter); + overflow-y: scroll; + + .vertical-navigation-list-item { + align-items: center; + cursor: pointer; + color: currentColor; + display: flex; + padding: var(--base-gutter); + position: relative; + font: { + weight: 500; + } + + &:hover { + background: var(--vertical-navigation-hover-item-background-color); + } + + &:active { + background: var(--vertical-navigation-active-item-background-color); + } + + .vertical-navigation-list-item-icon { + margin-right: var(--base-gutter); + font: { + size: 1.1rem; + } + } + + &.active { + color: #fff; + background: var(--primary-color); + border-radius: var(--base-border-radius); + } + + &:not(:last-child) { + margin-bottom: var(--base-gutter); + } + } + } + + &.is-collapsed { + min-width: auto; + + .vertical-navigation-list-item { + position: relative; + .vertical-navigation-list-item-icon { + margin-right: 0; + } + + .vertical-navigation-list-item-text { + display: none; + } + } + } +} + +.navigation-primary { + color: variables.color('deep-purple', 'background'); + + .vertical-navigation-list-item { + color: #fff; + } + + .vertical-navigation-divider { + background: var(--primary-color-light-background); + } +} + +.vertical-navigation-tooltip { + margin-left: 0.5rem; + background: #000; +} diff --git a/src/style/components/_page.scss b/src/style/components/_page.scss index 1e3207a..c29b3c6 100644 --- a/src/style/components/_page.scss +++ b/src/style/components/_page.scss @@ -1,7 +1,14 @@ @use "../base/variables"; .page { - background: var(--page-background-color); + display: flex; + flex-flow: row wrap; + + .page-main { + display: flex; + flex-direction: column; + flex: 1 1; + } .page-header { border-bottom: solid 1px var(--base-border-color); @@ -25,4 +32,35 @@ .page-content { padding: var(--page-gutter); } + + .page-side { + flex: 0 0 auto; + background: var(--page-side-background-color); + + &.page-side-right { + border-left: solid 1px var(--page-side-border-color); + } + + &.page-side-left { + border-right: solid 1px var(--page-side-border-color); + } + + &.page-side-fixed { + align-self: flex-start; + position: sticky; + top: 0; + } + } + + .page-top { + width: 100%; + flex: 0 0 100%; + align-self: flex-start; + z-index: 9999; + + &.page-top-sticky { + position: sticky; + top: 0; + } + } } diff --git a/src/style/components/_panel.scss b/src/style/components/_panel.scss index e46dc3a..ce1bd5f 100644 --- a/src/style/components/_panel.scss +++ b/src/style/components/_panel.scss @@ -2,6 +2,10 @@ background: var(--panel-background); &.panel-spaced { - padding: var(--panel-gutter); + padding: var(--base-gutter); + } + + &.panel-primary { + background: var(--primary-color); } } diff --git a/src/style/index.scss b/src/style/index.scss index 251cabe..a276f5d 100644 --- a/src/style/index.scss +++ b/src/style/index.scss @@ -17,6 +17,8 @@ @use "components/tags"; @use "components/overlay"; @use "components/tooltips"; +@use "components/navigation"; +@use "components/logos"; /** * 3. Layout diff --git a/www/src/index.tsx b/www/src/index.tsx index a276c94..79b4808 100644 --- a/www/src/index.tsx +++ b/www/src/index.tsx @@ -1,14 +1,16 @@ import * as React from 'react'; import { useState } from 'react'; import * as ReactDom from 'react-dom'; - import '../../src/style/index.scss'; import { Button, Card, Col, Grid, Icon, Page, Row, SelectField, Tag, TextField, Variant } from '../../src'; +import logoFull from '@/images/coderan/logo.svg'; +import logoLetter from '@/images/coderan/logo-letter.svg'; import Container from '../../src/components/Container/Container'; import FormGroup from '../../src/components/Form/Group'; import FormLabel from '../../src/components/Form/Label'; import FormMessage from '../../src/components/Form/Message'; import Tooltip from '../../src/components/Tooltip'; +import VerticalNavigation from '../../src/components/Navigation/VerticalNavigation'; const TestControllable = () => { const [value, setValue] = useState(''); @@ -34,159 +36,139 @@ const TestControllable = () => { ReactDom.render( - - - - - - - - -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Button colors

- -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- - - - - - - - - - - - -
-
-
-
-
- - - - - - - Col 1/1 - - - Col 1/2 - Col 2/2 - + + + {({ collapse, collapsed }) => ( + <> + + {collapsed ? ( + + ) : ( + + )} + + + + } + content="Home" + /> + } + content="Tooltips" + /> + + + )} + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+

Button colors

+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + + + + + + Col 1/1 + + + Col 1/2 + Col 2/2 + - - Col 1/3 - Col 2/3 - Col 3/4 - + + Col 1/3 + Col 2/3 + Col 3/4 + Col 1/3 @@ -194,1828 +176,1830 @@ ReactDom.render( Col 3/4 - - Col 1/4 - Col 2/4 - Col 3/4 - Col 4/4 - - - - - - - - - - -
Standard input
- Username - -
+ + Col 1/4 + Col 2/4 + Col 3/4 + Col 4/4 + +
+
+
+
+ + + + + +
Standard input
+ Username + +
- -
Input with floating label
- -
+ +
Input with floating label
+ +
- -
Input with default value
- -
+ +
Input with default value
+ +
- -
Input with actions
- { + +
Input with actions
+ { - }} - actions={[ - - ]} - valid={true} - /> -
+ }} + actions={[ + + ]} + valid={true} + /> +
- -
Invalid input
- - - Input is invalid - -
+ +
Invalid input
+ + + Input is invalid + +
- -
Valid input
- -
- -
Valid input
- - - - - - - -
- -
-
- - - - test text - Primary - Danger - Rood - Roze - Paars - Diep-paars - Indigo - Blauw - Lichtblauw - Teal - Groen - Lichtgroen - Limoen - Geel - Amber - Oranje - Bruin - Grijs - Blauwgrijs - - -
- - - - -
Activity
- -
-
- - -
Alert circle
- -
-
- - -
Alert triangle
- -
-
- - -
Archive
- -
-
- - -
Arrow left
- -
-
- - -
Arrow circle down
- -
-
- - -
Arrow circle left
- -
-
- - -
Arrow circle right
- -
-
- - -
Arrow circle up
- -
-
- - -
Sort down
- -
-
- - -
Sort down
- -
-
- - -
Arrow right
- -
-
- - -
Arrow alt left
- -
-
- - -
Arrow alt down
- -
-
- - -
Arrow alt right
- -
-
- - -
Arrow alt up
- -
-
- - -
Sort left
- -
-
- - -
Sort right
- -
-
- - -
Sort up
- -
-
- - -
Arrow up
- -
-
- - -
chevron-double down
- -
-
- - -
chevron-double left
- -
-
- - -
chevron-double right
- -
-
- - -
chevron-double up
- -
-
- - -
At
- -
-
- - -
Attach 2
- -
-
- - -
Attach
- -
-
- - -
Award
- -
-
- - -
Backspace
- -
-
- - -
Bar chart 2
- -
-
- - -
Bar chart
- -
-
- - -
Battery
- -
-
- - -
Behance
- -
-
- - -
Bell off
- -
-
- - -
Bell
- -
-
- - -
Bluetooth
- -
-
- - -
Book open
- -
-
- - -
Book
- -
-
- - -
Bookmark
- -
-
- - -
Briefcase
- -
-
- - -
Browser
- -
-
- - -
Brush
- -
-
- - -
Bulb
- -
-
- - -
Calendar
- -
-
- - -
Camera
- -
-
- - -
Car
- -
-
- - -
Cast
- -
-
- - -
Charging
- -
-
- - -
Checkmark circle 2
- -
-
- - -
Checkmark circle
- -
-
- - -
Checkmark
- -
-
- - -
Checkmark square 2
- -
-
- - -
Checkmark square
- -
-
- - -
Chevron down
- -
-
- - -
Chevron left
- -
-
- - -
Chevron right
- -
-
- - -
Chevron up
- -
-
- - -
Clipboard
- -
-
- - -
Clock
- -
-
- - -
Close circle
- -
-
- - -
Close
- -
-
- - -
Close square
- -
-
- - -
Cloud download
- -
-
- - -
Cloud upload
- -
-
- - -
Code download
- -
-
- - -
Code
- -
-
- - -
Collapse
- -
-
- - -
Color palette
- -
-
- - -
Color picker
- -
-
- - -
Compass
- -
-
- - -
Copy
- -
-
- - -
Corner down left
- -
-
- - -
Corner down right
- -
-
- - -
Corner left down
- -
-
- - -
Corner left up
- -
-
- - -
Corner right down
- -
-
- - -
Corner right up
- -
-
- - -
Corner up left
- -
-
- - -
Corner up right
- -
-
- - -
Credit card
- -
-
- - -
Crop
- -
-
- - -
Cube
- -
-
- - -
Diagonal arrow left down
- -
-
- - -
Diagonal arrow left up
- -
-
- - -
Diagonal arrow right down
- -
-
- - -
Diagonal arrow right up
- -
-
- - -
Done all
- -
-
- - -
Download
- -
-
- - -
Droplet off
- -
-
- - -
Droplet
- -
-
- - -
Edit 2
- -
-
- - -
Edit
- -
-
- - -
Email
- -
-
- - -
Expand
- -
-
- - -
External link
- -
-
- - -
Eye off 2
- -
-
- - -
Eye off
- -
-
- - -
Eye
- -
-
- - -
Facebook
- -
-
- - -
File add
- -
-
- - -
File
- -
-
- - -
File remove
- -
-
- - -
File text
- -
-
- - -
Film
- -
-
- - -
Flag
- -
-
- - -
Flash off
- -
-
- - -
Flash
- -
-
- - -
Flip 2
- -
-
- - -
Flip
- -
-
- - -
Folder add
- -
-
- - -
Folder
- -
-
- - -
Folder remove
- -
-
- - -
Funnel
- -
-
- - -
Gift
- -
-
- - -
Github
- -
-
- - -
Globe 2
- -
-
- - -
Globe
- -
-
- - -
Google
- -
-
- - -
Grid
- -
-
- - -
Hard drive
- -
-
- - -
Hash
- -
-
- - -
Headphones
- -
-
- - -
Heart
- -
-
- - -
Home
- -
-
- - -
Image
- -
-
- - -
Inbox
- -
-
- - -
Info
- -
-
- - -
Keypad
- -
-
- - -
Layers
- -
-
- - -
Layout
- -
-
- - -
Link 2
- -
-
- - -
Link
- -
-
- - -
Linkedin
- -
-
- - -
List
- -
-
- - -
Loader
- -
-
- - -
Lock
- -
-
- - -
Log in
- -
-
- - -
Log out
- -
-
- - -
Map
- -
-
- - -
Maximize
- -
-
- - -
Menu 2
- -
-
- - -
Menu arrow
- -
-
- - -
Menu
- -
-
- - -
Message circle
- -
-
- - -
Message square
- -
-
- - -
Mic off
- -
-
- - -
Mic
- -
-
- - -
Minimize
- -
-
- - -
Minus circle
- -
-
- - -
Minus
- -
-
- - -
Minus square
- -
-
- - -
Monitor
- -
-
- - -
Moon
- -
-
- - -
More horizontal
- -
-
- - -
More vertical
- -
-
- - -
Move
- -
-
- - -
Music
- -
-
- - -
Navigation 2
- -
-
- - -
Navigation
- -
-
- - -
Npm
- -
-
- - -
Options 2
- -
-
- - -
Options
- -
-
- - -
Pantone
- -
-
- - -
Paper plane
- -
-
- - -
Pause circle
- -
-
- - -
People
- -
-
- - -
Percent
- -
-
- - -
user add
- -
-
- - -
user delete
- -
-
- - -
user done
- -
-
- - -
user
- -
-
- - -
user remove
- -
-
- - -
Phone call
- -
-
- - -
Phone missed
- -
-
- - -
Phone off
- -
-
- - -
Phone
- -
-
- - -
Pie chart
- -
-
- - -
Pin
- -
-
- - -
Play circle
- -
-
- - -
Plus circle
- -
-
- - -
Plus
- -
-
- - -
Plus square
- -
-
- - -
Power
- -
-
- - -
Pricetags
- -
-
- - -
Printer
- -
-
- - -
Question mark circle
- -
-
- - -
Question mark
- -
-
- - -
Radio button off
- -
-
- - -
Radio button on
- -
-
- - -
Radio
- -
-
- - -
Recording
- -
-
- - -
Refresh
- -
-
- - -
Repeat
- -
-
- - -
Rewind left
- -
-
- - -
Rewind right
- -
-
- - -
Save
- -
-
- - -
Scissors
- -
-
- - -
Search
- -
-
- - -
Settings 2
- -
-
- - -
Settings
- -
-
- - -
Shake
- -
-
- - -
Share
- -
-
- - -
Shield off
- -
-
- - -
Shield
- -
-
- - -
Shopping bag
- -
-
- - -
Shopping cart
- -
-
- - -
Shuffle 2
- -
-
- - -
Shuffle
- -
-
- - -
Step backwards
- -
-
- - -
Step forward
- -
-
- - -
Slash
- -
-
- - -
Smartphone
- -
-
- - -
Smiling face
- -
-
- - -
Speaker
- -
-
- - -
Square
- -
-
- - -
Star
- -
-
- - -
Stop circle
- -
-
- - -
Sun
- -
-
- - -
Swap
- -
-
- - -
Sync
- -
-
- - -
Text
- -
-
- - -
Thermometer minus
- -
-
- - -
Thermometer
- -
-
- - -
Thermometer plus
- -
-
- - -
Toggle left
- -
-
- - -
Toggle right
- -
-
- - -
Trash 2
- -
-
- - -
Trash
- -
-
- - -
Trending down
- -
-
- - -
Trending up
- -
-
- - -
Tv
- -
-
- - -
Twitter
- -
-
- - -
Umbrella
- -
-
- - -
Undo
- -
-
- - -
Unlock
- -
-
- - -
Upload
- -
-
- - -
Video off
- -
-
- - -
Video
- -
-
- - -
Volume down
- -
-
- - -
Volume mute
- -
-
- - -
Volume off
- -
-
- - -
Volume up
- -
-
- - -
Wifi off
- -
-
- - -
Wifi
- -
-
-
-
-
-
+ +
Valid input
+ +
+ +
Valid input
+ + + + + + + +
+ + + + + + + + + Primary + Danger + Rood + Roze + Paars + Diep-paars + Indigo + Blauw + Lichtblauw + Teal + Groen + Lichtgroen + Limoen + Geel + Amber + Oranje + Bruin + Grijs + Blauwgrijs + + + + + + + +
Activity
+ +
+
+ + +
Alert circle
+ +
+
+ + +
Alert triangle
+ +
+
+ + +
Archive
+ +
+
+ + +
Arrow left
+ +
+
+ + +
Arrow circle down
+ +
+
+ + +
Arrow circle left
+ +
+
+ + +
Arrow circle right
+ +
+
+ + +
Arrow circle up
+ +
+
+ + +
Sort down
+ +
+
+ + +
Sort down
+ +
+
+ + +
Arrow right
+ +
+
+ + +
Arrow alt left
+ +
+
+ + +
Arrow alt down
+ +
+
+ + +
Arrow alt right
+ +
+
+ + +
Arrow alt up
+ +
+
+ + +
Sort left
+ +
+
+ + +
Sort right
+ +
+
+ + +
Sort up
+ +
+
+ + +
Arrow up
+ +
+
+ + +
chevron-double down
+ +
+
+ + +
chevron-double left
+ +
+
+ + +
chevron-double right
+ +
+
+ + +
chevron-double up
+ +
+
+ + +
At
+ +
+
+ + +
Attach 2
+ +
+
+ + +
Attach
+ +
+
+ + +
Award
+ +
+
+ + +
Backspace
+ +
+
+ + +
Bar chart 2
+ +
+
+ + +
Bar chart
+ +
+
+ + +
Battery
+ +
+
+ + +
Behance
+ +
+
+ + +
Bell off
+ +
+
+ + +
Bell
+ +
+
+ + +
Bluetooth
+ +
+
+ + +
Book open
+ +
+
+ + +
Book
+ +
+
+ + +
Bookmark
+ +
+
+ + +
Briefcase
+ +
+
+ + +
Browser
+ +
+
+ + +
Brush
+ +
+
+ + +
Bulb
+ +
+
+ + +
Calendar
+ +
+
+ + +
Camera
+ +
+
+ + +
Car
+ +
+
+ + +
Cast
+ +
+
+ + +
Charging
+ +
+
+ + +
Checkmark circle 2
+ +
+
+ + +
Checkmark circle
+ +
+
+ + +
Checkmark
+ +
+
+ + +
Checkmark square 2
+ +
+
+ + +
Checkmark square
+ +
+
+ + +
Chevron down
+ +
+
+ + +
Chevron left
+ +
+
+ + +
Chevron right
+ +
+
+ + +
Chevron up
+ +
+
+ + +
Clipboard
+ +
+
+ + +
Clock
+ +
+
+ + +
Close circle
+ +
+
+ + +
Close
+ +
+
+ + +
Close square
+ +
+
+ + +
Cloud download
+ +
+
+ + +
Cloud upload
+ +
+
+ + +
Code download
+ +
+
+ + +
Code
+ +
+
+ + +
Collapse
+ +
+
+ + +
Color palette
+ +
+
+ + +
Color picker
+ +
+
+ + +
Compass
+ +
+
+ + +
Copy
+ +
+
+ + +
Corner down left
+ +
+
+ + +
Corner down right
+ +
+
+ + +
Corner left down
+ +
+
+ + +
Corner left up
+ +
+
+ + +
Corner right down
+ +
+
+ + +
Corner right up
+ +
+
+ + +
Corner up left
+ +
+
+ + +
Corner up right
+ +
+
+ + +
Credit card
+ +
+
+ + +
Crop
+ +
+
+ + +
Cube
+ +
+
+ + +
Diagonal arrow left down
+ +
+
+ + +
Diagonal arrow left up
+ +
+
+ + +
Diagonal arrow right down
+ +
+
+ + +
Diagonal arrow right up
+ +
+
+ + +
Done all
+ +
+
+ + +
Download
+ +
+
+ + +
Droplet off
+ +
+
+ + +
Droplet
+ +
+
+ + +
Edit 2
+ +
+
+ + +
Edit
+ +
+
+ + +
Email
+ +
+
+ + +
Expand
+ +
+
+ + +
External link
+ +
+
+ + +
Eye off 2
+ +
+
+ + +
Eye off
+ +
+
+ + +
Eye
+ +
+
+ + +
Facebook
+ +
+
+ + +
File add
+ +
+
+ + +
File
+ +
+
+ + +
File remove
+ +
+
+ + +
File text
+ +
+
+ + +
Film
+ +
+
+ + +
Flag
+ +
+
+ + +
Flash off
+ +
+
+ + +
Flash
+ +
+
+ + +
Flip 2
+ +
+
+ + +
Flip
+ +
+
+ + +
Folder add
+ +
+
+ + +
Folder
+ +
+
+ + +
Folder remove
+ +
+
+ + +
Funnel
+ +
+
+ + +
Gift
+ +
+
+ + +
Github
+ +
+
+ + +
Globe 2
+ +
+
+ + +
Globe
+ +
+
+ + +
Google
+ +
+
+ + +
Grid
+ +
+
+ + +
Hard drive
+ +
+
+ + +
Hash
+ +
+
+ + +
Headphones
+ +
+
+ + +
Heart
+ +
+
+ + +
Home
+ +
+
+ + +
Image
+ +
+
+ + +
Inbox
+ +
+
+ + +
Info
+ +
+
+ + +
Keypad
+ +
+
+ + +
Layers
+ +
+
+ + +
Layout
+ +
+
+ + +
Link 2
+ +
+
+ + +
Link
+ +
+
+ + +
Linkedin
+ +
+
+ + +
List
+ +
+
+ + +
Loader
+ +
+
+ + +
Lock
+ +
+
+ + +
Log in
+ +
+
+ + +
Log out
+ +
+
+ + +
Map
+ +
+
+ + +
Maximize
+ +
+
+ + +
Menu 2
+ +
+
+ + +
Menu arrow
+ +
+
+ + +
Menu
+ +
+
+ + +
Message circle
+ +
+
+ + +
Message square
+ +
+
+ + +
Mic off
+ +
+
+ + +
Mic
+ +
+
+ + +
Minimize
+ +
+
+ + +
Minus circle
+ +
+
+ + +
Minus
+ +
+
+ + +
Minus square
+ +
+
+ + +
Monitor
+ +
+
+ + +
Moon
+ +
+
+ + +
More horizontal
+ +
+
+ + +
More vertical
+ +
+
+ + +
Move
+ +
+
+ + +
Music
+ +
+
+ + +
Navigation 2
+ +
+
+ + +
Navigation
+ +
+
+ + +
Npm
+ +
+
+ + +
Options 2
+ +
+
+ + +
Options
+ +
+
+ + +
Pantone
+ +
+
+ + +
Paper plane
+ +
+
+ + +
Pause circle
+ +
+
+ + +
People
+ +
+
+ + +
Percent
+ +
+
+ + +
user add
+ +
+
+ + +
user delete
+ +
+
+ + +
user done
+ +
+
+ + +
user
+ +
+
+ + +
user remove
+ +
+
+ + +
Phone call
+ +
+
+ + +
Phone missed
+ +
+
+ + +
Phone off
+ +
+
+ + +
Phone
+ +
+
+ + +
Pie chart
+ +
+
+ + +
Pin
+ +
+
+ + +
Play circle
+ +
+
+ + +
Plus circle
+ +
+
+ + +
Plus
+ +
+
+ + +
Plus square
+ +
+
+ + +
Power
+ +
+
+ + +
Pricetags
+ +
+
+ + +
Printer
+ +
+
+ + +
Question mark circle
+ +
+
+ + +
Question mark
+ +
+
+ + +
Radio button off
+ +
+
+ + +
Radio button on
+ +
+
+ + +
Radio
+ +
+
+ + +
Recording
+ +
+
+ + +
Refresh
+ +
+
+ + +
Repeat
+ +
+
+ + +
Rewind left
+ +
+
+ + +
Rewind right
+ +
+
+ + +
Save
+ +
+
+ + +
Scissors
+ +
+
+ + +
Search
+ +
+
+ + +
Settings 2
+ +
+
+ + +
Settings
+ +
+
+ + +
Shake
+ +
+
+ + +
Share
+ +
+
+ + +
Shield off
+ +
+
+ + +
Shield
+ +
+
+ + +
Shopping bag
+ +
+
+ + +
Shopping cart
+ +
+
+ + +
Shuffle 2
+ +
+
+ + +
Shuffle
+ +
+
+ + +
Step backwards
+ +
+
+ + +
Step forward
+ +
+
+ + +
Slash
+ +
+
+ + +
Smartphone
+ +
+
+ + +
Smiling face
+ +
+
+ + +
Speaker
+ +
+
+ + +
Square
+ +
+
+ + +
Star
+ +
+
+ + +
Stop circle
+ +
+
+ + +
Sun
+ +
+
+ + +
Swap
+ +
+
+ + +
Sync
+ +
+
+ + +
Text
+ +
+
+ + +
Thermometer minus
+ +
+
+ + +
Thermometer
+ +
+
+ + +
Thermometer plus
+ +
+
+ + +
Toggle left
+ +
+
+ + +
Toggle right
+ +
+
+ + +
Trash 2
+ +
+
+ + +
Trash
+ +
+
+ + +
Trending down
+ +
+
+ + +
Trending up
+ +
+
+ + +
Tv
+ +
+
+ + +
Twitter
+ +
+
+ + +
Umbrella
+ +
+
+ + +
Undo
+ +
+
+ + +
Unlock
+ +
+
+ + +
Upload
+ +
+
+ + +
Video off
+ +
+
+ + +
Video
+ +
+
+ + +
Volume down
+ +
+
+ + +
Volume mute
+ +
+
+ + +
Volume off
+ +
+
+ + +
Volume up
+ +
+
+ + +
Wifi off
+ +
+
+ + +
Wifi
+ +
+
+
+
+ + +
, document.getElementById('root') ); diff --git a/www/webpack.config.js b/www/webpack.config.js index fc6ec09..a84f9dd 100644 --- a/www/webpack.config.js +++ b/www/webpack.config.js @@ -71,7 +71,7 @@ module.exports = { mode: 'development', devServer: { host: 'localhost', - port: 3000, + port: 3333, open: true, historyApiFallback: true, publicPath: '/',