Skip to content

Commit

Permalink
Adding ListTile and CircleCheckbox components
Browse files Browse the repository at this point in the history
  • Loading branch information
alvaro-signal committed Jan 25, 2023
1 parent da0a741 commit 2d9cbf4
Show file tree
Hide file tree
Showing 7 changed files with 497 additions and 0 deletions.
92 changes: 92 additions & 0 deletions stylesheets/components/CircleCheckbox.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

.CircleCheckbox {
&__checkbox {
position: relative;
height: 20px;
width: 20px;

input[type='checkbox'] {
cursor: pointer;
height: 0;
position: absolute;
width: 0;

@include keyboard-mode {
&:focus {
&::before {
border-color: $color-ultramarine;
}
outline: none;
}
}

&::before {
@include rounded-corners;
background: inherit;
content: '';
display: block;
height: 20px;
position: absolute;
width: 20px;

@include light-theme {
border: 1.5px solid $color-gray-25;
}
@include dark-theme {
border: 1.5px solid $color-gray-65;
}
}

&:checked {
&::before {
background: $color-ultramarine;
border: 1.5px solid $color-ultramarine;
}

&::after {
border: solid $color-white;
border-width: 0 2px 2px 0;
content: '';
display: block;
height: 11px;
left: 7px;
position: absolute;
top: 3px;
transform: rotate(45deg);
width: 6px;
}
}
&:disabled {
cursor: inherit;
}

@include light-theme {
&:disabled {
&::before {
border-color: $color-gray-15;
}
}
&:disabled:checked {
&::before {
background: $color-gray-15;
}
}
}

@include dark-theme {
&:disabled {
&::before {
border-color: $color-gray-45;
}
}
&:disabled:checked {
&::before {
background: $color-gray-45;
}
}
}
}
}
}
103 changes: 103 additions & 0 deletions stylesheets/components/ListTile.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

button.ListTile {
width: 100%;
}

.ListTile {
display: flex;
align-items: center;
padding: 6px 14px;
user-select: none;

// use a transparent border to inset the background
border: 2px solid transparent;
border-width: 2px 10px;
background-clip: padding-box;
border-radius: 20px / 12px;

// reset button styles
background-color: transparent;
color: inherit;
box-sizing: border-box;
text-align: inherit;

&--variant-panelrow {
padding: 8px 16px;
}

&__content {
flex: 1;
display: flex;
flex-direction: column;
font-family: $inter;

.ListTile[aria-disabled='true'] & {
opacity: 0.5;
}
}

&__title {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
font-size: 14px;
line-height: 20px;
}

&__subtitle {
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
font-size: 12px;
color: $color-gray-25;
line-height: 17px;

&--max-lines-1 {
-webkit-line-clamp: 1;
}
&--max-lines-2 {
-webkit-line-clamp: 2;
}
&--max-lines-3 {
-webkit-line-clamp: 3;
}

@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
}

&[aria-disabled='true'] {
cursor: not-allowed;
}

&__leading {
margin-right: 12px;
}
&__trailing {
margin-left: 12px;
}

&--clickable {
cursor: pointer;
&:hover:not([aria-disabled='true']) {
@include light-theme {
background-color: $color-black-alpha-06;
}

@include dark-theme {
background-color: $color-white-alpha-06;
}

& .ConversationDetails-panel-row__actions {
opacity: 1;
}
}
}
}
2 changes: 2 additions & 0 deletions stylesheets/manifest.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
@import './components/CallingToast.scss';
@import './components/ChatColorPicker.scss';
@import './components/Checkbox.scss';
@import './components/CircleCheckbox.scss';
@import './components/CompositionArea.scss';
@import './components/CompositionTextArea.scss';
@import './components/ContactModal.scss';
Expand Down Expand Up @@ -87,6 +88,7 @@
@import './components/LeftPaneDialog.scss';
@import './components/LeftPaneSearchInput.scss';
@import './components/Lightbox.scss';
@import './components/ListTile.scss';
@import './components/MediaEditor.scss';
@import './components/MediaQualitySelector.scss';
@import './components/MessageAudio.scss';
Expand Down
30 changes: 30 additions & 0 deletions ts/components/CircleCheckbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import React from 'react';
import { action } from '@storybook/addon-actions';

import type { Props } from './CircleCheckbox';
import { CircleCheckbox } from './CircleCheckbox';

const createProps = (): Props => ({
checked: false,
name: 'check-me',
onChange: action('onChange'),
});

export default {
title: 'Components/CircleCheckbox',
};

export function Normal(): JSX.Element {
return <CircleCheckbox {...createProps()} />;
}

export function Checked(): JSX.Element {
return <CircleCheckbox {...createProps()} checked />;
}

export function Disabled(): JSX.Element {
return <CircleCheckbox {...createProps()} disabled />;
}
50 changes: 50 additions & 0 deletions ts/components/CircleCheckbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import React from 'react';

import { getClassNamesFor } from '../util/getClassNamesFor';

export type Props = {
id?: string;
checked?: boolean;
disabled?: boolean;
isRadio?: boolean;
name?: string;
onChange?: (value: boolean) => unknown;
onClick?: () => unknown;
};

/**
* A fancy checkbox
*
* It's only the checkbox, it does NOT produce a label.
* It is a controlled component, you must provide a value and
* update it yourself onClick/onChange.
*/
export function CircleCheckbox({
id,
checked,
disabled,
isRadio,
name,
onChange,
onClick,
}: Props): JSX.Element {
const getClassName = getClassNamesFor('CircleCheckbox');

return (
<div className={getClassName('__checkbox')}>
<input
checked={Boolean(checked)}
disabled={disabled}
aria-disabled={disabled}
id={id}
name={name}
onChange={onChange && (ev => onChange(ev.target.checked))}
onClick={onClick}
type={isRadio ? 'radio' : 'checkbox'}
/>
</div>
);
}

0 comments on commit 2d9cbf4

Please sign in to comment.