Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions web/src/assets/styles/blocks.scss
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,89 @@ ul[data-type="agama/list"][role="grid"] {
}
}

[data-type="agama/segmented-control"] {
ul {
display: inline-flex;
gap: var(--spacer-smaller);
list-style-type: none;
border-radius: var(--spacer-smaller);
align-items: center;
margin-inline: 0;

li {
margin: 0;

&:not(:last-child) {
padding-inline-end: var(--spacer-smaller);
border-inline-end: 1px solid var(--color-gray-dark);
}

button {
padding: var(--spacer-smaller) var(--spacer-small);
border: 1px solid var(--color-gray-darker);
border-radius: var(--spacer-smaller);
background: white; // var(--color-gray);

&[aria-current="true"] {
background: var(--color-primary);
color: white;
font-weight: bold;
font-size: var(--fs-normal);
}

&:not([aria-current="true"]):hover {
background: var(--color-gray);
}
}
}
}
}

[data-type="agama/controlled-panels"] {
[data-type="agama/option"] {
label, input {
cursor: pointer;
}

label {
display: flex;
gap: var(--spacer-smaller);
}
}

[data-variant="buttons"] {
input { position: absolute; opacity: 0 }

label {
border: 1px solid var(--color-primary);
padding: var(--spacer-small);
gap: var(--spacer-small);
border-radius: var(--spacer-smaller);
position: relative;

&:has(input:checked) {
background: var(--color-primary);
color: white;
}

&:has(input:focus-visible) {
// outline: 1px dotted;
// outline-offset: 0.25rem;
box-shadow: 0 0 0 3px var(--focus-color);
}
}

[data-type="agama/option"]:not(:last-child) {
border-inline-end: 2px solid var(--color-gray-darker);
padding-inline-end: var(--spacer-small);
}
}

> div[aria-expanded="false"] {
display: none;
}
}

table[data-type="agama/tree-table"] {
th:first-child {
block-size: fit-content;
Expand Down Expand Up @@ -670,3 +753,27 @@ section [data-type="agama/reminder"] {
max-inline-size: 100%;
}
}


[data-type="agama/expandable-selector"] {
// The expandable selector is built on top of PF/Table#expandable
// Let's tweak some styles
tr {
td:first-child {
padding-inline-start: 0;
}

td:last-child {
padding-inline-end: 0;
}
}

tr.pf-v5-c-table__expandable-row.pf-m-expanded {
border-bottom: 0;

.pf-v5-c-table__expandable-row-content {
font-size: var(--fs-medium);
padding-block: var(--spacer-small);
}
}
}
1 change: 1 addition & 0 deletions web/src/assets/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
--fw-bold: 700;

--fs-small: 0.7rem;
--fs-medium: 12px;
--fs-base: 14px;
--fs-large: 1rem;
--fs-h1: 1.5rem;
Expand Down
108 changes: 108 additions & 0 deletions web/src/components/core/ControlledPanels.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) [2024] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";

/**
* Wrapper component for holding ControlledPanel options
*
* Useful for rendering the ControlledPanel options horizontally.
*
* @see ControlledPanel examples.
*
* @param {React.PropsWithChildren} props
*/
const Options = ({ children, ...props }) => {
return (
<div className="split" {...props}>
{ children }
</div>
);
};

/**
* Renders an option intended to control the visibility of panels referenced by
* the controls prop.
*
* @typedef {object} OptionProps
* @property {string} id - The option id.
* @property {React.AriaAttributes["aria-controls"]} controls - A space-separated of one or more ID values
* referencing the elements whose contents or presence are controlled by the option.
* @property {boolean} isSelected - Whether the option is selected or not.
* @typedef {Omit<React.ComponentPropsWithoutRef<"input">, "aria-controls">} InputProps
*
* @param {React.PropsWithChildren<InputProps & OptionProps>} props
*/
const Option = ({ id, controls, isSelected, children, ...props }) => {
return (
<div data-type="agama/option">
<label htmlFor={id}>
<input id={id} checked={isSelected} type="radio" aria-controls={controls} {...props} />
{children}
</label>
</div>
);
};

/**
* Renders content whose visibility will be controlled by an option
*
* @typedef {object} PanelBaseProps
* @property {string} id - The option id.
* @property {boolean} isExpanded - The value for the aria-expanded attribute
* which will determine if the panel is visible or not.
*
* @typedef {PanelBaseProps & Omit<React.HTMLAttributes<HTMLDivElement>, "id" | "aria-expanded">} PanelProps
*
* @param {PanelProps} props
*/
const Panel = ({ id, isExpanded = false, children, ...props }) => {
return (
<div {...props} id={id} aria-expanded={isExpanded}>
{ children }
</div>
);
};

/**
* TODO: Write the documentation and examples.
* TODO: Find a better name.
* TODO: Improve it.
* NOTE: Please, be aware that despite the name, this has no relation with so
* called React controlled components https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components
* This is just a convenient, dummy component for simplifying the use of this
* options/tabs pattern across Agama UI.
*/
const ControlledPanels = ({ children, ...props }) => {
return (
<div {...props} data-type="agama/controlled-panels">
{ children }
</div>
);
};

ControlledPanels.Options = Options;
ControlledPanels.Option = Option;
ControlledPanels.Panel = Panel;

export default ControlledPanels;
Loading