base popdown window
This commit is contained in:
parent
c0a05f48b0
commit
828da2ce9e
6 changed files with 143 additions and 156 deletions
|
|
@ -1,5 +1,6 @@
|
|||
@use "sass:color";
|
||||
@use "scheme";
|
||||
@use "font";
|
||||
|
||||
$scale: 0.068rem;
|
||||
@function s($value: 1) {
|
||||
|
|
@ -42,3 +43,57 @@ $scale: 0.068rem;
|
|||
@mixin ease-in-out {
|
||||
transition-timing-function: cubic-bezier(0.85, 0, 0.15, 1);
|
||||
}
|
||||
|
||||
@mixin popdown-window($colour) {
|
||||
@include rounded(8);
|
||||
@include border($colour, 0.4, 2);
|
||||
@include shadow;
|
||||
@include font.mono;
|
||||
|
||||
background-color: scheme.$base;
|
||||
color: $colour;
|
||||
padding: s(10) s(12);
|
||||
font-size: s(14);
|
||||
|
||||
.header {
|
||||
@include spacing(8);
|
||||
|
||||
padding: 0 s(5);
|
||||
margin-bottom: s(8);
|
||||
font-size: s(15);
|
||||
|
||||
button {
|
||||
@include rounded(5);
|
||||
@include element-decel;
|
||||
|
||||
padding: s(3) s(8);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: scheme.$surface0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: scheme.$surface1;
|
||||
}
|
||||
|
||||
&.enabled {
|
||||
background-color: $colour;
|
||||
color: scheme.$base;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: color.mix($colour, scheme.$base, 80%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: color.mix($colour, scheme.$base, 70%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: s(32);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,57 +14,10 @@
|
|||
}
|
||||
|
||||
.notifications {
|
||||
@include lib.rounded(8);
|
||||
@include lib.border(scheme.$mauve, 0.4, 2);
|
||||
@include lib.shadow;
|
||||
@include font.mono;
|
||||
@include lib.popdown-window(scheme.$mauve);
|
||||
|
||||
min-width: lib.s(400);
|
||||
min-height: lib.s(600);
|
||||
background-color: scheme.$base;
|
||||
color: scheme.$mauve;
|
||||
padding: lib.s(10) lib.s(12);
|
||||
|
||||
.header {
|
||||
@include lib.spacing(8);
|
||||
|
||||
padding: 0 lib.s(5);
|
||||
margin-bottom: lib.s(8);
|
||||
|
||||
button {
|
||||
@include lib.rounded(5);
|
||||
@include lib.element-decel;
|
||||
|
||||
padding: lib.s(3) lib.s(8);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: scheme.$surface0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: scheme.$surface1;
|
||||
}
|
||||
|
||||
&.enabled {
|
||||
background-color: scheme.$mauve;
|
||||
color: scheme.$base;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: color.mix(scheme.$mauve, scheme.$base, 80%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: color.mix(scheme.$mauve, scheme.$base, 70%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: lib.s(32);
|
||||
}
|
||||
|
||||
.notification {
|
||||
.wrapper {
|
||||
|
|
|
|||
|
|
@ -3,60 +3,27 @@
|
|||
@use "lib";
|
||||
@use "font";
|
||||
|
||||
$accent: scheme.$blue;
|
||||
|
||||
.updates {
|
||||
@include lib.rounded(8);
|
||||
@include lib.border(scheme.$blue, 0.4, 2);
|
||||
@include lib.shadow;
|
||||
@include font.mono;
|
||||
@include lib.popdown-window($accent);
|
||||
|
||||
min-width: lib.s(600);
|
||||
min-height: lib.s(400);
|
||||
background-color: scheme.$base;
|
||||
color: scheme.$blue;
|
||||
padding: lib.s(10) lib.s(12);
|
||||
font-size: lib.s(14);
|
||||
|
||||
.wrapper {
|
||||
@include lib.element-decel;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: color.mix(scheme.$blue, scheme.$base, 80%);
|
||||
color: color.mix($accent, scheme.$base, 80%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: color.mix(scheme.$blue, scheme.$base, 60%);
|
||||
color: color.mix($accent, scheme.$base, 60%);
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@include lib.spacing(8);
|
||||
|
||||
padding: 0 lib.s(5);
|
||||
margin-bottom: lib.s(8);
|
||||
font-size: lib.s(15);
|
||||
|
||||
button {
|
||||
@include lib.rounded(5);
|
||||
@include lib.element-decel;
|
||||
|
||||
padding: lib.s(3) lib.s(8);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: scheme.$surface0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: scheme.$surface1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: lib.s(32);
|
||||
}
|
||||
|
||||
.repos {
|
||||
@include lib.spacing($vertical: true);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { bind } from "astal";
|
|||
import { Astal, Gtk } from "astal/gtk3";
|
||||
import AstalNotifd from "gi://AstalNotifd";
|
||||
import Notification from "../widgets/notification";
|
||||
import PopupWindow from "../widgets/popupwindow";
|
||||
import PopdownWindow from "../widgets/popdownwindow";
|
||||
|
||||
const List = () => (
|
||||
<box
|
||||
|
|
@ -44,40 +44,22 @@ const List = () => (
|
|||
);
|
||||
|
||||
export default () => (
|
||||
<PopupWindow name="notifications">
|
||||
<box vertical className="notifications">
|
||||
<box className="header">
|
||||
<label
|
||||
label={bind(AstalNotifd.get_default(), "notifications").as(
|
||||
n => `${n.length} notification${n.length === 1 ? "" : "s"}`
|
||||
)}
|
||||
/>
|
||||
<box hexpand />
|
||||
<button
|
||||
cursor="pointer"
|
||||
onClicked={() => (AstalNotifd.get_default().dontDisturb = !AstalNotifd.get_default().dontDisturb)}
|
||||
label="Silence"
|
||||
className={bind(AstalNotifd.get_default(), "dontDisturb").as(d => (d ? "enabled" : ""))}
|
||||
/>
|
||||
<button
|
||||
cursor="pointer"
|
||||
onClicked={() => AstalNotifd.get_default().notifications.forEach(n => n.dismiss())}
|
||||
label="Clear"
|
||||
/>
|
||||
</box>
|
||||
<stack
|
||||
transitionType={Gtk.StackTransitionType.CROSSFADE}
|
||||
transitionDuration={150}
|
||||
shown={bind(AstalNotifd.get_default(), "notifications").as(n => (n.length > 0 ? "list" : "empty"))}
|
||||
>
|
||||
<box vertical valign={Gtk.Align.CENTER} name="empty">
|
||||
<label className="icon" label="notifications_active" />
|
||||
<label label="All caught up!" />
|
||||
</box>
|
||||
<scrollable expand hscroll={Gtk.PolicyType.NEVER} name="list">
|
||||
<List />
|
||||
</scrollable>
|
||||
</stack>
|
||||
</box>
|
||||
</PopupWindow>
|
||||
<PopdownWindow
|
||||
name="notifications"
|
||||
count={bind(AstalNotifd.get_default(), "notifications").as(n => n.length)}
|
||||
headerButtons={[
|
||||
{
|
||||
label: "Silence",
|
||||
onClicked: () => (AstalNotifd.get_default().dontDisturb = !AstalNotifd.get_default().dontDisturb),
|
||||
className: bind(AstalNotifd.get_default(), "dontDisturb").as(d => (d ? "enabled" : "")),
|
||||
},
|
||||
{
|
||||
label: "Clear",
|
||||
onClicked: () => AstalNotifd.get_default().notifications.forEach(n => n.dismiss()),
|
||||
},
|
||||
]}
|
||||
emptyIcon="notifications_active"
|
||||
emptyLabel="All caught up!"
|
||||
list={<List />}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { bind, execAsync, Variable } from "astal";
|
|||
import { App, Astal, Gtk } from "astal/gtk3";
|
||||
import Updates, { Repo as IRepo, Update as IUpdate } from "../services/updates";
|
||||
import { MenuItem } from "../utils/widgets";
|
||||
import PopupWindow from "../widgets/popupwindow";
|
||||
import PopdownWindow from "../widgets/popdownwindow";
|
||||
|
||||
const constructItem = (label: string, exec: string, quiet = true) =>
|
||||
new MenuItem({
|
||||
|
|
@ -67,36 +67,22 @@ const List = () => (
|
|||
);
|
||||
|
||||
export default () => (
|
||||
<PopupWindow name="updates">
|
||||
<box vertical className="updates">
|
||||
<box className="header">
|
||||
<label label={bind(Updates.get_default(), "numUpdates").as(n => `${n} update${n === 1 ? "" : "s"}`)} />
|
||||
<box hexpand />
|
||||
<button
|
||||
cursor="pointer"
|
||||
onClicked={() =>
|
||||
execAsync("uwsm app -T -- yay")
|
||||
.then(() => Updates.get_default().getUpdates())
|
||||
// Ignore errors
|
||||
.catch(() => {})
|
||||
}
|
||||
label="Update all"
|
||||
/>
|
||||
<button cursor="pointer" onClicked={() => Updates.get_default().getUpdates()} label="Reload" />
|
||||
</box>
|
||||
<stack
|
||||
transitionType={Gtk.StackTransitionType.CROSSFADE}
|
||||
transitionDuration={150}
|
||||
shown={bind(Updates.get_default(), "numUpdates").as(n => (n > 0 ? "list" : "empty"))}
|
||||
>
|
||||
<box vertical valign={Gtk.Align.CENTER} name="empty">
|
||||
<label className="icon" label="deployed_code_history" />
|
||||
<label label="All packages up to date!" />
|
||||
</box>
|
||||
<scrollable expand hscroll={Gtk.PolicyType.NEVER} name="list">
|
||||
<List />
|
||||
</scrollable>
|
||||
</stack>
|
||||
</box>
|
||||
</PopupWindow>
|
||||
<PopdownWindow
|
||||
name="updates"
|
||||
count={bind(Updates.get_default(), "numUpdates")}
|
||||
headerButtons={[
|
||||
{
|
||||
label: "Update all",
|
||||
onClicked: () =>
|
||||
execAsync("uwsm app -T -- yay")
|
||||
.then(() => Updates.get_default().getUpdates())
|
||||
// Ignore errors
|
||||
.catch(() => {}),
|
||||
},
|
||||
{ label: "Reload", onClicked: () => Updates.get_default().getUpdates() },
|
||||
]}
|
||||
emptyIcon="deployed_code_history"
|
||||
emptyLabel="All packages up to date!"
|
||||
list={<List />}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
44
src/widgets/popdownwindow.tsx
Normal file
44
src/widgets/popdownwindow.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import type { Binding } from "astal";
|
||||
import { Gtk } from "astal/gtk3";
|
||||
import PopupWindow from "./popupwindow";
|
||||
|
||||
export default ({
|
||||
name,
|
||||
count,
|
||||
headerButtons,
|
||||
emptyIcon,
|
||||
emptyLabel,
|
||||
list,
|
||||
}: {
|
||||
name: string;
|
||||
count: Binding<number>;
|
||||
headerButtons: { label: string; onClicked: () => void; className?: Binding<string> }[];
|
||||
emptyIcon: string;
|
||||
emptyLabel: string;
|
||||
list: JSX.Element;
|
||||
}) => (
|
||||
<PopupWindow name={name}>
|
||||
<box vertical className={name}>
|
||||
<box className="header">
|
||||
<label label={count.as(c => `${c} ${name.slice(0, -1)}${c === 1 ? "" : "s"}`)} />
|
||||
<box hexpand />
|
||||
{headerButtons.map(({ label, onClicked, className }) => (
|
||||
<button cursor="pointer" onClicked={onClicked} label={label} className={className} />
|
||||
))}
|
||||
</box>
|
||||
<stack
|
||||
transitionType={Gtk.StackTransitionType.CROSSFADE}
|
||||
transitionDuration={150}
|
||||
shown={count.as(c => (c > 0 ? "list" : "empty"))}
|
||||
>
|
||||
<box vertical valign={Gtk.Align.CENTER} name="empty">
|
||||
<label className="icon" label={emptyIcon} />
|
||||
<label label={emptyLabel} />
|
||||
</box>
|
||||
<scrollable expand hscroll={Gtk.PolicyType.NEVER} name="list">
|
||||
{list}
|
||||
</scrollable>
|
||||
</stack>
|
||||
</box>
|
||||
</PopupWindow>
|
||||
);
|
||||
Loading…
Add table
Reference in a new issue