Cleaner GridItem width overriding; remembered scroll position

This commit is contained in:
DarkCat09 2023-07-25 11:49:49 +04:00
parent b50e79ae4d
commit 251b1e7501
6 changed files with 135 additions and 119 deletions

View file

@ -1,23 +1,24 @@
--- ---
import Icon from './Icon.astro';
export interface Props { export interface Props {
id: string;
title: string; title: string;
text: string; text: string;
url: string; url: string;
elemClass?: Array<String>; width?: number;
btnClass?: Array<string>;
dataJs?: string;
} }
const { const {
id,
title, text, url, title, text, url,
elemClass = [], width = 9,
btnClass = [],
dataJs = "",
} = Astro.props; } = Astro.props;
--- ---
<div class:list={["gi", ...elemClass]}> <div class="gi" id={id}>
<a href={url} target="_blank" class="gi-main"> <div class="gi-row">
<div class="gi-main">
<span class="icon-wrapper"> <span class="icon-wrapper">
<slot name="icon-primary" /> <slot name="icon-primary" />
</span> </span>
@ -33,35 +34,73 @@ const {
</slot> </slot>
</span> </span>
</span> </span>
</a> </div>
<a href="javascript:void(0)" class:list={["gi-btn", ...btnClass]} data-js={dataJs}> <a href={`#${id}`} class="gi-btn gi-btn-expand">
<span class="icon-wrapper"> <span class="icon-wrapper">
<slot name="icon-btn" /> <Icon code="&#xf107;" />
</span> </span>
</a> </a>
<a href="#scroll" class="gi-btn gi-btn-close">
<span class="icon-wrapper">
<Icon code="&#xf106;" />
</span>
</a>
</div>
<div class="gi-options">
<slot name="options" />
</div>
<div class="gi-options gi-note">
<slot name="note" />
</div>
</div> </div>
<style lang="less"> <style lang="less" define:vars={{width: `${width}rem`}}>
@import "/src/styles/grid_calc.less";
.gi { .gi {
// vertical horizontal // vertical horizontal
padding: 0.4rem @gi-horiz-padding; padding: 0.4rem 0.6rem;
display: flex; display: flex;
flex-direction: row; flex-direction: column;
align-items: center;
width: @gi-width;
min-height: 3rem; min-height: 3rem;
border-radius: var(--bdrs); border-radius: var(--bdrs);
&:hover { &:hover {
background: var(--accent-bg); background: var(--accent-bg);
} }
.gi-options { display: none }
.gi-btn-close { display: none }
.gi-btn-expand { display: flex }
&:target {
background: var(--accent-bg);
.gi-options {
display: flex;
flex-direction: row;
justify-content: center;
:global(.icon) {
@icon-size: 1.75rem;
font-size: @icon-size;
width: @icon-size;
}
} }
a.gi-main { .gi-btn-close { display: flex }
.gi-btn-expand { display: none }
}
}
.gi-row {
display: flex;
flex-direction: row;
align-items: center;
}
.gi-main {
flex-grow: 1; flex-grow: 1;
height: 100%; height: 100%;
@ -73,46 +112,22 @@ const {
text-decoration: none; text-decoration: none;
.icon-wrapper { .icon-wrapper {
width: @gi-icon-primary; @icon-size: 2.3rem;
font-size: @gi-icon-primary;
margin-right: @gi-icon-margin; width: @icon-size;
font-size: @icon-size;
margin-right: 0.4rem;
& > :global(img) { & > :global(img) {
width: @gi-icon-primary; width: @icon-size;
} }
} }
}
a.gi-btn {
position: relative;
font-size: 1.1rem;
display: flex;
flex-direction: column;
align-items: center;
.icon-wrapper {
width: @gi-icon-btn;
font-size: @gi-icon-btn;
margin-left: @gi-icon-margin;
& > :global(img) {
width: @gi-icon-btn;
}
}
}
.icon-wrapper {
display: flex;
flex-direction: column;
align-items: center;
}
.content { .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: @gi-text-width; width: var(--width);
overflow: hidden; overflow: hidden;
.title { .title {
@ -124,4 +139,34 @@ const {
color: var(--fg-sec); color: var(--fg-sec);
} }
} }
}
.gi-btn {
position: relative;
font-size: 1.1rem;
display: flex;
flex-direction: column;
align-items: center;
.icon-wrapper {
@icon-size: 1.25rem;
width: @icon-size;
font-size: @icon-size;
margin-left: 0.4rem;
& > :global(img) {
width: @icon-size;
}
}
}
.icon-wrapper {
display: flex;
flex-direction: column;
align-items: center;
user-select: none;
}
</style> </style>

View file

@ -12,23 +12,11 @@ const { name, description, url, iconUrl = `${url}/favicon.ico` } = Astro.props;
--- ---
<GridItem <GridItem
id={`s-${name.toLowerCase()}`}
title={name} title={name}
text={description} text={description}
url={url} url={url}
elemClass={["gi-service"]} width={14}
> >
<img src={iconUrl} slot="icon-primary" /> <img src={iconUrl} slot="icon-primary" />
</GridItem> </GridItem>
<style lang="less" is:global>
@import "/src/styles/grid_calc.less";
// Overwriting default GridItem's width
.gi-service {
width: @service-width;
.content {
width: @service-text-width;
}
}
</style>

View file

@ -8,26 +8,37 @@ export interface Props {
name: string; name: string;
icon: string; icon: string;
copyName?: boolean; copyName?: boolean;
note?: string;
} }
const { app, url, name, icon, copyName = false } = Astro.props; const {
app, url, name, icon,
copyName = false,
note = "",
} = Astro.props;
--- ---
<GridItem <GridItem
id={`p-${app.toLowerCase()}`}
title={app} text={name} url={url} title={app} text={name} url={url}
elemClass={["gi-profile"]} width={9.5}
btnClass={["profile-copy"]}
dataJs={copyName ? name : url}
> >
<Icon code={icon} slot="icon-primary" /> <Icon code={icon} slot="icon-primary" />
<Icon code="&#xf0c5;" slot="icon-btn" /> <Fragment slot="options">
<a href="javascript:void(0)" class="profile-copy" data-url={copyName ? name : url}>
<Icon code="&#xf0c5;" />
</a>
<a href={url}>
<Icon code="&#xf35d;" />
</a>
</Fragment>
</GridItem> </GridItem>
<script> <script>
const copy = document.querySelectorAll('.profile-copy') const copy = document.querySelectorAll('.profile-copy')
const copyClickHandler = (ev: Event) => { const copyClickHandler = (ev: Event) => {
const elem = ev.currentTarget as HTMLElement const elem = ev.currentTarget as HTMLElement
const link = elem.dataset.js const link = elem.dataset.url
if (!link) return if (!link) return
navigator.clipboard.writeText(link) navigator.clipboard.writeText(link)
} }
@ -35,15 +46,3 @@ const { app, url, name, icon, copyName = false } = Astro.props;
elem.addEventListener('click', copyClickHandler) elem.addEventListener('click', copyClickHandler)
} }
</script> </script>
<style lang="less" is:global>
@import "/src/styles/grid_calc.less";
.gi-profile {
width: @profile-width;
.content {
width: @profile-text-width;
}
}
</style>

