Merge pull request #546 from ajnart/gridstack-exerpiments

Gridstack exerpiments
This commit is contained in:
Thomas Camlong
2023-01-03 22:35:11 +09:00
committed by GitHub
16 changed files with 399 additions and 343 deletions

View File

@@ -17,195 +17,6 @@
}
],
"apps": [
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990",
"name": "Donate",
"url": "https://ko-fi.com/ajnart",
"behaviour": {
"onClickUrl": "https://ko-fi.com/ajnart",
"externalUrl": "https://ko-fi.com/ajnart",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/61e1116779fc0a9bd5bdbcc7_Frame%206.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
"y": 0
},
"size": {
"width": 3,
"height": 3
}
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
"name": "Contribute",
"url": "https://github.com/ajnart/homarr",
"behaviour": {
"onClickUrl": "https://github.com/ajnart/homarr",
"externalUrl": "https://github.com/ajnart/homarr",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/github.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
"y": 3
},
"size": {
"width": 3,
"height": 3
}
}
},
{
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
"name": "Your app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": "https://homarr.dev"
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 15,
"y": 5
},
"size": {
"width": 5,
"height": 4
}
},
"integration": {
"type": null,
"properties": []
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33a",
"name": "Documentation",
"url": "https://homarr.dev",
"behaviour": {
"onClickUrl": "https://homarr.dev",
"externalUrl": "https://homarr.dev",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 3,
"y": 3
},
"size": {
"width": 3,
"height": 3
}
}
},
{
"id": "e41a11f5-9c6e-41bc-ac0e-4c4c47582faa",
"name": "Your app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": ""
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
"y": 6
},
"size": {
"width": 2,
"height": 2
}
},
"integration": {
"type": null,
"properties": []
}
},
{
"id": "76217a87-7151-42d0-b0cf-1b72aef63f83",
"name": "Small app",
@@ -229,8 +40,8 @@
},
"shape": {
"location": {
"x": 17,
"y": 0
"x": 0,
"y": 2
},
"size": {
"width": 2,
@@ -265,29 +76,43 @@
"properties": []
},
"area": {
"type": "wrapper",
"type": "category",
"properties": {
"id": "default"
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 3,
"y": 0
"x": 0,
"y": 4
},
"size": {
"width": 3,
"width": 4,
"height": 3
}
}
}
],
"widgets": [
},
{
"id": "weather",
"properties": {
"displayInFahrenheit": false,
"location": "Paris"
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990",
"name": "Donate",
"url": "https://ko-fi.com/ajnart",
"behaviour": {
"onClickUrl": "https://ko-fi.com/ajnart",
"externalUrl": "https://ko-fi.com/ajnart",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/61e1116779fc0a9bd5bdbcc7_Frame%206.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "category",
@@ -297,15 +122,167 @@
},
"shape": {
"location": {
"x": 6,
"y": 0
"x": 2,
"y": 2
},
"size": {
"width": 2,
"height": 2
}
}
},
{
"id": "e41a11f5-9c6e-41bc-ac0e-4c4c47582faa",
"name": "Your app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": ""
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 8,
"y": 12
},
"size": {
"width": 4,
"height": 2
}
},
"integration": {
"type": null,
"properties": []
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
"name": "Contribute",
"url": "https://github.com/ajnart/homarr",
"behaviour": {
"onClickUrl": "https://github.com/ajnart/homarr",
"externalUrl": "https://github.com/ajnart/homarr",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/github.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "category",
"properties": {
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 4,
"y": 2
},
"size": {
"width": 2,
"height": 2
}
}
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33a",
"name": "Documentation",
"url": "https://homarr.dev",
"behaviour": {
"onClickUrl": "https://homarr.dev",
"externalUrl": "https://homarr.dev",
"isOpeningNewTab": true
},
"network": {
"enabledStatusChecker": false,
"okStatus": [
200
]
},
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"integration": {
"type": null,
"properties": []
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 8,
"y": 9
},
"size": {
"width": 4,
"height": 3
}
}
},
{
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
"name": "Your app",
"url": "https://homarr.dev",
"appearance": {
"iconUrl": "/imgs/logo/logo.png"
},
"network": {
"enabledStatusChecker": false,
"okStatus": []
},
"behaviour": {
"isOpeningNewTab": true,
"externalUrl": "https://homarr.dev"
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
"y": 7
},
"size": {
"width": 6,
"height": 4
}
},
"integration": {
"type": null,
"properties": []
}
}
],
"widgets": [
{
"id": "date",
"properties": {
@@ -317,6 +294,29 @@
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f"
}
},
"shape": {
"location": {
"x": 0,
"y": 0
},
"size": {
"width": 6,
"height": 2
}
}
},
{
"id": "weather",
"properties": {
"displayInFahrenheit": false,
"location": "Paris"
},
"area": {
"type": "wrapper",
"properties": {
"id": "default"
}
},
"shape": {
"location": {
"x": 0,
@@ -341,8 +341,8 @@
},
"shape": {
"location": {
"x": 15,
"y": 0
"x": 0,
"y": 2
},
"size": {
"width": 5,

View File

@@ -100,10 +100,11 @@ export const IntegrationSelector = ({ form }: IntegrationSelectorProps) => {
placeholder={t('integration.type.placeholder')}
itemComponent={SelectItemComponent}
data={data}
maxDropdownHeight={400}
maxDropdownHeight={150}
dropdownPosition="bottom"
clearable
variant="default"
mb="md"
searchable
icon={
form.values.integration?.type && (
<img

View File

@@ -23,39 +23,40 @@ export const AppTile = ({ className, app }: AppTileProps) => {
classes: { card: cardClass },
} = useCardStyles(false);
const inner = (
<>
<Text align="center" weight={500} size="md" className={classes.appName}>
{app.name}
</Text>
<Center style={{ height: '75%', flex: 1 }}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<motion.img
className={classes.image}
src={app.appearance.iconUrl}
alt=""
animate={{
scale: [0.8, 1.15, 1],
rotate: [0, 15, -15, 0],
}}
transition={{
duration: 0.5,
}}
/>
</Center>
</>
);
function Inner() {
return (
<>
<Text align="center" weight={500} size="md" className={classes.appName}>
{app.name}
</Text>
<Center style={{ height: '85%', flex: 1 }}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<motion.img
className={classes.image}
src={app.appearance.iconUrl}
alt={app.name}
whileHover={{
scale: 1.2,
transition: { duration: 0.2 },
}}
initial={{ opacity: 0, scale: 0.5 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.3 }}
/>
</Center>
</>
);
}
return (
<HomarrCardWrapper className={className}>
<AppMenu app={app} />
{!app.url || isEditMode ? (
<UnstyledButton
className={classes.button}
style={{ pointerEvents: isEditMode ? 'none' : 'auto' }}
>
{inner}
<Inner />
</UnstyledButton>
) : (
<UnstyledButton
@@ -63,9 +64,9 @@ export const AppTile = ({ className, app }: AppTileProps) => {
component={NextLink}
href={app.behaviour.externalUrl.length > 0 ? app.behaviour.externalUrl : app.url}
target={app.behaviour.isOpeningNewTab ? '_blank' : '_self'}
className={cx(classes.button, classes.link)}
className={cx(classes.button)}
>
{inner}
<Inner />
</UnstyledButton>
)}
<AppPing app={app} />
@@ -76,14 +77,14 @@ export const AppTile = ({ className, app }: AppTileProps) => {
const useStyles = createStyles((theme, _params, getRef) => ({
image: {
ref: getRef('image'),
maxHeight: '80%',
maxWidth: '80%',
transition: 'transform 100ms ease-in-out',
maxHeight: '90%',
maxWidth: '90%',
},
appName: {
ref: getRef('appName'),
},
button: {
paddingBottom: 10,
height: '100%',
width: '100%',
display: 'flex',
@@ -91,20 +92,12 @@ const useStyles = createStyles((theme, _params, getRef) => ({
alignItems: 'center',
gap: 4,
},
link: {
[`&:hover .${getRef('image')}`]: {
// TODO: add styles for image when hovering card
},
[`&:hover .${getRef('appName')}`]: {
// TODO: add styles for app name when hovering card
},
},
}));
export const appTileDefinition = {
component: AppTile,
minWidth: 2,
minWidth: 1,
minHeight: 1,
maxWidth: 12,
minHeight: 2,
maxHeight: 12,
};

View File

@@ -22,7 +22,7 @@ export const HomarrCardWrapper = ({ ...props }: HomarrCardWrapperProps) => {
withBorder
style={{ cursor: isEditMode ? 'move' : 'default' }}
radius="lg"
shadow="md"
shadow="sm"
/>
);
};

View File

@@ -35,9 +35,13 @@ export const GridstackTileWrapper = ({
data-type={type}
data-id={id}
gs-x={x}
data-gridstack-x={x}
gs-y={y}
data-gridstack-y={y}
gs-w={width}
data-gridstack-w={width}
gs-h={height}
data-gridstack-h={height}
gs-min-w={minWidth}
gs-min-h={minHeight}
gs-max-w={maxWidth}

View File

@@ -12,6 +12,7 @@ export const initializeGridstack = (
items: AppType[],
widgets: IWidget<string, any>[],
isEditMode: boolean,
isLargerThanSm: boolean,
events: {
onChange: (changedNode: GridStackNode) => void;
onAdd: (addedNode: GridStackNode) => void;
@@ -19,7 +20,7 @@ export const initializeGridstack = (
) => {
if (!wrapperRef.current) return;
// calculates the currently available count of columns
const columnCount = areaType === 'sidebar' ? 4 : Math.floor(wrapperRef.current.offsetWidth / 64);
const columnCount = areaType === 'sidebar' ? 4 : isLargerThanSm || typeof isLargerThanSm === 'undefined' ? 12 : 6;
const minRow = areaType !== 'sidebar' ? 1 : Math.floor(wrapperRef.current.offsetHeight / 64);
// initialize gridstack
const newGrid = gridRef;

View File

@@ -11,6 +11,7 @@ import {
import { useConfigContext } from '../../../../config/provider';
import { useConfigStore } from '../../../../config/store';
import { useResize } from '../../../../hooks/use-resize';
import { useScreenLargerThan } from '../../../../hooks/useScreenLargerThan';
import { AppType } from '../../../../types/app';
import { AreaType } from '../../../../types/area';
import { IWidget } from '../../../../widgets/widgets';
@@ -31,6 +32,7 @@ export const useGridstack = (
areaType: 'wrapper' | 'category' | 'sidebar',
areaId: string
): UseGristackReturnType => {
const isLargerThanSm = useScreenLargerThan('sm');
const isEditMode = useEditModeStore((x) => x.enabled);
const { config, configVersion, name: configName } = useConfigContext();
const updateConfig = useConfigStore((x) => x.updateConfig);
@@ -78,8 +80,52 @@ export const useGridstack = (
// change column count depending on the width and the gridRef
useEffect(() => {
if (areaType === 'sidebar') return;
gridRef.current?.column(Math.floor(width / 64), 'moveScale');
}, [gridRef, width]);
gridRef.current?.column(
isLargerThanSm || typeof isLargerThanSm === 'undefined' ? 12 : 6,
(column, prevColumn, newNodes, nodes) => {
let nextRow = 0;
let available = 6;
if (column === prevColumn) {
newNodes.concat(nodes);
return;
}
nodes.reverse().forEach((node) => {
const newnode = node;
const width = parseInt(newnode.el!.getAttribute('data-gridstack-w')!, 10);
const height = parseInt(newnode.el!.getAttribute('data-gridstack-h')!, 10);
const x = parseInt(newnode.el!.getAttribute('data-gridstack-x')!, 10);
const y = parseInt(newnode.el!.getAttribute('data-gridstack-y')!, 10);
if (column === 6) {
newnode.x = available >= width ? 6 - available : 0;
newnode.y = nextRow;
if (width > 6) {
newnode.w = 6;
nextRow += 2;
available = 6;
} else if (available >= width) {
available -= width;
if (available === 0) {
nextRow += 2;
available = 6;
}
} else if (available < width) {
newnode.y = newnode.y! + 2;
available = 6 - width;
nextRow += 2;
}
} else {
newnode.x = y % 2 === 1 ? x + 6 : x;
newnode.y = Math.floor(y / 2);
}
newNodes.push(newnode);
});
}
);
}, [isLargerThanSm]);
const onChange = isEditMode
? (changedNode: GridStackNode) => {
@@ -236,6 +282,7 @@ export const useGridstack = (
items,
widgets ?? [],
isEditMode,
isLargerThanSm,
{
onChange,
onAdd,

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import Consola from 'consola';
import { ActionIcon, Button, Group, Paper, Popover, Space, Text } from '@mantine/core';
import { ActionIcon, Button, Group, Popover, Text } from '@mantine/core';
import { IconEditCircle, IconEditCircleOff, IconX } from '@tabler/icons';
import { getCookie } from 'cookies-next';
import { Trans, useTranslation } from 'next-i18next';

View File

@@ -4,7 +4,6 @@ import { CURRENT_VERSION, REPO_URL } from '../../../../data/constants';
import { useConfigContext } from '../../../config/provider';
import { Logo } from '../Logo';
import { useCardStyles } from '../useCardStyles';
import { AddElementAction } from './Actions/AddElementAction/AddElementAction';
import DockerMenuButton from './Actions/Docker/DockerModule';
import { ToggleEditModeAction } from './Actions/ToggleEditMode/ToggleEditMode';
import { Search } from './Search';

View File

@@ -1,4 +1,4 @@
import { ActionIcon, Badge, Menu, Tooltip } from '@mantine/core';
import { ActionIcon, Badge, Menu } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { IconInfoCircle, IconMenu2, IconSettings } from '@tabler/icons';
import { useTranslation } from 'next-i18next';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { PasswordInput, Paper, Title, Text, Container, Group, Button } from '@mantine/core';
import { PasswordInput, Paper, Title, Text, Container, Button } from '@mantine/core';
import { setCookie } from 'cookies-next';
import { showNotification, updateNotification } from '@mantine/notifications';
import axios from 'axios';

View File

@@ -13,15 +13,24 @@
}
@for $i from 1 to 13 {
.grid-stack>.grid-stack-item[gs-w="#{$i}"] { width: $i * 64px }
.grid-stack>.grid-stack-item[gs-min-w="#{$i}"] { min-width: $i * 64px }
.grid-stack>.grid-stack-item[gs-max-w="#{$i}"] { max-width: $i * 64px }
.grid-stack>.grid-stack-item[gs-w="#{$i}"] { width: ($i / 12) * 100 + "%" }
.grid-stack>.grid-stack-item[gs-min-w="#{$i}"] { min-width: ($i / 12) * 100 + "%" }
.grid-stack>.grid-stack-item[gs-max-w="#{$i}"] { max-width: ($i / 12) * 100 + "%" }
}
@for $i from 1 to 96 {
.grid-stack>.grid-stack-item[gs-h="#{$i}"] { height: $i * 64 + "px" }
.grid-stack>.grid-stack-item[gs-min-h="#{$i}"] { min-height: $i * 64 + "px" }
.grid-stack>.grid-stack-item[gs-max-h="#{$i}"] { max-height: $i * 64 + "px" }
}
@for $i from 1 to 13 {
.grid-stack>.grid-stack-item[gs-h="#{$i}"] { height: $i * 64px; }
.grid-stack>.grid-stack-item[gs-min-h="#{$i}"] { min-height: $i * 64px; }
.grid-stack>.grid-stack-item[gs-max-h="#{$i}"] { max-height: $i * 64px; }
.grid-stack>.grid-stack-item[gs-x="#{$i}"] { left: ($i / 12) * 100 + "%" }
}
@for $i from 1 to 96 {
.grid-stack>.grid-stack-item[gs-y="#{$i}"] { top: $i * 64 + "px" }
}
.grid-stack>.grid-stack-item>.grid-stack-item-content,
@@ -35,16 +44,7 @@
}
.grid-stack>.grid-stack-item {
min-width: 64px;
}
@for $i from 1 to 96 {
.grid-stack>.grid-stack-item[gs-x="#{$i}"] { left: $i * 64px }
}
@for $i from 1 to 96 {
.grid-stack>.grid-stack-item[gs-y="#{$i}"] { top: $i * 64px }
min-width: (1/12)+'%';
}
.grid-stack > .grid-stack-item > .grid-stack-item-content {
@@ -54,3 +54,19 @@
.grid-stack.grid-stack-animate {
transition: none;
}
@media screen and (max-width: 768px) {
@for $i from 1 to 7 {
.grid-stack>.grid-stack-item[gs-w="#{$i}"] { width: percentage(($i / 6)) !important }
.grid-stack>.grid-stack-item[gs-min-w="#{$i}"] { min-width: percentage(($i / 6)) !important }
.grid-stack>.grid-stack-item[gs-max-w="#{$i}"] { max-width: percentage(($i / 6)) !important }
}
@for $i from 1 to 7 {
.grid-stack>.grid-stack-item[gs-x="#{$i}"] { left: percentage(($i / 6)) }
}
.grid-stack>.grid-stack-item {
min-width: percentage(1/6) !important;
}
}

View File

@@ -1,4 +1,4 @@
import { Center, createStyles, MantineThemeColors, useMantineTheme } from '@mantine/core';
import { createStyles, Group, MantineThemeColors, useMantineTheme } from '@mantine/core';
import { Calendar } from '@mantine/dates';
import { IconCalendarTime } from '@tabler/icons';
import { useQuery } from '@tanstack/react-query';
@@ -21,7 +21,7 @@ const definition = defineWidget({
},
},
gridstack: {
minWidth: 4,
minWidth: 3,
minHeight: 5,
maxWidth: 12,
maxHeight: 12,
@@ -55,35 +55,37 @@ function CalendarTile({ widget }: CalendarTileProps) {
});
return (
<Calendar
month={month}
// Should be offset 5px to the left
style={{ position: 'relative', left: -10, top: -10 }}
onMonthChange={setMonth}
size="xs"
fullWidth
onChange={() => {}}
firstDayOfWeek={widget.properties.sundayStart ? 'sunday' : 'monday'}
dayStyle={(date) => ({
margin: 1,
backgroundColor: isToday(date)
? colorScheme === 'dark'
? colors.dark[5]
: colors.gray[0]
: undefined,
})}
styles={{
calendarHeader: {
marginRight: 40,
marginLeft: 40,
},
}}
allowLevelChange={false}
dayClassName={(_, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
renderDay={(date) => (
<CalendarDay date={date} medias={getReleasedMediasForDate(medias, date)} />
)}
/>
<Group grow style={{ height: '100%' }}>
<Calendar
month={month}
// Should be offset 5px to the left
style={{ position: 'relative', top: -10 }}
onMonthChange={setMonth}
size="xs"
fullWidth
onChange={() => {}}
firstDayOfWeek={widget.properties.sundayStart ? 'sunday' : 'monday'}
dayStyle={(date) => ({
margin: 1,
backgroundColor: isToday(date)
? colorScheme === 'dark'
? colors.dark[5]
: colors.gray[0]
: undefined,
})}
styles={{
calendarHeader: {
marginRight: 40,
marginLeft: 40,
},
}}
allowLevelChange={false}
dayClassName={(_, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
renderDay={(date) => (
<CalendarDay date={date} medias={getReleasedMediasForDate(medias, date)} />
)}
/>
</Group>
);
}

View File

@@ -16,7 +16,7 @@ const definition = defineWidget({
},
},
gridstack: {
minWidth: 4,
minWidth: 2,
minHeight: 2,
maxWidth: 12,
maxHeight: 12,
@@ -35,12 +35,10 @@ function DateTile({ widget }: DateTileProps) {
const formatString = widget.properties.display24HourFormat ? 'HH:mm' : 'h:mm A';
return (
<Center style={{ height: '100%' }}>
<Stack spacing="xs">
<Title>{dayjs(date).format(formatString)}</Title>
<Text size="lg">{dayjs(date).format('dddd, MMMM D')}</Text>
</Stack>
</Center>
<Stack spacing="xs" justify="space-around" align="center" style={{ height: '100%' }}>
<Title>{dayjs(date).format(formatString)}</Title>
<Text size="lg">{dayjs(date).format('dddd, MMMM D')}</Text>
</Stack>
);
}

View File

@@ -30,7 +30,7 @@ export const WeatherIcon = ({ code }: WeatherIconProps) => {
return (
<Tooltip withinPortal withArrow label={t(`card.weatherDescriptions.${name}`)}>
<Box>
<Icon size={50} />
<Icon style={{ float: 'left' }} size={50} />
</Box>
</Tooltip>
);

View File

@@ -19,7 +19,7 @@ const definition = defineWidget({
},
},
gridstack: {
minWidth: 4,
minWidth: 2,
minHeight: 2,
maxWidth: 12,
maxHeight: 12,
@@ -61,39 +61,34 @@ function WeatherTile({ widget }: WeatherTileProps) {
// TODO: add widgetWrapper that is generic and uses the definition
return (
<Center style={{ height: '100%' }}>
<Group spacing="md" noWrap align="center">
<Stack
spacing="xs"
justify="space-around"
align="center"
style={{ height: '100%', width: '100%' }}
>
<Group grow>
<WeatherIcon code={weather!.current_weather.weathercode} />
<Stack p={0} spacing={4}>
<Title order={2}>
{getPerferedUnit(
weather!.current_weather.temperature,
widget.properties.displayInFahrenheit
)}
</Title>
<Group spacing="xs" noWrap>
<div>
<span>
{getPerferedUnit(
weather!.daily.temperature_2m_max[0],
widget.properties.displayInFahrenheit
)}
</span>
<IconArrowUpRight size={16} style={{ right: 15 }} />
</div>
<div>
<span>
{getPerferedUnit(
weather!.daily.temperature_2m_min[0],
widget.properties.displayInFahrenheit
)}
</span>
<IconArrowDownRight size={16} />
</div>
</Group>
</Stack>
<Title order={2}>
{getPerferedUnit(
weather!.current_weather.temperature,
widget.properties.displayInFahrenheit
)}
</Title>
</Group>
</Center>
<Group noWrap spacing="xs">
<IconArrowUpRight />
{getPerferedUnit(
weather!.daily.temperature_2m_max[0],
widget.properties.displayInFahrenheit
)}
<IconArrowDownRight />
{getPerferedUnit(
weather!.daily.temperature_2m_min[0],
widget.properties.displayInFahrenheit
)}
</Group>
</Stack>
);
}