aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/WidgetParts
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/WidgetParts')
-rw-r--r--src/components/WidgetParts/ExpandableWidget/ExpandableWidget.module.scss146
-rw-r--r--src/components/WidgetParts/ExpandableWidget/ExpandableWidget.tsx47
-rw-r--r--src/components/WidgetParts/List/List.module.scss47
-rw-r--r--src/components/WidgetParts/List/List.tsx7
-rw-r--r--src/components/WidgetParts/OrderedList/OrderedList.module.scss66
-rw-r--r--src/components/WidgetParts/OrderedList/OrderedList.tsx7
-rw-r--r--src/components/WidgetParts/index.tsx5
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 };