diff --git a/src/App.vue b/src/App.vue index f31215213943ffadf45a87ff4c7a3e41c07db0c4..12b543a28e6ec2ff64f8ef15f824d4db22f79206 100644 --- a/src/App.vue +++ b/src/App.vue @@ -98,6 +98,10 @@ import PlusIcon from '@stories/icons/Mono/PlusIcon.vue'; import PointerIcon from '@stories/icons/Mono/PointerIcon.vue'; import SaveIcon from '@stories/icons/Mono/SaveIcon.vue'; import SettingsIcon from '@stories/icons/Mono/SettingsIcon.vue'; +import SortHorizontalIcon from '@stories/icons/Mono/SortHorizontalIcon.vue'; +import SortDownIcon from '@stories/icons/Mono/SortDownIcon.vue'; +import SortUpIcon from '@stories/icons/Mono/SortUpIcon.vue'; +import SortVerticalIcon from '@stories/icons/Mono/SortVerticalIcon.vue'; import LineIcon from '@stories/icons/Mono/LineIcon.vue'; import TableIcon from '@stories/icons/Mono/TableIcon.vue'; import TrashIcon from '@stories/icons/Mono/TrashIcon.vue'; @@ -213,6 +217,10 @@ const gentleIcons = { PointerIcon, SaveIcon, SettingsIcon, + SortDownIcon, + SortHorizontalIcon, + SortUpIcon, + SortVerticalIcon, TableIcon, TrashIcon, TriangleIcon, @@ -420,6 +428,7 @@ const sliderValue = ref(1); display: grid; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; gap: 10px; + margin-bottom: 20px; } .iconsItem { font-size: 14px; diff --git a/src/common/constants/icons.ts b/src/common/constants/icons.ts index 892a811cdd65c74e7434ef955c25de7458a168ff..83bd219a1d28eccfa66ed003bfad9ba2f4d9e42a 100644 --- a/src/common/constants/icons.ts +++ b/src/common/constants/icons.ts @@ -103,6 +103,10 @@ import TableIcon from '@stories/icons/Mono/TableIcon.vue'; import TrashIcon from '@stories/icons/Mono/TrashIcon.vue'; import UserIcon from '@stories/icons/Mono/UserIcon.vue'; import TriangleIcon from '@stories/icons/Mono/TriangleIcon.vue'; +import SortHorizontalIcon from '@stories/icons/Mono/SortHorizontalIcon.vue'; +import SortDownIcon from '@stories/icons/Mono/SortDownIcon.vue'; +import SortUpIcon from '@stories/icons/Mono/SortUpIcon.vue'; +import SortVerticalIcon from '@stories/icons/Mono/SortVerticalIcon.vue'; export const iconsSet: Record<string, Component> = { Age18Icon: Age18Icon, @@ -204,6 +208,10 @@ export const iconsSet: Record<string, Component> = { PointerIcon: PointerIcon, SaveIcon: SaveIcon, SettingsIcon: SettingsIcon, + SortDownIcon, + SortHorizontalIcon, + SortUpIcon, + SortVerticalIcon, TableIcon: TableIcon, TrashIcon: TrashIcon, TriangleIcon: TriangleIcon, diff --git a/src/common/interfaces/componentsProp.ts b/src/common/interfaces/componentsProp.ts index 38144bc9d8e54d068dcca56e226d76e85deffc96..7ada68de9bbeaea1d0ffcedf2066ba614572e8f9 100644 --- a/src/common/interfaces/componentsProp.ts +++ b/src/common/interfaces/componentsProp.ts @@ -3,7 +3,10 @@ import type { TDarkness, TIcons, TPosition, TTextStyle, TThemeColor } from '@int export interface ITableColumn { name: string; type?: TTableColumnType; - isFilter?: boolean; + editable?: boolean; + filterable?: boolean; + sortable?: boolean; + padding?: string; } export interface ITableItem { diff --git a/src/common/interfaces/componentsProps.ts b/src/common/interfaces/componentsProps.ts index b628fca0649e9fdc45dd79a6aedae7ab8d65697b..8f1d2168e530c41c72d17273cf8451a72877f9ae 100644 --- a/src/common/interfaces/componentsProps.ts +++ b/src/common/interfaces/componentsProps.ts @@ -30,6 +30,7 @@ export interface ITableProps { fontSize?: string; showAllLines?: boolean; stripedRows?: boolean; + center?: boolean; } export interface ITLProps { diff --git a/src/stories/components/Button/Button.stories.ts b/src/stories/components/Button/Button.stories.ts index f14c35f5260a91a35314d7916ae9f6ebd28676a5..eaefe1f2601624a2703192b16033eda1d169017c 100644 --- a/src/stories/components/Button/Button.stories.ts +++ b/src/stories/components/Button/Button.stories.ts @@ -72,7 +72,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: {}, }; diff --git a/src/stories/components/Divider/Divider.stories.ts b/src/stories/components/Divider/Divider.stories.ts index a10ca583897959f71fdae48ddb8f9c2c4079bce4..aed2c5658ff47ccd3f562cf97276c625e5089a58 100644 --- a/src/stories/components/Divider/Divider.stories.ts +++ b/src/stories/components/Divider/Divider.stories.ts @@ -49,7 +49,7 @@ type Story = StoryObj<typeof meta>; * See https://storybook.js.org/docs/api/csf * to learn how to use render functions. */ -export const Primary: Story = { +export const Simple: Story = { args: {}, }; diff --git a/src/stories/components/Drawer/Drawer.stories.ts b/src/stories/components/Drawer/Drawer.stories.ts index f4320b628ee8cce444b1e87271dbe9b787064369..4ecd4442c8adb245f70e5e10b07941a1d2d50729 100644 --- a/src/stories/components/Drawer/Drawer.stories.ts +++ b/src/stories/components/Drawer/Drawer.stories.ts @@ -76,7 +76,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { visible: true, default: 'Какой-то текÑÑ‚.', diff --git a/src/stories/components/MenuDial/MenuDial.stories.ts b/src/stories/components/MenuDial/MenuDial.stories.ts index 89c4739e83dd9ad255078986f24e9e41ab2c562d..ba5314da02b9733cb9e4900f2887f55061124591 100644 --- a/src/stories/components/MenuDial/MenuDial.stories.ts +++ b/src/stories/components/MenuDial/MenuDial.stories.ts @@ -67,7 +67,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { items: [ { diff --git a/src/stories/components/Modal/Modal.stories.ts b/src/stories/components/Modal/Modal.stories.ts index 6ac70ab164ee629755bba221dc4901568552969d..d8e3e292a7431b6dc72f76ecbf7b2858cc684138 100644 --- a/src/stories/components/Modal/Modal.stories.ts +++ b/src/stories/components/Modal/Modal.stories.ts @@ -77,7 +77,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { visible: true, header: 'Modal', diff --git a/src/stories/components/Popup/Popup.stories.ts b/src/stories/components/Popup/Popup.stories.ts index e1e63139a85b9400b93fc7d2a7242cbc99dac019..29237c646b459be379f0c09803d9819304e13c5e 100644 --- a/src/stories/components/Popup/Popup.stories.ts +++ b/src/stories/components/Popup/Popup.stories.ts @@ -48,7 +48,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { default: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet fugiat harum maiores placeat\n soluta, vel velit voluptas. Accusamus aut, error et minima neque praesentium, ratione,\n reprehenderit repudiandae saepe ut vero! Lorem ipsum dolor sit amet, consectetur adipisicing\n elit. Amet fugiat harum maiores placeat soluta, vel velit voluptas. Accusamus aut, error et\n minima neque praesentium, ratione, reprehenderit repudiandae saepe ut vero!', diff --git a/src/stories/components/SelectButton/SelectButton.stories.ts b/src/stories/components/SelectButton/SelectButton.stories.ts index 4dc87e4a6fd35ea96d80205e145091fb989dfda4..5fd64bd936517a2af56bfe9c1935ceddedf86b5c 100644 --- a/src/stories/components/SelectButton/SelectButton.stories.ts +++ b/src/stories/components/SelectButton/SelectButton.stories.ts @@ -94,7 +94,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { options: [ { diff --git a/src/stories/components/Slider/Slider.stories.ts b/src/stories/components/Slider/Slider.stories.ts index e8bfe3101d0d7f087e6834978c572a24badeaa2d..24e45871cc1573331b107ce62253dcba30eba375 100644 --- a/src/stories/components/Slider/Slider.stories.ts +++ b/src/stories/components/Slider/Slider.stories.ts @@ -75,7 +75,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: {}, }; diff --git a/src/stories/components/Table/Table.stories.ts b/src/stories/components/Table/Table.stories.ts index d5cd8f2cce7cae1eb590a454f235f7e3337b6a97..7d51e729c49070083451a720d8333546f30a3121 100644 --- a/src/stories/components/Table/Table.stories.ts +++ b/src/stories/components/Table/Table.stories.ts @@ -20,6 +20,7 @@ const meta: Meta = { gap: { control: 'text' }, showAllLines: { control: 'boolean' }, stripedRows: { control: 'boolean' }, + center: { control: 'boolean' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessTextColor: { control: 'select', @@ -73,7 +74,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { columns: [ { @@ -122,14 +123,19 @@ export const Full: Story = { { name: 'Name', type: 'text', + sortable: true, }, { name: 'Age', type: 'text', + filterable: true, }, { name: 'Hobbies', type: 'text', + padding: '30px', + filterable: true, + sortable: true, }, { name: 'Country', @@ -198,9 +204,12 @@ export const Full: Story = { fontSize: '20px', showAllLines: true, - gap: '70px', + gap: '20px', border: 'fuchsia', theme: 'black', stripedRows: true, + textColor: 'white', + darknessTextColor: '500', + center: true, }, }; diff --git a/src/stories/components/Table/Table.vue b/src/stories/components/Table/Table.vue index 06c38dbae57d9140db58218928f7ce88cf0e85b7..825cf7c4c21f40020ef6f2ce90e7263cf7e75c2d 100644 --- a/src/stories/components/Table/Table.vue +++ b/src/stories/components/Table/Table.vue @@ -1,8 +1,12 @@ <script setup lang="ts"> import type { ITableProps } from '@interfaces/componentsProps'; -import { computed } from 'vue'; +import { computed, ref } from 'vue'; import { convertThemeToColor, convertThemeToSecondaryColor, convertThemeToTextColor } from '@helpers/common'; import type { ITableItem } from '@interfaces/componentsProp'; +import FilterIcon from '@stories/icons/Mono/FilterIcon.vue'; +import SortDownIcon from '@stories/icons/Mono/SortDownIcon.vue'; +import SortUpIcon from '@stories/icons/Mono/SortUpIcon.vue'; +import SortVerticalIcon from '@stories/icons/Mono/SortVerticalIcon.vue'; const props = withDefaults(defineProps<ITableProps>(), { gap: '5px', @@ -22,6 +26,22 @@ const color = computed(() => ); const secondaryColor = computed(() => convertThemeToSecondaryColor(props.theme, props.darknessTheme)); const darkCellColor = computed(() => convertThemeToSecondaryColor(props.theme, String(+props.darknessTheme + 300))); + +const sortState = ref<string[]>( + (() => { + const columns = props.columns; + const result = []; + for (const column of columns) { + result.push(column.sortable ? 'none' : ''); + } + return result; + })(), +); + +const changeColumnSortMode = (index: number) => { + const cur = sortState.value[index]; + sortState.value[index] = cur === 'none' ? 'down' : cur === 'down' ? 'up' : 'none'; +}; </script> <template> @@ -38,14 +58,49 @@ const darkCellColor = computed(() => convertThemeToSecondaryColor(props.theme, S :class="{ leftBorder: showAllLines, }" - v-for="column of columns" + v-for="(column, index) of columns" :key="column.name" class="columnHeader" style="padding: 5px 0 5px 5px" > - <div class="columnFlex"> - {{ column.name }} - <div></div> + <div + :style="`justify-content: ${center ? 'center' : 'start'}; padding: ${center ? `0px calc(${gap} / 2 + ${column.padding ?? '0px'} / 2)` : `0 ${column.padding ?? '0px'} 0 0`}`" + :class="[ + 'columnFlex', + { + columnGap: !center, + }, + ]" + > + <div class="columnHeader-container"> + <h3> + {{ column.name }} + </h3> + <button v-if="column.sortable" @click.prevent="changeColumnSortMode(index)"> + <SortVerticalIcon + v-show="sortState[index] === 'none'" + :color="textColor" + :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" + /> + <SortDownIcon + v-show="sortState[index] === 'down'" + :color="textColor" + :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" + /> + <SortUpIcon + v-show="sortState[index] === 'up'" + :color="textColor" + :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" + /> + </button> + <button v-if="column.filterable" @click.prevent=""> + <FilterIcon + :color="textColor" + :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" + /> + </button> + </div> + <div v-if="!center"></div> </div> </th> </tr> @@ -59,7 +114,7 @@ const darkCellColor = computed(() => convertThemeToSecondaryColor(props.theme, S }" v-for="item of row" :key="item.value" - style="padding: 5px" + :style="`padding: 5px; text-align: ${center ? 'center' : 'start'}`" > {{ item.value }} </td> @@ -90,9 +145,15 @@ tr::after { } .columnFlex { display: flex; - gap: v-bind(gap); font-weight: bold; } +.columnGap { + gap: v-bind(gap); +} +.columnHeader-container { + display: flex; + gap: 10px; +} .tableLines { border-top: 1px solid v-bind(secondaryColor); border-right: 1px solid v-bind(secondaryColor); diff --git a/src/stories/components/ToggleSwitch/ToggleSwitch.stories.ts b/src/stories/components/ToggleSwitch/ToggleSwitch.stories.ts index 362f38e830ffba36d79ca8ff4de0d5e3aadda8e1..a17df1c6af687bbdc88afc8e24fd5351028e7c7d 100644 --- a/src/stories/components/ToggleSwitch/ToggleSwitch.stories.ts +++ b/src/stories/components/ToggleSwitch/ToggleSwitch.stories.ts @@ -70,7 +70,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { active: false, }, diff --git a/src/stories/components/TreeList/TreeList.stories.ts b/src/stories/components/TreeList/TreeList.stories.ts index a1eb0b5735022b5bcb43b99a6ab6362769f14e8b..bc3e1d3272f82649860b7637b94953d4e77d36fd 100644 --- a/src/stories/components/TreeList/TreeList.stories.ts +++ b/src/stories/components/TreeList/TreeList.stories.ts @@ -68,7 +68,7 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = { +export const Simple: Story = { args: { items: [ { diff --git a/src/stories/icons/Mono/SortDownIcon.vue b/src/stories/icons/Mono/SortDownIcon.vue new file mode 100644 index 0000000000000000000000000000000000000000..f23751bbc423985a97c1459f65d6ba1187451ea8 --- /dev/null +++ b/src/stories/icons/Mono/SortDownIcon.vue @@ -0,0 +1,30 @@ +<script setup lang="ts"> +interface Props { + color?: string; + size?: string | number; +} +defineProps<Props>(); +</script> + +<template> + <svg + :width="`${size ?? 40}px`" + :height="`${size ?? 40}px`" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M4 16L13 16" :stroke="color ?? '#000000'" stroke-width="1.5" stroke-linecap="round" /> + <path d="M6 11H13" :stroke="color ?? '#000000'" stroke-width="1.5" stroke-linecap="round" /> + <path d="M8 6L13 6" :stroke="color ?? '#000000'" stroke-width="1.5" stroke-linecap="round" /> + <path + d="M17 4L17 20L20 16" + :stroke="color ?? '#000000'" + stroke-width="1.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> +</template> + +<style scoped></style> diff --git a/src/stories/icons/Mono/SortHorizontalIcon.vue b/src/stories/icons/Mono/SortHorizontalIcon.vue new file mode 100644 index 0000000000000000000000000000000000000000..0d19cb51d6bc39e2ef6ae53451329298f858cc31 --- /dev/null +++ b/src/stories/icons/Mono/SortHorizontalIcon.vue @@ -0,0 +1,34 @@ +<script setup lang="ts"> +interface Props { + color?: string; + size?: string | number; +} +defineProps<Props>(); +</script> + +<template> + <svg + :width="`${size ?? 40}px`" + :height="`${size ?? 40}px`" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M18 8L6 8M6 8L10.125 4M6 8L10.125 12" + :stroke="color ?? '#000000'" + stroke-width="1.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + <path + d="M6 16L18 16M18 16L13.875 12M18 16L13.875 20" + :stroke="color ?? '#000000'" + stroke-width="1.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> +</template> + +<style scoped></style> diff --git a/src/stories/icons/Mono/SortUpIcon.vue b/src/stories/icons/Mono/SortUpIcon.vue new file mode 100644 index 0000000000000000000000000000000000000000..93e9e779560e671df10bca6f2d9e528f47c8ff02 --- /dev/null +++ b/src/stories/icons/Mono/SortUpIcon.vue @@ -0,0 +1,30 @@ +<script setup lang="ts"> +interface Props { + color?: string; + size?: string | number; +} +defineProps<Props>(); +</script> + +<template> + <svg + :width="`${size ?? 40}px`" + :height="`${size ?? 40}px`" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M4 8H13" :stroke="color ?? '#000000'" stroke-width="1.5" stroke-linecap="round" /> + <path d="M6 13H13" :stroke="color ?? '#000000'" stroke-width="1.5" stroke-linecap="round" /> + <path d="M8 18H13" :stroke="color ?? '#000000'" stroke-width="1.5" stroke-linecap="round" /> + <path + d="M17 20V4L20 8" + :stroke="color ?? '#000000'" + stroke-width="1.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> +</template> + +<style scoped></style> diff --git a/src/stories/icons/Mono/SortVerticalIcon.vue b/src/stories/icons/Mono/SortVerticalIcon.vue new file mode 100644 index 0000000000000000000000000000000000000000..aaeb51161c579454743f8a68c95cea94c74bd82e --- /dev/null +++ b/src/stories/icons/Mono/SortVerticalIcon.vue @@ -0,0 +1,34 @@ +<script setup lang="ts"> +interface Props { + color?: string; + size?: string | number; +} +defineProps<Props>(); +</script> + +<template> + <svg + :width="`${size ?? 40}px`" + :height="`${size ?? 40}px`" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M16 18L16 6M16 6L20 10.125M16 6L12 10.125" + :stroke="color ?? '#000000'" + stroke-width="1.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + <path + d="M8 6L8 18M8 18L12 13.875M8 18L4 13.875" + :stroke="color ?? '#000000'" + stroke-width="1.5" + stroke-linecap="round" + stroke-linejoin="round" + /> + </svg> +</template> + +<style scoped></style>