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 "sass:color";
|
||||||
@use "scheme";
|
@use "scheme";
|
||||||
|
@use "font";
|
||||||
|
|
||||||
$scale: 0.068rem;
|
$scale: 0.068rem;
|
||||||
@function s($value: 1) {
|
@function s($value: 1) {
|
||||||
|
|
@ -42,3 +43,57 @@ $scale: 0.068rem;
|
||||||
@mixin ease-in-out {
|
@mixin ease-in-out {
|
||||||
transition-timing-function: cubic-bezier(0.85, 0, 0.15, 1);
|
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 {
|
.notifications {
|
||||||
@include lib.rounded(8);
|
@include lib.popdown-window(scheme.$mauve);
|
||||||
@include lib.border(scheme.$mauve, 0.4, 2);
|
|
||||||
@include lib.shadow;
|
|
||||||
@include font.mono;
|
|
||||||
|
|
||||||
min-width: lib.s(400);
|
min-width: lib.s(400);
|
||||||
min-height: lib.s(600);
|
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 {
|
.notification {
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
|
||||||
|
|
@ -3,60 +3,27 @@
|
||||||
@use "lib";
|
@use "lib";
|
||||||
@use "font";
|
@use "font";
|
||||||
|
|
||||||
|
$accent: scheme.$blue;
|
||||||
|
|
||||||
.updates {
|
.updates {
|
||||||
@include lib.rounded(8);
|
@include lib.popdown-window($accent);
|
||||||
@include lib.border(scheme.$blue, 0.4, 2);
|
|
||||||
@include lib.shadow;
|
|
||||||
@include font.mono;
|
|
||||||
|
|
||||||
min-width: lib.s(600);
|
min-width: lib.s(600);
|
||||||
min-height: lib.s(400);
|
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 {
|
.wrapper {
|
||||||
@include lib.element-decel;
|
@include lib.element-decel;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
color: color.mix(scheme.$blue, scheme.$base, 80%);
|
color: color.mix($accent, scheme.$base, 80%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&: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 {
|
.repos {
|
||||||
@include lib.spacing($vertical: true);
|
@include lib.spacing($vertical: true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { bind } from "astal";
|
||||||
import { Astal, Gtk } from "astal/gtk3";
|
import { Astal, Gtk } from "astal/gtk3";
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import Notification from "../widgets/notification";
|
import Notification from "../widgets/notification";
|
||||||
import PopupWindow from "../widgets/popupwindow";
|
import PopdownWindow from "../widgets/popdownwindow";
|
||||||
|
|
||||||
const List = () => (
|
const List = () => (
|
||||||
<box
|
<box
|
||||||
|
|
@ -44,40 +44,22 @@ const List = () => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<PopupWindow name="notifications">
|
<PopdownWindow
|
||||||
<box vertical className="notifications">
|
name="notifications"
|
||||||
<box className="header">
|
count={bind(AstalNotifd.get_default(), "notifications").as(n => n.length)}
|
||||||
<label
|
headerButtons={[
|
||||||
label={bind(AstalNotifd.get_default(), "notifications").as(
|
{
|
||||||
n => `${n.length} notification${n.length === 1 ? "" : "s"}`
|
label: "Silence",
|
||||||
)}
|
onClicked: () => (AstalNotifd.get_default().dontDisturb = !AstalNotifd.get_default().dontDisturb),
|
||||||
/>
|
className: bind(AstalNotifd.get_default(), "dontDisturb").as(d => (d ? "enabled" : "")),
|
||||||
<box hexpand />
|
},
|
||||||
<button
|
{
|
||||||
cursor="pointer"
|
label: "Clear",
|
||||||
onClicked={() => (AstalNotifd.get_default().dontDisturb = !AstalNotifd.get_default().dontDisturb)}
|
onClicked: () => AstalNotifd.get_default().notifications.forEach(n => n.dismiss()),
|
||||||
label="Silence"
|
},
|
||||||
className={bind(AstalNotifd.get_default(), "dontDisturb").as(d => (d ? "enabled" : ""))}
|
]}
|
||||||
/>
|
emptyIcon="notifications_active"
|
||||||
<button
|
emptyLabel="All caught up!"
|
||||||
cursor="pointer"
|
list={<List />}
|
||||||
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>
|
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { bind, execAsync, Variable } from "astal";
|
||||||
import { App, Astal, Gtk } from "astal/gtk3";
|
import { App, Astal, Gtk } from "astal/gtk3";
|
||||||
import Updates, { Repo as IRepo, Update as IUpdate } from "../services/updates";
|
import Updates, { Repo as IRepo, Update as IUpdate } from "../services/updates";
|
||||||
import { MenuItem } from "../utils/widgets";
|
import { MenuItem } from "../utils/widgets";
|
||||||
import PopupWindow from "../widgets/popupwindow";
|
import PopdownWindow from "../widgets/popdownwindow";
|
||||||
|
|
||||||
const constructItem = (label: string, exec: string, quiet = true) =>
|
const constructItem = (label: string, exec: string, quiet = true) =>
|
||||||
new MenuItem({
|
new MenuItem({
|
||||||
|
|
@ -67,36 +67,22 @@ const List = () => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<PopupWindow name="updates">
|
<PopdownWindow
|
||||||
<box vertical className="updates">
|
name="updates"
|
||||||
<box className="header">
|
count={bind(Updates.get_default(), "numUpdates")}
|
||||||
<label label={bind(Updates.get_default(), "numUpdates").as(n => `${n} update${n === 1 ? "" : "s"}`)} />
|
headerButtons={[
|
||||||
<box hexpand />
|
{
|
||||||
<button
|
label: "Update all",
|
||||||
cursor="pointer"
|
onClicked: () =>
|
||||||
onClicked={() =>
|
execAsync("uwsm app -T -- yay")
|
||||||
execAsync("uwsm app -T -- yay")
|
.then(() => Updates.get_default().getUpdates())
|
||||||
.then(() => Updates.get_default().getUpdates())
|
// Ignore errors
|
||||||
// Ignore errors
|
.catch(() => {}),
|
||||||
.catch(() => {})
|
},
|
||||||
}
|
{ label: "Reload", onClicked: () => Updates.get_default().getUpdates() },
|
||||||
label="Update all"
|
]}
|
||||||
/>
|
emptyIcon="deployed_code_history"
|
||||||
<button cursor="pointer" onClicked={() => Updates.get_default().getUpdates()} label="Reload" />
|
emptyLabel="All packages up to date!"
|
||||||
</box>
|
list={<List />}
|
||||||
<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>
|
|
||||||
);
|
);
|
||||||
|
|
|
||||||
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