diff options
Diffstat (limited to 'src/components/WidgetParts')
7 files changed, 325 insertions, 0 deletions
diff --git a/src/components/WidgetParts/ExpandableWidget/ExpandableWidget.module.scss b/src/components/WidgetParts/ExpandableWidget/ExpandableWidget.module.scss new file mode 100644 index 0000000..058d805 --- /dev/null +++ b/src/components/WidgetParts/ExpandableWidget/ExpandableWidget.module.scss @@ -0,0 +1,146 @@ +@use "@styles/abstracts/functions" as fun; +@use "@styles/abstracts/mixins" as mix; + +.title { + margin: 0; + padding: 0; + background: none; + font-size: var(--font-size-xl); + text-align: left; +} + +.icon { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: center; + width: fun.convert-px(30); + height: fun.convert-px(30); + background: var(--color-bg); + border: fun.convert-px(1) solid var(--color-primary); + border-radius: fun.convert-px(3); + color: var(--color-primary); + font-weight: 800; + transition: all 0.25s ease-in-out 0s; + + &::before, + &::after { + content: ""; + background: var(--color-primary); + transition: all 0.4s ease-out 0s; + } + + &::before { + width: 10%; + height: 60%; + position: relative; + left: 30%; + } + + &::after { + width: 60%; + height: 10%; + position: relative; + left: -5%; + } +} + +.body { + width: 100%; + margin: 0; + overflow-y: auto; + visibility: hidden; + opacity: 0; + height: 0; + transition: all 0.5s ease-in-out 0s; + + &--borders { + border: fun.convert-px(2) solid var(--color-primary-dark); + } + + > *:last-child { + margin-bottom: 0; + } + + @include mix.media("screen") { + @include mix.dimensions("md") { + font-size: var(--font-size-sm); + font-weight: 500; + } + } +} + +.header { + flex: 0 0 auto; + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: space-between; + gap: var(--spacing-md); + width: 100%; + min-height: var(--header-height); + position: sticky; + top: 0; + background: var(--color-bg); + border: none; + border-bottom: fun.convert-px(2) solid var(--color-primary-dark); + cursor: pointer; + transition: background 0.2s ease-in-out 0s; + + > button { + padding: 0 var(--spacing-xs); + } +} + +.wrapper--expanded .icon { + &::before { + height: 0; + } +} + +.header:hover, +.header:focus { + .icon { + background: var(--color-primary-light); + color: var(--color-fg-inverted); + transform: scale(1.2); + + &::before, + &::after { + background: var(--color-bg); + } + } +} + +.wrapper { + --header-height: #{fun.convert-px(65)}; + + display: flex; + flex-flow: column; + min-height: var(--header-height); + position: relative; + overflow-y: hidden; + + &:first-of-type { + .header { + border-top: fun.convert-px(2) solid var(--color-primary-dark); + } + } +} + +.wrapper--expanded { + ~ .wrapper { + .header { + border-top: fun.convert-px(2) solid var(--color-primary-dark); + } + } + + .body { + visibility: visible; + opacity: 1; + min-height: inherit; + height: 100%; + margin: var(--spacing-sm) 0; + transition: all 0.45s ease-in-out 0s; + } +} diff --git a/src/components/WidgetParts/ExpandableWidget/ExpandableWidget.tsx b/src/components/WidgetParts/ExpandableWidget/ExpandableWidget.tsx new file mode 100644 index 0000000..52b5c06 --- /dev/null +++ b/src/components/WidgetParts/ExpandableWidget/ExpandableWidget.tsx @@ -0,0 +1,47 @@ +import { t } from '@lingui/macro'; +import { TitleLevel } from '@ts/types/app'; +import { ReactNode, useState } from 'react'; +import styles from './ExpandableWidget.module.scss'; + +const ExpandableWidget = ({ + children, + title, + titleLevel = 2, + expand = false, + withBorders = false, +}: { + children: ReactNode; + title: string; + titleLevel?: TitleLevel; + expand?: boolean; + withBorders?: boolean; +}) => { + const [isExpanded, setIsExpanded] = useState<boolean>(expand); + + const handleExpanse = () => setIsExpanded((prev) => !prev); + + const TitleTag = `h${titleLevel}` as keyof JSX.IntrinsicElements; + + const wrapperClasses = `${styles.wrapper} ${ + isExpanded ? styles['wrapper--expanded'] : '' + }`; + + const bodyClasses = `${styles.body} ${ + withBorders ? styles['body--borders'] : '' + }`; + + return ( + <div className={wrapperClasses}> + <button type="button" className={styles.header} onClick={handleExpanse}> + <span className="screen-reader-text"> + {isExpanded ? t`Collapse` : t`Expand`} + </span> + <TitleTag className={styles.title}>{title}</TitleTag> + <span className={styles.icon} aria-hidden={true}></span> + </button> + <div className={bodyClasses}>{children}</div> + </div> + ); +}; + +export default ExpandableWidget; diff --git a/src/components/WidgetParts/List/List.module.scss b/src/components/WidgetParts/List/List.module.scss new file mode 100644 index 0000000..5da5741 --- /dev/null +++ b/src/components/WidgetParts/List/List.module.scss @@ -0,0 +1,47 @@ +@use "@styles/abstracts/functions" as fun; + +.list { + margin: 0; + padding: 0; + list-style-type: none; + + .list { + border: none; + border-top: fun.convert-px(1) solid var(--color-primary-dark); + } + + li { + margin: 0; + + &:not(:last-of-type) { + border-bottom: fun.convert-px(1) solid var(--color-primary-dark); + } + } + + a { + display: flex; + flex-flow: row nowrap; + width: 100%; + padding: var(--spacing-2xs) var(--spacing-xs); + background: none; + text-decoration: underline solid transparent 0; + transition: all 0.16s ease-in-out 0s, text-decoration-color 0s; + + &:hover, + &:focus { + background: var(--color-bg-secondary); + } + + &:focus { + color: var(--color-primary); + text-decoration-color: var(--color-primary-light); + text-decoration-thickness: 0.25ex; + } + + &:active { + background: var(--color-bg-tertiary); + text-decoration-color: transparent; + text-decoration-thickness: 0; + } + } +} diff --git a/src/components/WidgetParts/List/List.tsx b/src/components/WidgetParts/List/List.tsx new file mode 100644 index 0000000..317c4d1 --- /dev/null +++ b/src/components/WidgetParts/List/List.tsx @@ -0,0 +1,7 @@ +import styles from './List.module.scss'; + +const List = ({ items }: { items: Array<any> }) => { + return <ul className={styles.list}>{items}</ul>; +}; + +export default List; diff --git a/src/components/WidgetParts/OrderedList/OrderedList.module.scss b/src/components/WidgetParts/OrderedList/OrderedList.module.scss new file mode 100644 index 0000000..a286932 --- /dev/null +++ b/src/components/WidgetParts/OrderedList/OrderedList.module.scss @@ -0,0 +1,66 @@ +@use "@styles/abstracts/functions" as fun; +@use "@styles/abstracts/placeholders"; + +.list { + @extend %reset-ordered-list; + counter-reset: link; + + .list { + border-top: fun.convert-px(1) solid var(--color-primary-dark); + } + + a { + display: flex; + flex-flow: row nowrap; + width: 100%; + padding: var(--spacing-2xs) var(--spacing-xs); + background: none; + text-decoration: underline solid transparent 0; + transition: all 0.16s ease-in-out 0s, text-decoration-color 0s; + counter-increment: link; + + &:hover, + &:focus { + background: var(--color-bg-secondary); + } + + &:focus { + color: var(--color-primary); + text-decoration-color: var(--color-primary-light); + text-decoration-thickness: 0.25ex; + } + + &:active { + background: var(--color-bg-tertiary); + text-decoration-color: transparent; + text-decoration-thickness: 0; + } + + &::before { + content: counters(link, ".") ". "; + color: var(--color-secondary); + padding-right: var(--spacing-2xs); + } + } + + li { + width: 100%; + margin: 0; + + &:not(:last-of-type) { + border-bottom: fun.convert-px(1) solid var(--color-primary-dark); + } + + &::before { + display: none; + } + } + + li li a::before { + padding-left: var(--spacing-sm); + } + + li li li a::before { + padding-left: var(--spacing-lg); + } +} diff --git a/src/components/WidgetParts/OrderedList/OrderedList.tsx b/src/components/WidgetParts/OrderedList/OrderedList.tsx new file mode 100644 index 0000000..a12ec06 --- /dev/null +++ b/src/components/WidgetParts/OrderedList/OrderedList.tsx @@ -0,0 +1,7 @@ +import styles from './OrderedList.module.scss'; + +const OrderedList = ({ items }: { items: Array<any> }) => { + return <ol className={styles.list}>{items}</ol>; +}; + +export default OrderedList; diff --git a/src/components/WidgetParts/index.tsx b/src/components/WidgetParts/index.tsx new file mode 100644 index 0000000..59df3bd --- /dev/null +++ b/src/components/WidgetParts/index.tsx @@ -0,0 +1,5 @@ +import ExpandableWidget from './ExpandableWidget/ExpandableWidget'; +import List from './List/List'; +import OrderedList from './OrderedList/OrderedList'; + +export { ExpandableWidget, List, OrderedList }; |