View file

@ -19,6 +19,7 @@ const { title, description } = Astro.props;
<title>{title}</title> <title>{title}</title>
</head> </head>
<body> <body>
<div id="scroll"></div>
<slot /> <slot />
</body> </body>
</html> </html>
@ -113,3 +114,11 @@ const { title, description } = Astro.props;
} }
} }
</style> </style>
<style>
#scroll {
position: fixed;
display: block;
height: 1px;
}
</style>

View file

@ -9,7 +9,7 @@ const { id } = Astro.props;
--- ---
<div class="modal-bg" id={id}> <div class="modal-bg" id={id}>
<a href="#" class="modal-bg-close"></a> <a href="#scroll" class="modal-bg-close"></a>
<div class="modal"> <div class="modal">
<div class="controls"> <div class="controls">
<a href="#"><Icon code="&#xf00d;" /></a> <a href="#"><Icon code="&#xf00d;" /></a>

View file

@ -1,25 +0,0 @@
@import "/src/styles/max_width.less";
@gi-icon-primary: 2.3rem;
@gi-icon-btn: 1.8rem;
@gi-text-width: 9.5rem;
@profile-text-width: 9rem;
@service-text-width: 14rem;
@gi-icon-margin: 0.4rem;
@gi-horiz-padding: 0.6rem;
// GridItem width without text
@gi-width-wo-text: @gi-horiz-padding + @gi-icon-primary + @gi-icon-margin + @gi-icon-margin + @gi-icon-btn + @gi-horiz-padding;
@gi-width: @gi-width-wo-text + @gi-text-width;
@profile-width: @gi-width-wo-text + @profile-text-width;
@service-width: @gi-width-wo-text + @service-text-width;
.grid-mixin() {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}