Migrate twenty UI (#21407)
## Migrate all `twenty-ui-deprecated` components into `twenty-ui` Ports all **192 components** and **70 stories** into the new `twenty-ui` package with full public-API parity (export diff: 0 missing / 0 extra across all 13 modules; story titles byte-identical for the Argos cross-package diff). - **Styling:** Linaria → SCSS Modules, `var(--t-*)` tokens, `data-*` state. Canonical pattern in `Button.module.scss`. - **Behavior:** Base UI where mapped (Checkbox, Radio, Modal→Dialog, Tooltip drops `react-tooltip`, JSON tree→Collapsible); framer kept only where animation is the public contract. - **Fixed an inert axe gate** in `.storybook/vitest.setup.ts` (a11y addon annotations were never registered). Now live; 119 stories carry `a11y: 'todo'` overrides pending a fix pass.
@@ -279,5 +279,6 @@
|
||||
"defaultBase": "main",
|
||||
"tui": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"analytics": false
|
||||
}
|
||||
|
||||
@@ -18,42 +18,42 @@
|
||||
{
|
||||
"name": "testing",
|
||||
"path": "dist/testing.mjs",
|
||||
"limit": "10 kB"
|
||||
"limit": "188 kB"
|
||||
},
|
||||
{
|
||||
"name": "components",
|
||||
"path": "dist/components.mjs",
|
||||
"limit": "40 kB"
|
||||
"limit": "209 kB"
|
||||
},
|
||||
{
|
||||
"name": "display",
|
||||
"path": "dist/display.mjs",
|
||||
"limit": "30 kB"
|
||||
"limit": "509 kB"
|
||||
},
|
||||
{
|
||||
"name": "feedback",
|
||||
"path": "dist/feedback.mjs",
|
||||
"limit": "20 kB"
|
||||
"limit": "164 kB"
|
||||
},
|
||||
{
|
||||
"name": "input",
|
||||
"path": "dist/input.mjs",
|
||||
"limit": "50 kB"
|
||||
"limit": "278 kB"
|
||||
},
|
||||
{
|
||||
"name": "layout",
|
||||
"path": "dist/layout.mjs",
|
||||
"limit": "20 kB"
|
||||
"limit": "230 kB"
|
||||
},
|
||||
{
|
||||
"name": "navigation",
|
||||
"path": "dist/navigation.mjs",
|
||||
"limit": "20 kB"
|
||||
"limit": "219 kB"
|
||||
},
|
||||
{
|
||||
"name": "json-visualizer",
|
||||
"path": "dist/json-visualizer.mjs",
|
||||
"limit": "30 kB"
|
||||
"limit": "173 kB"
|
||||
},
|
||||
{
|
||||
"name": "theme",
|
||||
@@ -68,7 +68,7 @@
|
||||
{
|
||||
"name": "utilities",
|
||||
"path": "dist/utilities.mjs",
|
||||
"limit": "10 kB"
|
||||
"limit": "217 kB"
|
||||
},
|
||||
{
|
||||
"name": "style.css",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type Preview } from '@storybook/react-vite';
|
||||
import '@new-ui/theme-constants/theme-light.css';
|
||||
import '@new-ui/theme-constants/theme-dark.css';
|
||||
import { ThemeProvider } from '@new-ui/theme-constants';
|
||||
import '@ui/theme-constants/theme-light.css';
|
||||
import '@ui/theme-constants/theme-dark.css';
|
||||
import { ThemeProvider } from '@ui/theme-constants';
|
||||
|
||||
const preview: Preview = {
|
||||
tags: ['autodocs'],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview';
|
||||
import { setProjectAnnotations } from '@storybook/react-vite';
|
||||
import { MotionGlobalConfig } from 'framer-motion';
|
||||
import * as projectAnnotations from './preview';
|
||||
@@ -9,4 +10,6 @@ import * as projectAnnotations from './preview';
|
||||
MotionGlobalConfig.skipAnimations = true;
|
||||
|
||||
// Apply Storybook's preview configuration to Vitest runs.
|
||||
setProjectAnnotations([projectAnnotations]);
|
||||
// The a11y addon annotations register the axe afterEach hook so that
|
||||
// parameters.a11y.test = 'error' (set in preview.tsx) actually gates tests.
|
||||
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);
|
||||
|
||||
@@ -0,0 +1,710 @@
|
||||
|
||||
This project is mostly licensed under the GNU General Public License (GPL) as described below. However, certain files within this project are licensed under a different commercial license. These files are clearly marked with the following comment at the top of the file: /* @license Enterprise */
|
||||
Files with this comment are not licensed under the aGPL v3, but instead are subject to the commercial license terms defined later in this file.
|
||||
|
||||
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
------------------------------------
|
||||
|
||||
|
||||
|
||||
The Twenty.com Commercial License (the “Commercial License”)
|
||||
Copyright (c) 2023-present Twenty.com, PBC
|
||||
|
||||
With regard to Twenty's Software:
|
||||
|
||||
This part of the software and associated documentation files (the "Software") may only be
|
||||
used in production, if you (and any entity that you represent) have agreed to,
|
||||
and are in compliance with, the Terms available
|
||||
at https://twenty.com/legal/terms, or other agreements governing
|
||||
the use of the Software, as mutually agreed by you and Twenty.com, PBC ("Twenty"),
|
||||
and otherwise have a valid Twenty Enterprise Edition subscription
|
||||
for the correct number of hosts and seats as defined in the Commercial Terms.
|
||||
Subject to the foregoing sentence,
|
||||
you are free to modify this Software and publish patches to the Software. You agree
|
||||
that Twenty and/or its licensors (as applicable) retain all right, title and interest in
|
||||
and to all such modifications and/or patches, and all such modifications and/or
|
||||
patches may only be used, copied, modified, displayed, distributed, or otherwise
|
||||
exploited with a valid Commercial Subscription for the correct number of hosts and seats.
|
||||
Notwithstanding the foregoing, you may copy and modify the Software for development
|
||||
and testing purposes, without requiring a subscription. You agree that Twenty.Com and/or
|
||||
its licensors (as applicable) retain all right, title and interest in and to all such
|
||||
modifications. You are not granted any other rights beyond what is expressly stated herein.
|
||||
Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense,
|
||||
and/or sell the Software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
For all third party components incorporated into the Twenty Software, those
|
||||
components are licensed under the original license provided by the owner of the
|
||||
applicable component.
|
||||
@@ -1,23 +1,28 @@
|
||||
# twenty-ui
|
||||
|
||||
> **Status:** Phase 0 — Foundations in progress. The package is scaffolded and builds
|
||||
> on SCSS Modules + Base UI; the theme layer is ported from `twenty-ui` with a parity
|
||||
> test, and the size/Storybook/a11y harnesses are wired up. Remaining Phase 0 work: the
|
||||
> CI diff-table workflow, the `twenty-ui` component inventory, and the `modules/ui` triage.
|
||||
> The sections below remain the design document for the full effort.
|
||||
> **Status:** Phases 0–3 complete (June 2026). All 192 components and all 70 stories were
|
||||
> migrated from `twenty-ui-deprecated` with full public-API parity (export-identifier diff:
|
||||
> 0 missing / 0 extra across all 13 subpath modules) and byte-identical story titles for the
|
||||
> Argos cross-package diff. Gates green: typecheck, lint, jest, build, storybook:build,
|
||||
> storybook:test (225 stories incl. play functions + live axe gate), size.
|
||||
> Remaining: the Argos visual-parity triage, the a11y fix pass (119 stories carry
|
||||
> inherited-violation `a11y: 'todo'` overrides), the CI diff-table workflow, the
|
||||
> `modules/ui` triage (Phase 4), and the publish pipeline (Phase 5).
|
||||
> The sections below remain the design document for the full effort; see
|
||||
> [Migration outcomes](#migration-outcomes-june-2026) for decisions taken during the port.
|
||||
|
||||
`twenty-ui` is the next generation of Twenty's UI library, replacing [`twenty-ui`](../twenty-ui).
|
||||
`twenty-ui` is the next generation of Twenty's UI library, replacing [`twenty-ui-deprecated`](../twenty-ui-deprecated).
|
||||
It is built on a headless component library and a zero-runtime, CSS-variable styling layer.
|
||||
|
||||
## Goals
|
||||
|
||||
1. Publish as a standalone, versioned **npm package**.
|
||||
2. Replace `twenty-ui` in `twenty-front` with **no visual change** (same design, token for token).
|
||||
3. **Migrate every component** currently exported by `twenty-ui`.
|
||||
3. **Migrate every component** currently exported by `twenty-ui-deprecated`. *(Done — June 2026.)*
|
||||
4. **Absorb the generic, reusable UI** currently living in `twenty-front/src/modules/ui` (dropdowns, modals, tab lists, side panels, navigation, field inputs/displays, etc.), decoupling it from application concerns so it ships from the library.
|
||||
5. Enforce a **quality bar in CI**: bundle size, render/load time, and accessibility, measured against the old library.
|
||||
|
||||
## Current state (`twenty-ui`)
|
||||
## Current state (`twenty-ui-deprecated`)
|
||||
|
||||
| Aspect | Today |
|
||||
| --- | --- |
|
||||
@@ -26,10 +31,10 @@ It is built on a headless component library and a zero-runtime, CSS-variable sty
|
||||
| Behavior | Hand-rolled (modals, menus, tooltips, selects, etc.); `react-tooltip` for tooltips |
|
||||
| Build | Vite library mode, dual ESM/CJS, `vite-plugin-dts`, auto-generated barrels |
|
||||
| Icons | `@tabler/icons-react` re-exports + custom icons + Jotai-backed `IconsProvider` |
|
||||
| Consumption | ~1,721 files in `twenty-front` import it (mostly `display` and `theme-constants`); imported by package name |
|
||||
| Consumption | ~1,730 files in `twenty-front` import it (mostly `display` and `theme-constants`), plus `twenty-front-component-renderer` and `twenty-sdk`; imported by package name |
|
||||
| Published | No (`private: true`) |
|
||||
|
||||
`twenty-front/src/modules/ui/` (application-level UI) consumes `twenty-ui` today. Its **generic, reusable**
|
||||
`twenty-front/src/modules/ui/` (application-level UI) consumes `twenty-ui-deprecated` today. Its **generic, reusable**
|
||||
components are now **in scope** — they migrate into `twenty-ui` (see [Application-level UI migration](#application-level-ui-migration-twenty-frontsrcmodulesui)).
|
||||
|
||||
## Decision 1 — Headless library: Base UI
|
||||
@@ -98,30 +103,32 @@ packages/twenty-ui/
|
||||
```
|
||||
|
||||
**Public API parity.** Keep the same subpath exports, component names, and prop signatures as
|
||||
`twenty-ui` so the final swap is a codemod + dependency rename, not a rewrite of 1,721 files.
|
||||
Keep auto-generated barrels and dual ESM/CJS + `dts` output.
|
||||
`twenty-ui-deprecated` so the final swap is a codemod + dependency rename, not a rewrite of ~1,730 files.
|
||||
Keep auto-generated barrels and dual ESM/CJS + `dts` output. *(Achieved: the export-identifier sets of
|
||||
all 13 module barrels are identical between the two packages.)*
|
||||
|
||||
**Internal changes vs `twenty-ui`:** Linaria → SCSS Modules; hand-rolled behavior + `react-tooltip`
|
||||
**Internal changes vs `twenty-ui-deprecated`:** Linaria → SCSS Modules; hand-rolled behavior + `react-tooltip`
|
||||
→ Base UI; prefer Base UI/CSS transitions over `framer-motion` where possible; keep the icon system
|
||||
as-is.
|
||||
as-is. The internal path alias is `@ui/*` (same convention as the deprecated package, so ported files
|
||||
diff cleanly against their sources).
|
||||
|
||||
## Theming
|
||||
|
||||
`theme-constants` has ~943 importers and must be a drop-in replacement.
|
||||
|
||||
- Keep the public API identical: `ThemeProvider`, `ThemeContext`, `useTheme`, the `themeCssVariables` shape, `ThemeType`, color helpers, and the `theme-light.css` / `theme-dark.css` exports.
|
||||
- Reuse `twenty-ui`'s token values verbatim to guarantee identical design.
|
||||
- Tokens live in `src/theme/` (`THEME_LIGHT` / `THEME_DARK`); the `--t-*` CSS variables and the `themeCssVariables` accessor are static files mirrored token-for-token from `twenty-ui` (matching `twenty-ui`'s own static-CSS approach).
|
||||
- A theme parity test asserts the theme CSS and `themeCssVariables` stay identical to `twenty-ui`'s `--t-*` values.
|
||||
- Reuse `twenty-ui-deprecated`'s token values verbatim to guarantee identical design.
|
||||
- Tokens live in `src/theme/` (`THEME_LIGHT` / `THEME_DARK`); the `--t-*` CSS variables and the `themeCssVariables` accessor are static files mirrored token-for-token from `twenty-ui-deprecated` (matching its own static-CSS approach).
|
||||
- A theme parity test asserts the theme CSS and `themeCssVariables` stay identical to `twenty-ui-deprecated`'s `--t-*` values.
|
||||
|
||||
## Component migration map
|
||||
|
||||
A full component-by-component inventory with prop signatures is a Phase 0 deliverable. Components
|
||||
split into two buckets.
|
||||
Components split into two buckets. *(The migration is complete; see
|
||||
[Migration outcomes](#migration-outcomes-june-2026) below for where reality diverged from this map.)*
|
||||
|
||||
**Backed by a Base UI primitive (behavioral):**
|
||||
|
||||
| `twenty-ui` | Base UI |
|
||||
| `twenty-ui-deprecated` | Base UI |
|
||||
| --- | --- |
|
||||
| `Modal` | `Dialog` / `AlertDialog` |
|
||||
| `AppTooltip`, `OverflowingTextWithTooltip` | `Tooltip` (removes `react-tooltip`) |
|
||||
@@ -141,15 +148,43 @@ split into two buckets.
|
||||
`ColorSample`, `Checkmark`, placeholders, the icon system, `CodeEditor` (Monaco), `json-visualizer`,
|
||||
and the `utilities` / `theme` / `testing` / `accessibility` helpers.
|
||||
|
||||
### Migration outcomes (June 2026)
|
||||
|
||||
Decisions taken during the port where reality diverged from the map above (public API parity won every time):
|
||||
|
||||
- **`MenuItem` family and `TabButton` did NOT move to Base UI** Menu/Tabs — those primitives require a
|
||||
`Root` context the deprecated standalone APIs don't have. They are pure presentation with `data-*` state.
|
||||
The Base UI `Menu` mapping applies to the Phase-4 `modules/ui` dropdown instead.
|
||||
- **`AnimatedExpandableContainer` kept framer-motion** (sanctioned fallback): its exported utils are framer
|
||||
variant factories whose signatures are public API, and Collapsible/grid-rows could not match scrollHeight
|
||||
mid-animation retargeting or initial-mount animation.
|
||||
- **`Avatar`'s `invalidAvatarUrlsAtomV2` and the icon system's `iconsState` Jotai atoms were kept** — both are
|
||||
public `display` exports, overriding this doc's earlier "Jotai → local state" idea.
|
||||
- **`CardContent` kept framer-motion**: its motion props are part of the public prop type and twenty-front's
|
||||
`CalendarDayCardContent` passes them.
|
||||
- **`ProgressBar` is pure SCSS** (Base UI Progress was optional and not needed for parity); `useProgressAnimation`
|
||||
keeps framer motion-values verbatim (public hook).
|
||||
- **Known behavior deltas to watch in QA:** `AppTooltip` and `Modal` (without an explicit `container`) now portal
|
||||
to `document.body` (Base UI), so overflow-clipping ancestors no longer clip them and `AppTooltip`'s default
|
||||
`maxWidth: '40%'` resolves against the body; `Checkbox`/`Radio` test ids moved from the hidden input to the
|
||||
visible Base UI control.
|
||||
- **The Storybook axe gate was inert until this migration** — `.storybook/vitest.setup.ts` did not register the
|
||||
a11y addon annotations, so `a11y.test: 'error'` never ran. It is now live; 119 ported stories carry
|
||||
story-level `a11y: { test: 'todo' }` overrides (`// TODO(a11y)` comments) pending a dedicated fix pass.
|
||||
- The canonical styling pattern is established in `src/input/button/components/Button/Button.tsx` +
|
||||
`Button.module.scss`: `data-variant/accent/position/inverted` attributes, Sass maps + `@each` assigning
|
||||
`--btn-*` custom properties, all declarations on a flat `(0,1,0)` class so `styled(Component)` consumer
|
||||
overrides keep working.
|
||||
|
||||
## Application-level UI migration (`twenty-front/src/modules/ui`)
|
||||
|
||||
`twenty-front/src/modules/ui` holds ~250 application-level UI building blocks that consume `twenty-ui`
|
||||
`twenty-front/src/modules/ui` holds ~250 application-level UI building blocks that consume `twenty-ui-deprecated`
|
||||
today: `display`, `feedback` (snackbar/dialog managers), `field` (input + display), `input`
|
||||
(incl. relation picker), `layout` (dropdown, modal, tab-list, side-panel, page, table, resizable-panel,
|
||||
expandable-list, selectable-list, top-bar, …), `navigation` (drawer, breadcrumb, step-bar, menu-item),
|
||||
`drag-and-drop`, `suggestion`, `theme`, and `utilities` (hotkey, scroll, focus, responsive, drag-select, …).
|
||||
|
||||
These are a **different kind of migration** than the `twenty-ui` swap: they are stateful and
|
||||
These are a **different kind of migration** than the `twenty-ui-deprecated` swap: they are stateful and
|
||||
app-coupled — Jotai atoms, hooks, contexts, and (in places) GraphQL/router/Recoil-style state — rather
|
||||
than pure presentation. The goal is to extract the **generic, reusable** parts into `twenty-ui`
|
||||
while leaving genuinely app-specific wiring in `twenty-front`.
|
||||
@@ -165,14 +200,14 @@ while leaving genuinely app-specific wiring in `twenty-front`.
|
||||
workspace/router/permission logic, and anything whose only consumer is a single feature screen.
|
||||
|
||||
A component-by-component triage of `modules/ui` (generic / app-specific / hybrid, with target subpath
|
||||
and state-decoupling notes) is a **Phase 0 deliverable**, alongside the `twenty-ui` inventory.
|
||||
and state-decoupling notes) is the remaining **Phase 4 prerequisite** (the `twenty-ui-deprecated` inventory itself is complete — every component is migrated).
|
||||
|
||||
## Hardest components to migrate (risk hotspots)
|
||||
|
||||
A predicted ranking of where the effort and risk concentrate, to inform sequencing and staffing. This
|
||||
is a hypothesis to validate during the Phase 0 inventory/triage, not a final list.
|
||||
|
||||
### In `twenty-ui`
|
||||
### In `twenty-ui-deprecated` *(all migrated — predictions held; see Migration outcomes)*
|
||||
|
||||
| Component | Why it's hard | Migration shape |
|
||||
| --- | --- | --- |
|
||||
@@ -215,23 +250,23 @@ Apollo error formatting, and the icon/theme-color pickers tied to Twenty's icon
|
||||
- **Workbench** — Storybook (`@storybook/react-vite`). Every component has stories covering variants, sizes, and states (via `storybook-addon-pseudo-states`), in light and dark, with `autodocs`.
|
||||
- **Functional** — component/interaction tests via `@storybook/addon-vitest` (real browser); unit tests (Jest) for hooks/utilities; coverage gate via `@storybook/addon-coverage`.
|
||||
- **Accessibility** — Storybook a11y addon (axe-core) with `parameters.a11y.test = 'error'` so violations fail CI.
|
||||
- **Visual parity** — visual regression via Argos (self-hosted) plus a cross-package comparison project that diffs `twenty-ui` stories against `twenty-ui` stories with identical names; a pixel-diff threshold is the per-component acceptance gate. See [Visual regression](#visual-regression) below.
|
||||
- **Performance & size** — `size-limit` per entry point with budgets; tree-shaking fixtures (importing one component must not pull the library); build-time tracking; render benchmarks via React Profiler; load-time via Lighthouse/Playwright on the built Storybook. As one concrete benchmark, a dedicated **stress story** renders a very large number of a single component (e.g. 10,000 buttons) and measures total render time — compared against the `twenty-ui` equivalent and gated against a budget to catch per-instance overhead regressions.
|
||||
- **Visual parity** — visual regression via Argos (self-hosted) plus a cross-package comparison project that diffs `twenty-ui` stories against `twenty-ui-deprecated` stories with identical names; a pixel-diff threshold is the per-component acceptance gate. See [Visual regression](#visual-regression) below.
|
||||
- **Performance & size** — `size-limit` per entry point with budgets; tree-shaking fixtures (importing one component must not pull the library); build-time tracking; render benchmarks via React Profiler; load-time via Lighthouse/Playwright on the built Storybook. As one concrete benchmark, a dedicated **stress story** renders a very large number of a single component (e.g. 10,000 buttons) and measures total render time — compared against the `twenty-ui-deprecated` equivalent and gated against a budget to catch per-instance overhead regressions. *(Stress story not yet built.)*
|
||||
|
||||
CI surfaces a per-PR diff table (`twenty-ui` vs `twenty-ui`) for size, a11y, and visual changes.
|
||||
CI surfaces a per-PR diff table (`twenty-ui-deprecated` vs `twenty-ui`) for size, a11y, and visual changes. *(Not yet built.)*
|
||||
|
||||
## Visual regression
|
||||
|
||||
Two Argos projects (on argos.twenty-internal.com) provide visual regression in CI:
|
||||
|
||||
1. **`twenty-ui`** — pixel diff of `twenty-ui` stories against the `main` branch baseline. Catches regressions introduced by a PR.
|
||||
2. **`twenty-ui-vs-new-ui`** — cross-package comparison. The baseline is always `twenty-ui` screenshots from `main`; PR builds upload `twenty-ui` screenshots and diff them against the `twenty-ui` baseline. This shows exactly which components still differ between the two implementations.
|
||||
2. **`twenty-ui-vs-new-ui`** — cross-package comparison. The baseline is always `twenty-ui-deprecated` screenshots from `main`; PR builds upload `twenty-ui` screenshots and diff them against that baseline. This shows exactly which components still differ between the two implementations.
|
||||
|
||||
For the cross-package comparison to produce meaningful diffs, stories in `twenty-ui` must use the **same title hierarchy** as `twenty-ui` (e.g. `UI/Input/Toggle`).
|
||||
For the cross-package comparison to produce meaningful diffs, stories in `twenty-ui` must use the **same title hierarchy** as `twenty-ui-deprecated` (e.g. `UI/Input/Toggle/Toggle`). *(Done: all 70 story titles are byte-identical.)*
|
||||
|
||||
### Local visual diff
|
||||
|
||||
Run a pixel diff of `twenty-ui` components against `twenty-ui` using the self-hosted Argos instance.
|
||||
Run a pixel diff of `twenty-ui` components against `twenty-ui-deprecated` using the self-hosted Argos instance.
|
||||
|
||||
**Prerequisites:**
|
||||
- AWS SSO configured and logged in (`aws sso login --profile twenty-dev`)
|
||||
@@ -262,10 +297,10 @@ This builds Storybook, captures screenshots of every story, and uploads
|
||||
them to Argos with build name `<username>/twenty-ui`. The diff
|
||||
compares against the latest approved baseline.
|
||||
|
||||
To run `twenty-ui`'s visual diff in the same Argos instance (to build the
|
||||
To run `twenty-ui-deprecated`'s visual diff in the same Argos instance (to build the
|
||||
cross-package comparison baseline):
|
||||
|
||||
npx nx storybook:visual-diff twenty-ui
|
||||
npx nx storybook:visual-diff twenty-ui-deprecated
|
||||
|
||||
**4. View results**
|
||||
|
||||
@@ -276,28 +311,28 @@ to review diffs.
|
||||
|
||||
- Vite library mode, dual ESM/CJS, `vite-plugin-dts`, `vite-plugin-svgr`; SCSS via Vite's built-in `sass`; no Babel.
|
||||
- `sideEffects: ["**/*.css", "**/*.scss"]`; emit per-entry CSS plus `style.css` / `theme-light.css` / `theme-dark.css`.
|
||||
- Public package (remove `private`); ships as `twenty-ui` until cut-over, then claims the `twenty-ui` name once the old package is removed.
|
||||
- Public package (remove `private`); ships as `twenty-ui` (the old package already moved to the `twenty-ui-deprecated` name and is removed after cut-over).
|
||||
- **Changesets** for semver + changelog; GitHub Actions release with `npm publish --provenance`.
|
||||
- Declare `react` / `react-dom` as peer dependencies; validate the `exports`/types map with `publint` + `@arethetypeswrong/cli`.
|
||||
- Publish the Storybook as living documentation.
|
||||
|
||||
## Migration & rollout
|
||||
|
||||
1. Build `twenty-ui` to parity with the same API surface and design, validated by the parity, a11y, and size suites.
|
||||
1. ~~Build `twenty-ui` to parity with the same API surface and design~~ **Done** — validated by the export-parity diff, a11y, and size suites; visual-parity triage via Argos still pending.
|
||||
2. Dogfood on a few non-critical `twenty-front` screens behind a temporary alias.
|
||||
3. Codemod imports `twenty-ui` → `twenty-ui` across `twenty-front` (subpaths preserved); handle any changed APIs explicitly.
|
||||
3. Codemod imports `twenty-ui-deprecated` → `twenty-ui` (subpaths preserved) across `twenty-front` (~1,730 files), `twenty-front-component-renderer`, and `twenty-sdk`; handle any changed APIs explicitly.
|
||||
4. Swap the dependency, run the full test suite + visual diffs, ship.
|
||||
5. Deprecate and remove `twenty-ui` after a soak period.
|
||||
5. Remove `twenty-ui-deprecated` after a soak period.
|
||||
|
||||
## Roadmap
|
||||
|
||||
- **Phase 0 — Foundations:** scaffold package + tooling; port the theme layer with parity test; stand up the benchmark/parity/a11y CI harness first; complete the component inventory **and the `modules/ui` triage** (generic / app-specific / hybrid).
|
||||
- **Phase 1 — Primitives:** icons, typography, button family, status/tag/chip/pill; establish the canonical component pattern.
|
||||
- **Phase 2 — Behavioral:** Modal, Tooltip, Menu, Tabs, Checkbox, Radio, Switch, inputs/Field, Progress, Avatar, Collapsible.
|
||||
- **Phase 3 — Long tail:** banners/callout/info, card/section/separator, loader, color/card pickers, code editor, json-visualizer, placeholders, utilities/testing/accessibility.
|
||||
- ~~**Phase 0 — Foundations**~~ ✅ scaffolding, tooling, theme parity, harnesses. Still open from Phase 0: the CI diff-table workflow and the `modules/ui` triage (moved under Phase 4).
|
||||
- ~~**Phase 1 — Primitives**~~ ✅ done June 2026 (canonical pattern: `Button.tsx` + data-attribute Sass matrix).
|
||||
- ~~**Phase 2 — Behavioral**~~ ✅ done June 2026 (Base UI where mapped; see Migration outcomes for exceptions).
|
||||
- ~~**Phase 3 — Long tail**~~ ✅ done June 2026. Follow-up debt: the a11y fix pass for the 119 `a11y: 'todo'` stories, and the Argos visual-parity triage.
|
||||
- **Phase 4 — Application-level UI:** migrate the generic/hybrid components from `twenty-front/src/modules/ui` per the triage — decouple state, split headless cores, swap each behind its existing `@/ui/...` import path.
|
||||
- **Phase 5 — Hardening & publish:** close gaps; finalize release pipeline; cut `1.0.0`; publish docs.
|
||||
- **Phase 6 — Cut-over:** dogfood → codemod → swap → remove `twenty-ui`.
|
||||
- **Phase 6 — Cut-over:** dogfood → codemod → swap → remove `twenty-ui-deprecated`.
|
||||
|
||||
A component is done only with: stories (all states, light/dark), passing interaction + a11y tests,
|
||||
a passing visual-parity diff, and a within-budget size entry.
|
||||
@@ -316,10 +351,10 @@ a passing visual-parity diff, and a within-budget size entry.
|
||||
|
||||
## Open questions
|
||||
|
||||
1. Published package name: `twenty-ui` now, renamed to `twenty-ui` at cut-over (Phase 6).
|
||||
2. Styling: confirm SCSS Modules vs vanilla-extract vs plain CSS Modules.
|
||||
3. Variants helper: `clsx` + `data-*` vs `cva`.
|
||||
1. ~~Published package name.~~ **Resolved:** the rename already happened — this package owns `twenty-ui`; the old one is `twenty-ui-deprecated`.
|
||||
2. ~~Styling: SCSS Modules vs vanilla-extract vs plain CSS Modules.~~ **Resolved:** SCSS Modules, proven across all 192 components.
|
||||
3. ~~Variants helper: `clsx` + `data-*` vs `cva`.~~ **Resolved:** `clsx` + `data-*` attributes with Sass maps/`@each` (canonical pattern in `Button.module.scss`); `cva` not needed.
|
||||
4. ~~Visual regression tooling: Chromatic vs self-hosted image snapshots.~~ **Resolved:** Argos (self-hosted at argos.twenty-internal.com). See [Visual regression](#visual-regression).
|
||||
5. How aggressively to drop `framer-motion` in favor of CSS/Base UI transitions.
|
||||
6. Scope of `assets` / `testing` / `json-visualizer`: port verbatim or modernize.
|
||||
7. Where to draw the generic-vs-app-specific line for `modules/ui`, and whether hybrid components live as a headless core in `twenty-ui` with a thin app wrapper in `twenty-front`.
|
||||
5. ~~How aggressively to drop `framer-motion`.~~ **Resolved:** keep it where animation is the public contract (`utilities/animation`, `AnimatedButton`, `AnimatedCheckmark`, `AnimatedExpandableContainer`, `useProgressAnimation`, `CardContent`); converted to CSS/Base UI transitions everywhere it was an internal micro-transition.
|
||||
6. ~~Scope of `assets` / `testing` / `json-visualizer`.~~ **Resolved:** ported — assets byte-identical, testing decorators converted to SCSS, json-visualizer recursion verbatim with CSS/Collapsible animations.
|
||||
7. Where to draw the generic-vs-app-specific line for `modules/ui`, and whether hybrid components live as a headless core in `twenty-ui` with a thin app wrapper in `twenty-front`. **(Still open — Phase 4.)**
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
{
|
||||
"name": "twenty-ui",
|
||||
"version": "0.1.0",
|
||||
"description": "Twenty's shared React UI component library.",
|
||||
"license": "AGPL-3.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twentyhq/twenty.git",
|
||||
"directory": "packages/twenty-ui"
|
||||
},
|
||||
"homepage": "https://twenty.com",
|
||||
"bugs": "https://github.com/twentyhq/twenty/issues",
|
||||
"keywords": [
|
||||
"twenty",
|
||||
"ui",
|
||||
"react",
|
||||
"components",
|
||||
"design-system"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.mjs",
|
||||
"style": "./dist/style.css",
|
||||
@@ -50,6 +69,7 @@
|
||||
"@base-ui/react": "^1.5.0",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@sniptt/guards": "^0.2.0",
|
||||
"@tabler/icons-react": "^3.31.0",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^2.30.0",
|
||||
@@ -61,7 +81,6 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-responsive": "^9.0.2",
|
||||
"react-router-dom": "^6.4.4",
|
||||
"twenty-shared": "workspace:*",
|
||||
"zod": "^4.1.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
.root {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare const classNames: {
|
||||
readonly root: 'root';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,9 @@
|
||||
import styles from './VisibilityHidden.module.scss';
|
||||
|
||||
export const VisibilityHidden = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
return <span className={styles.root}>{children}</span>;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
.root {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare const classNames: {
|
||||
readonly root: 'root';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { clsx } from 'clsx';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
import styles from './VisibilityHiddenInput.module.scss';
|
||||
|
||||
// The deprecated Linaria styled.input forwarded refs and accepted all native
|
||||
// input props, so the port preserves that contract.
|
||||
export const VisibilityHiddenInput = forwardRef<
|
||||
HTMLInputElement,
|
||||
React.ComponentPropsWithoutRef<'input'>
|
||||
>(({ className, ...props }, ref) => (
|
||||
// oxlint-disable-next-line react/jsx-props-no-spreading
|
||||
<input ref={ref} className={clsx(styles.root, className)} {...props} />
|
||||
));
|
||||
|
||||
VisibilityHiddenInput.displayName = 'VisibilityHiddenInput';
|
||||
@@ -7,4 +7,6 @@
|
||||
* |___/
|
||||
*/
|
||||
|
||||
export {};
|
||||
export { VisibilityHidden } from './components/VisibilityHidden';
|
||||
export { VisibilityHiddenInput } from './components/VisibilityHiddenInput';
|
||||
export { VISIBILITY_HIDDEN } from './utils/visibility-hidden';
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export const VISIBILITY_HIDDEN = `
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
`;
|
||||
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-address-book" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M20 6v12a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2z" />
|
||||
<path d="M10 16h6" />
|
||||
<path d="M13 11m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M4 8h3" />
|
||||
<path d="M4 12h3" />
|
||||
<path d="M4 16h3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 536 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M26.9568 9.88184H22.1265L30.7753 31.7848H35.4917L26.9568 9.88184ZM13.028 9.88184L4.4917 31.7848H9.32203L11.2305 27.1793H20.2166L22.0126 31.6724H26.8444L18.0832 9.88184H13.028ZM12.5783 23.1361L15.4987 15.3853L18.5315 23.1361H12.5783Z" fill="#D4A574"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 351 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" fill="#D97757" fill-rule="nonzero"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,11 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="#3186FF"/>
|
||||
<path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#gemini-g0)"/>
|
||||
<path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#gemini-g1)"/>
|
||||
<path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#gemini-g2)"/>
|
||||
<defs>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" id="gemini-g0" x1="7" x2="11" y1="15.5" y2="12"><stop stop-color="#08B962"/><stop offset="1" stop-color="#08B962" stop-opacity="0"/></linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" id="gemini-g1" x1="8" x2="11.5" y1="5.5" y2="11"><stop stop-color="#F94543"/><stop offset="1" stop-color="#F94543" stop-opacity="0"/></linearGradient>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" id="gemini-g2" x1="3.5" x2="17.5" y1="13.5" y2="12"><stop stop-color="#FABC12"/><stop offset=".46" stop-color="#FABC12" stop-opacity="0"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,25 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="636.363" fill="none" viewBox="0 0 800 636.363">
|
||||
<path fill="url(#a)" d="M627.272 81.819h172.727v499.999c0 30.123-24.423 54.545-54.545 54.545h-90.909a27.273 27.273 0 0 1-27.273-27.273z"/>
|
||||
<path fill="#FC413D" d="M172.728 81.819H.001v499.999c0 30.123 24.422 54.545 54.545 54.545h90.909a27.273 27.273 0 0 0 27.273-27.273z"/>
|
||||
<path fill="url(#b)" d="M141.937 20.256C105.423-10.435 50.946-5.717 20.255 30.797-10.435 67.306-5.717 121.783 30.796 152.478l345.808 290.677a36.364 36.364 0 0 0 46.796 0l345.808-290.681c36.509-30.691 41.227-85.168 10.536-121.682-30.691-36.509-85.168-41.227-121.677-10.536L400 237.182z"/>
|
||||
<defs>
|
||||
<linearGradient id="a" x1="165" x2="165" y1="44" y2="166" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.54544 0 0 4.54544 -36.363 -118.18)">
|
||||
<stop stop-color="#60D673"/>
|
||||
<stop offset=".17" stop-color="#42C868"/>
|
||||
<stop offset=".39" stop-color="#0EBC5F"/>
|
||||
<stop offset=".62" stop-color="#00A9BB"/>
|
||||
<stop offset=".86" stop-color="#3C90FF"/>
|
||||
<stop offset="1" stop-color="#3186FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b" x1="8" x2="184" y1="46.13" y2="46.13" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.54544 0 0 4.54544 -36.363 -118.18)">
|
||||
<stop offset=".08" stop-color="#FF63A0"/>
|
||||
<stop offset=".3" stop-color="#FC413D"/>
|
||||
<stop offset=".5" stop-color="#FC413D"/>
|
||||
<stop offset=".65" stop-color="#FC413D"/>
|
||||
<stop offset=".72" stop-color="#FC5C30"/>
|
||||
<stop offset=".86" stop-color="#FEB10C"/>
|
||||
<stop offset=".91" stop-color="#FEC700"/>
|
||||
<stop offset=".96" stop-color="#FFDB0F"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,32 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="859.095" fill="none" viewBox="0 0 800 859.095">
|
||||
<path fill="#BBE2FF" d="M64.743 150.866C64.743 67.544 132.287 0 215.609 0h368.782c83.322 0 150.866 67.544 150.866 150.866v159.246c0 83.322-67.544 150.866-150.866 150.866H215.609c-83.322 0-150.866-67.544-150.866-150.866z"/>
|
||||
<path fill="#3C90FF" d="M1.186 216.827C-9.548 135.255 53.952 62.861 136.221 62.861h527.558c82.274 0 145.769 72.394 135.035 153.966l-32.127 244.151 32.127 244.151c10.733 81.572-52.761 153.966-135.035 153.966H136.221c-82.274 0-145.769-72.394-135.035-153.966l32.127-244.151z"/>
|
||||
<mask id="a" width="154" height="152" x="19" y="20" maskUnits="userSpaceOnUse">
|
||||
<path fill="#3C90FF" d="M19.867 49.392C17.818 33.82 29.94 20 45.645 20h100.71c15.706 0 27.827 13.82 25.778 29.392L166 96l6.133 46.608C174.182 158.18 162.061 172 146.355 172H45.645c-15.706 0-27.827-13.82-25.778-29.392L26 96z"/>
|
||||
</mask>
|
||||
<g mask="url(#a)" transform="matrix(5.23839 0 0 5.23839 -102.885 -41.907)">
|
||||
<path fill="url(#b)" d="M0 0h166v76H0z" transform="matrix(1 0 0 -1 13 172)"/>
|
||||
</g>
|
||||
<mask id="c" width="154" height="152" x="19" y="20" maskUnits="userSpaceOnUse">
|
||||
<path fill="#3186FF" d="M19.867 49.392C17.818 33.82 29.94 20 45.645 20h100.71c15.706 0 27.827 13.82 25.778 29.392L166 96l6.133 46.608C174.182 158.18 162.061 172 146.355 172H45.645c-15.706 0-27.827-13.82-25.778-29.392L26 96z"/>
|
||||
</mask>
|
||||
<g mask="url(#c)" transform="matrix(5.23839 0 0 5.23839 -102.885 -41.907)">
|
||||
<path fill="url(#d)" d="M32 27.2C32 16.596 40.596 8 51.2 8h89.6C151.404 8 160 16.596 160 27.2V96H32z" filter="url(#e)"/>
|
||||
</g>
|
||||
<path fill="#FFF" d="M291.843 656.558q-32.908 0-56.454-10.702t-39.864-28.628q-16.056-18.198-22.745-35.584-6.689-17.386-5.348-21.137a10.843 10.843 0 0 1 5.348-5.888l29.702-11.771q3.74-1.87 7.491-.534 3.74 1.069 8.827 12.305 5.354 11.236 14.982 23.814a74.909 74.909 0 0 0 23.546 19.529q13.651 6.956 33.709 6.956 32.373 0 51.373-18.727 19.262-18.727 19.262-47.622 0-31.305-20.336-48.162-20.331-16.852-53.778-16.852H259.47a9.953 9.953 0 0 1-6.957-2.671q-2.672-2.944-2.677-6.689v-28.628q0-4.018 2.672-6.689a9.534 9.534 0 0 1 6.962-2.944h24.343q29.969 0 48.162-16.323 18.192-16.323 18.192-42.274 0-25.679-16.323-41.467-16.323-15.789-44.945-15.789-16.056 0-27.826 5.354a60.241 60.241 0 0 0-20.336 14.982 118.911 118.911 0 0 0-14.714 19.801q-6.15 10.168-9.901 11.237-3.74.801-7.224-1.336l-28.093-13.646q-3.478-1.875-4.547-5.888-1.068-4.012 6.422-18.727 7.759-14.982 23.542-30.503a110.006 110.006 0 0 1 36.925-24.081q21.137-8.565 49.23-8.56 52.174 0 82.672 27.554 30.503 27.292 30.503 72.243 0 31.037-14.982 53.777-14.719 22.735-41.739 32.111v1.069q32.64 9.628 51.368 35.312 19 25.422 18.994 60.734 0 50.571-35.317 82.945-35.307 32.373-92.038 32.373zm268.467-6.155q-4.547 0-8.03-3.478a11.786 11.786 0 0 1-3.206-8.292V341.113l-60.2 43.342q-3.216 2.41-7.496 1.608a10.267 10.267 0 0 1-6.417-4.012l-17.392-24.62a10.372 10.372 0 0 1-1.875-7.491q.801-4.275 4.28-6.684l106.753-76.255q1.341-1.069 2.944-1.603 1.608-.801 3.745-.801h22.478q4.547 0 7.224 3.211 2.944 2.934 2.944 7.491v363.334q0 4.819-3.478 8.292a10.477 10.477 0 0 1-8.03 3.478z"/>
|
||||
<defs>
|
||||
<linearGradient id="b" x1="83" x2="83" y1="76" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4FA0FF"/>
|
||||
<stop offset="1" stop-color="#3186FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="d" x1="89.06" x2="89.06" y1="21.75" y2="96.39" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A9A8FF"/>
|
||||
<stop offset=".8" stop-color="#3C90FF"/>
|
||||
</linearGradient>
|
||||
<filter id="e" width="152" height="112" x="20" y="-4" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" mode="normal"/>
|
||||
<feGaussianBlur result="effect1_foregroundBlur_37330_7673" stdDeviation="6"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.056 4.50022C14.0839 4.44597 9.20616 9.15015 9.15036 15.0106C9.09611 20.8726 13.8855 25.6621 19.8576 25.7163H23.6085V21.7391H20.056C16.3252 21.7825 13.2671 18.8468 13.2237 15.1827C13.1787 11.5216 16.1702 8.52086 19.901 8.47746H20.056C23.7868 8.47746 26.8108 11.4457 26.8216 15.1083V24.8809C26.8216 28.5109 23.8085 31.4683 20.1211 31.5132C18.3617 31.5007 16.6759 30.8049 15.42 29.5726L12.551 32.3905C14.5529 34.3571 17.239 35.4715 20.0451 35.4998H20.1877C26.0823 35.413 30.8175 30.7212 30.85 24.9351V14.8603C30.7059 9.0928 25.9165 4.50022 20.056 4.50022Z" fill="#F55036"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 675 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.84682 4.19127L4.10596 3.92969L3.05961 18.8931L6.80048 19.1547" fill="currentFill"/>
|
||||
<path d="M17.199 4.84524L20.9399 5.10683L19.8935 20.0703L16.1526 19.8087" fill="currentFill"/>
|
||||
<path d="M7.99728 15.4793L8.00663 15.4799L7.99728 15.4793Z" fill="#E8EFFD"/>
|
||||
<path d="M11.7381 15.7409L11.7475 15.7415L11.7381 15.7409Z" fill="#E8EFFD"/>
|
||||
<path d="M15.479 16.0024L15.4884 16.0031L15.479 16.0024Z" fill="#E8EFFD"/>
|
||||
<path d="M7.84682 4.19127L4.10596 3.92969L3.05961 18.8931L6.80048 19.1547M17.199 4.84524L20.9399 5.10683L19.8935 20.0703L16.1526 19.8087M7.99728 15.4793L8.00663 15.4799M11.7381 15.7409L11.7475 15.7415M15.479 16.0024L15.4884 16.0031" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 850 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="26" height="26" viewBox="-1 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.66433 7.43347C5.72493 6.9399 5.97912 6.49062 6.37099 6.18446C6.76285 5.8783 7.26028 5.74035 7.75386 5.80095L18.92 7.17199C19.4136 7.23259 19.8629 7.48678 20.169 7.87864C20.4752 8.27051 20.6131 8.76794 20.5525 9.26151L19.1815 20.4277C19.1209 20.9212 18.8667 21.3705 18.4748 21.6767C18.083 21.9828 17.5855 22.1208 17.092 22.0602L5.92582 20.6891C5.43224 20.6285 4.98296 20.3744 4.6768 19.9825C4.37064 19.5906 4.23269 19.0932 4.2933 18.5996L5.66433 7.43347Z" fill="#E8EFFD"/>
|
||||
<path d="M17.2875 5.08246L16.8305 8.8045L17.2875 5.08246Z" fill="#E8EFFD"/>
|
||||
<path d="M9.84339 4.16844L9.38638 7.89048L9.84339 4.16844Z" fill="#E8EFFD"/>
|
||||
<path d="M5.20732 11.1555L20.0955 12.9836L5.20732 11.1555Z" fill="#E8EFFD"/>
|
||||
<path d="M8.47236 15.3346L10.3334 15.5631L10.1049 17.4241L8.24385 17.1956L8.47236 15.3346Z" fill="#E8EFFD"/>
|
||||
<path d="M17.2875 5.08246L16.8305 8.8045M9.84339 4.16844L9.38638 7.89048M5.20732 11.1555L20.0955 12.9836M5.66433 7.43347C5.72493 6.9399 5.97912 6.49062 6.37099 6.18446C6.76285 5.8783 7.26028 5.74035 7.75386 5.80095L18.92 7.17199C19.4136 7.23259 19.8629 7.48678 20.169 7.87864C20.4752 8.27051 20.6131 8.76794 20.5525 9.26151L19.1815 20.4277C19.1209 20.9212 18.8667 21.3705 18.4748 21.6767C18.083 21.9828 17.5855 22.1208 17.092 22.0602L5.92582 20.6891C5.43224 20.6285 4.98296 20.3744 4.6768 19.9825C4.37064 19.5906 4.23269 19.0932 4.2933 18.5996L5.66433 7.43347ZM8.47236 15.3346L10.3334 15.5631L10.1049 17.4241L8.24385 17.1956L8.47236 15.3346Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,9 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.8968 20.4301L6.54196 20.8745C6.04589 20.9092 5.55636 20.7454 5.18105 20.4191C4.80575 20.0929 4.57542 19.6309 4.54073 19.1348L3.75597 7.91225C3.72128 7.41618 3.88508 6.92665 4.21132 6.55135C4.53757 6.17605 4.99954 5.94571 5.49561 5.91103L16.7182 5.12627C17.2143 5.09158 17.7038 5.25537 18.0791 5.58162C18.4544 5.90786 18.6847 6.36984 18.7194 6.8659L18.981 10.6068" fill="currentFill"/>
|
||||
<path d="M14.7627 17.4803C14.8321 18.4724 15.2928 19.3964 16.0434 20.0488C16.794 20.7013 17.773 21.0289 18.7652 20.9595C19.7573 20.8902 20.6812 20.4295 21.3337 19.6789C21.9862 18.9283 22.3138 17.9492 22.2444 16.9571C22.1751 15.965 21.7144 15.041 20.9638 14.3885C20.2132 13.736 19.2341 13.4084 18.242 13.4778C17.2499 13.5472 16.3259 14.0079 15.6734 14.7585C15.0209 15.5091 14.6933 16.4881 14.7627 17.4803Z" fill="#E8EFFD"/>
|
||||
<path d="M14.717 3.38663L14.9786 7.12749L14.717 3.38663Z" fill="#E8EFFD"/>
|
||||
<path d="M7.23525 3.9098L7.49684 7.65067L7.23525 3.9098Z" fill="#E8EFFD"/>
|
||||
<path d="M4.01756 11.6531L18.981 10.6068L4.01756 11.6531Z" fill="#E8EFFD"/>
|
||||
<path d="M18.4052 15.8122L18.5036 17.2188L19.5042 18.0886" fill="#E8EFFD"/>
|
||||
<path d="M12.8968 20.4301L6.54196 20.8745C6.04589 20.9092 5.55636 20.7454 5.18105 20.4191C4.80575 20.0929 4.57542 19.6309 4.54073 19.1348L3.75597 7.91225C3.72128 7.41618 3.88508 6.92665 4.21132 6.55135C4.53757 6.17605 4.99954 5.94571 5.49561 5.91103L16.7182 5.12627C17.2143 5.09158 17.7038 5.25537 18.0791 5.58162C18.4544 5.90786 18.6847 6.36984 18.7194 6.8659L18.981 10.6068L4.01756 11.6531M14.717 3.38663L14.9786 7.12749M7.23525 3.9098L7.49684 7.65067M18.4052 15.8122L18.5036 17.2188L19.5042 18.0886M14.7627 17.4803C14.8321 18.4724 15.2928 19.3964 16.0434 20.0488C16.794 20.7013 17.773 21.0289 18.7652 20.9595C19.7573 20.8902 20.6812 20.4295 21.3337 19.6789C21.9862 18.9283 22.3138 17.9492 22.2444 16.9571C22.1751 15.965 21.7144 15.041 20.9638 14.3885C20.2132 13.736 19.2341 13.4084 18.242 13.4778C17.2499 13.5472 16.3259 14.0079 15.6734 14.7585C15.0209 15.5091 14.6933 16.4881 14.7627 17.4803Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_39321_100611)">
|
||||
<path d="M10.2501 3.41974L14.9262 3.74672C15.2983 3.77274 15.6447 3.94549 15.8894 4.22697C16.1341 4.50844 16.257 4.87559 16.2309 5.24764C16.1702 6.11577 15.7672 6.92422 15.1104 7.49515C14.4536 8.06608 13.5969 8.35272 12.7288 8.29201L11.7936 8.22662C10.9255 8.16591 10.117 7.76283 9.54608 7.10605C8.97515 6.44927 8.68851 5.59259 8.74922 4.72447C8.77523 4.35242 8.94798 4.00594 9.22946 3.76125C9.51093 3.51657 9.87808 3.39372 10.2501 3.41974Z" fill="#E8EFFD"/>
|
||||
<path d="M4.19089 16.1531L4.25629 15.2179C4.39504 13.2336 5.31637 11.3857 6.81758 10.0807C8.31879 8.77574 10.2769 8.12056 12.2612 8.25931C14.2455 8.39807 16.0934 9.31939 17.3983 10.8206C18.7033 12.3218 19.3585 14.2799 19.2197 16.2642L19.1544 17.1994C19.085 18.1916 18.6243 19.1155 17.8737 19.768C17.1231 20.4205 16.144 20.7481 15.1519 20.6787L7.67017 20.1555C6.67803 20.0862 5.75409 19.6255 5.1016 18.8749C4.4491 18.1243 4.12151 17.1452 4.19089 16.1531Z" fill="#E8EFFD"/>
|
||||
<path d="M10.2501 3.41974L14.9262 3.74672C15.2983 3.77274 15.6447 3.94549 15.8894 4.22697C16.1341 4.50844 16.257 4.87559 16.2309 5.24764C16.1702 6.11577 15.7672 6.92422 15.1104 7.49515C14.4536 8.06608 13.5969 8.35272 12.7288 8.29201L11.7936 8.22662C10.9255 8.16591 10.117 7.76283 9.54608 7.10605C8.97515 6.44927 8.68851 5.59259 8.74922 4.72447C8.77523 4.35242 8.94798 4.00594 9.22946 3.76125C9.51093 3.51657 9.87808 3.39372 10.2501 3.41974Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.19089 16.1531L4.25629 15.2179C4.39504 13.2336 5.31637 11.3857 6.81758 10.0807C8.31879 8.77574 10.2769 8.12056 12.2612 8.25931C14.2455 8.39807 16.0934 9.31939 17.3983 10.8206C18.7033 12.3218 19.3585 14.2799 19.2197 16.2642L19.1544 17.1994C19.085 18.1916 18.6243 19.1155 17.8737 19.768C17.1231 20.4205 16.144 20.7481 15.1519 20.6787L7.67017 20.1555C6.67803 20.0862 5.75409 19.6255 5.1016 18.8749C4.4491 18.1243 4.12151 17.1452 4.19089 16.1531Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_39321_100611">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.2892 3.45947L13.5508 7.20033C13.5681 7.44837 13.6833 7.67935 13.8709 7.84247C14.0586 8.0056 14.3034 8.0875 14.5514 8.07015L18.2923 7.80856" fill="#F0F4FF"/>
|
||||
<path d="M17.272 20.0972L7.91983 20.7511C7.42376 20.7858 6.93422 20.622 6.55892 20.2958C6.18362 19.9695 5.95329 19.5076 5.9186 19.0115L5.00305 5.91847C4.96836 5.4224 5.13215 4.93287 5.4584 4.55756C5.78464 4.18226 6.24662 3.95193 6.74269 3.91724L13.2892 3.45947L18.2923 7.80856L19.0116 18.0959C19.0463 18.592 18.8825 19.0815 18.5563 19.4568C18.23 19.8322 17.7681 20.0625 17.272 20.0972Z" fill="#F0F4FF"/>
|
||||
<path d="M13.2892 3.45947L13.5508 7.20033C13.5681 7.44837 13.6833 7.67935 13.8709 7.84247C14.0586 8.0056 14.3034 8.0875 14.5514 8.07015L18.2923 7.80856M13.2892 3.45947L6.74269 3.91724C6.24662 3.95193 5.78464 4.18226 5.4584 4.55756C5.13215 4.93287 4.96836 5.4224 5.00305 5.91847L5.9186 19.0115C5.95329 19.5076 6.18362 19.9695 6.55892 20.2958C6.93422 20.622 7.42376 20.7858 7.91983 20.7511L17.272 20.0972C17.7681 20.0625 18.23 19.8322 18.5563 19.4568C18.8825 19.0815 19.0463 18.592 19.0116 18.0959L18.2923 7.80856M13.2892 3.45947L18.2923 7.80856" stroke="#8DA4EF" stroke-width="1.33" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.80092 4.84535C6.30485 4.88004 5.84288 5.11037 5.51664 5.48567C5.19039 5.86097 5.0266 6.3505 5.06128 6.84657L5.25747 9.65222C5.30951 10.3963 5.16235 11.1237 4.84837 11.6744C4.53438 12.2251 4.0793 12.554 3.58323 12.5887C4.0793 12.554 4.57572 12.8163 4.96329 13.3179C5.35086 13.8196 5.59782 14.5194 5.64985 15.2635L5.84605 18.0692C5.88073 18.5652 6.11106 19.0272 6.48637 19.3535C6.86167 19.6797 7.3512 19.8435 7.84727 19.8088" fill="currentFill"/>
|
||||
<path d="M16.1531 4.19138C16.6492 4.15669 17.1387 4.32049 17.514 4.64673C17.8893 4.97298 18.1196 5.43495 18.1543 5.93102L18.3505 8.73667C18.4025 9.48077 18.6495 10.1806 19.0371 10.6823C19.4246 11.1839 19.9211 11.4462 20.4171 11.4115C19.9211 11.4462 19.466 11.7751 19.152 12.3258C18.838 12.8765 18.6909 13.6039 18.7429 14.348L18.9391 17.1536C18.9738 17.6497 18.81 18.1392 18.4837 18.5145C18.1575 18.8898 17.6955 19.1202 17.1994 19.1548" fill="currentFill"/>
|
||||
<path d="M6.80092 4.84535C6.30485 4.88004 5.84288 5.11037 5.51664 5.48567C5.19039 5.86097 5.0266 6.3505 5.06128 6.84657L5.25747 9.65222C5.30951 10.3963 5.16235 11.1237 4.84837 11.6744C4.53438 12.2251 4.0793 12.554 3.58323 12.5887C4.0793 12.554 4.57572 12.8163 4.96329 13.3179C5.35086 13.8196 5.59782 14.5194 5.64985 15.2635L5.84605 18.0692C5.88073 18.5652 6.11106 19.0272 6.48637 19.3535C6.86167 19.6797 7.3512 19.8435 7.84727 19.8088M16.1531 4.19138C16.6492 4.15669 17.1387 4.32049 17.514 4.64673C17.8893 4.97298 18.1196 5.43495 18.1543 5.93102L18.3505 8.73667C18.4025 9.48077 18.6495 10.1806 19.0371 10.6823C19.4246 11.1839 19.9211 11.4462 20.4171 11.4115C19.9211 11.4462 19.466 11.7751 19.152 12.3258C18.838 12.8765 18.6909 13.6039 18.7429 14.348L18.9391 17.1536C18.9738 17.6497 18.81 18.1392 18.4837 18.5145C18.1575 18.8898 17.6955 19.1202 17.1994 19.1548" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,17 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="3" fill="none"/>
|
||||
<g clip-path="url(#clip0_36855_127168)">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/>
|
||||
<path d="M3.60925 11.1178C3.49343 12.2198 3.59579 13.3338 3.91049 14.3962C4.22519 15.4586 4.74606 16.4486 5.44336 17.3097C6.14067 18.1708 7.00075 18.8861 7.9745 19.4148C8.94826 19.9435 10.0166 20.2753 11.1186 20.3911C12.2205 20.5069 13.3345 20.4045 14.3969 20.0898C15.4593 19.7751 16.4493 19.2543 17.3104 18.557C18.1715 17.8597 18.8868 16.9996 19.4156 16.0258C19.9443 15.0521 20.276 13.9837 20.3918 12.8818C20.6257 10.6563 19.966 8.42898 18.5577 6.68991C17.1494 4.95084 15.108 3.84243 12.8825 3.60852C10.657 3.37461 8.42971 4.03436 6.69064 5.44263C4.95157 6.8509 3.84316 8.89234 3.60925 11.1178Z" fill="currentFill"/>
|
||||
<path d="M4.46411 8.3797L20.1278 10.026L4.46411 8.3797Z" fill="#E8EFFD"/>
|
||||
<path d="M3.87614 13.9739L19.5399 15.6202L3.87614 13.9739Z" fill="#E8EFFD"/>
|
||||
<path d="M12.416 3.55949C10.5807 5.91142 9.44243 8.73125 9.1306 11.6982C8.81876 14.6651 9.34592 17.6599 10.6521 20.342" fill="#E8EFFD"/>
|
||||
<path d="M13.3487 3.65752C14.6548 6.33963 15.182 9.3345 14.8702 12.3014C14.5583 15.2683 13.42 18.0881 11.5848 20.4401" fill="currentFill"/>
|
||||
<path d="M4.46411 8.3797L20.1278 10.026M3.87614 13.9739L19.5399 15.6202M12.416 3.55949C10.5807 5.91142 9.44243 8.73125 9.1306 11.6982C8.81876 14.6651 9.34592 17.6599 10.6521 20.342M13.3487 3.65752C14.6548 6.33963 15.182 9.3345 14.8702 12.3014C14.5583 15.2683 13.42 18.0881 11.5848 20.4401M3.60925 11.1178C3.49343 12.2198 3.59579 13.3338 3.91049 14.3962C4.22519 15.4586 4.74606 16.4486 5.44336 17.3097C6.14067 18.1708 7.00075 18.8861 7.9745 19.4148C8.94826 19.9435 10.0166 20.2753 11.1186 20.3911C12.2205 20.5069 13.3345 20.4045 14.3969 20.0898C15.4593 19.7751 16.4493 19.2543 17.3104 18.557C18.1715 17.8597 18.8868 16.9996 19.4156 16.0258C19.9443 15.0521 20.276 13.9837 20.3918 12.8818C20.6257 10.6563 19.966 8.42898 18.5577 6.68991C17.1494 4.95084 15.108 3.84243 12.8825 3.60852C10.657 3.37461 8.42971 4.03436 6.69064 5.44263C4.95157 6.8509 3.84316 8.89234 3.60925 11.1178Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_36855_127168">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="3" fill="none"/>
|
||||
<g clip-path="url(#clip0_36855_127259)">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/>
|
||||
<path d="M3.25579 7.91194C3.2211 7.41587 3.3849 6.92633 3.71115 6.55103C4.03739 6.17573 4.49936 5.9454 4.99543 5.91071L18.0885 4.99516C18.5845 4.96047 19.0741 5.12426 19.4494 5.45051C19.8247 5.77675 20.055 6.23873 20.0897 6.7348L20.7437 16.087C20.7783 16.583 20.6145 17.0726 20.2883 17.4479C19.9621 17.8232 19.5001 18.0535 19.004 18.0882L5.91099 19.0037C5.41492 19.0384 4.92538 18.8746 4.55008 18.5484C4.17478 18.2221 3.94445 17.7602 3.90976 17.2641L3.25579 7.91194Z" fill="#E8EFFD"/>
|
||||
<path d="M3.25579 7.91194L12.0651 12.9347L20.0897 6.7348" fill="#E8EFFD"/>
|
||||
<path d="M3.25579 7.91194C3.2211 7.41587 3.3849 6.92633 3.71115 6.55103C4.03739 6.17573 4.49936 5.9454 4.99543 5.91071L18.0885 4.99516C18.5845 4.96047 19.0741 5.12426 19.4494 5.45051C19.8247 5.77675 20.055 6.23873 20.0897 6.7348M3.25579 7.91194L3.90976 17.2641C3.94445 17.7602 4.17478 18.2221 4.55008 18.5484C4.92538 18.8746 5.41492 19.0384 5.91099 19.0037L19.004 18.0882C19.5001 18.0535 19.9621 17.8232 20.2883 17.4479C20.6145 17.0726 20.7783 16.583 20.7437 16.087L20.0897 6.7348M3.25579 7.91194L12.0651 12.9347L20.0897 6.7348" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_36855_127259">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.25628 7.91194C3.22159 7.41587 3.38539 6.92633 3.71163 6.55103C4.03788 6.17573 4.49985 5.9454 4.99592 5.91071L18.0889 4.99516C18.585 4.96047 19.0746 5.12426 19.4499 5.45051C19.8252 5.77675 20.0555 6.23873 20.0902 6.7348L20.7441 16.087C20.7788 16.583 20.615 17.0726 20.2888 17.4479C19.9625 17.8232 19.5006 18.0535 19.0045 18.0882L5.91147 19.0037C5.4154 19.0384 4.92587 18.8746 4.55057 18.5484C4.17527 18.2221 3.94494 17.7602 3.91025 17.2641L3.25628 7.91194Z" fill="#E8EFFD"/>
|
||||
<path d="M14.9367 13.6737L14.6751 9.93282L17.7423 13.4775L17.4807 9.73663" fill="currentFill"/>
|
||||
<path d="M6.51971 14.2623L6.25812 10.5214L9.32536 14.0661L9.06377 10.3252" fill="currentFill"/>
|
||||
<path d="M11.9021 10.5966L11.9028 10.606L11.9021 10.5966Z" fill="#E8EFFD"/>
|
||||
<path d="M12.0983 13.4023L12.099 13.4116L12.0983 13.4023Z" fill="#E8EFFD"/>
|
||||
<path d="M14.9367 13.6737L14.6751 9.93282L17.7423 13.4775L17.4807 9.73663M6.51971 14.2623L6.25812 10.5214L9.32536 14.0661L9.06377 10.3252M11.9021 10.5966L11.9028 10.606M12.0983 13.4023L12.099 13.4116M3.25628 7.91194C3.22159 7.41587 3.38539 6.92633 3.71163 6.55103C4.03788 6.17573 4.49985 5.9454 4.99592 5.91071L18.0889 4.99516C18.585 4.96047 19.0746 5.12426 19.4499 5.45051C19.8252 5.77675 20.0555 6.23873 20.0902 6.7348L20.7441 16.087C20.7788 16.583 20.615 17.0726 20.2888 17.4479C19.9625 17.8232 19.5006 18.0535 19.0045 18.0882L5.91147 19.0037C5.4154 19.0384 4.92587 18.8746 4.55057 18.5484C4.17527 18.2221 3.94494 17.7602 3.91025 17.2641L3.25628 7.91194Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_39400_7686)">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/>
|
||||
<path d="M3.25625 7.91258L8.67136 4.71455L14.4788 7.12782L19.894 3.92979L20.7441 16.0876L15.329 19.2856L9.52151 16.8724L4.10641 20.0704L3.25625 7.91258Z" />
|
||||
<path d="M8.67136 4.71455L9.52151 16.8724L8.67136 4.71455Z" fill="#E8EFFD"/>
|
||||
<path d="M14.4788 7.12782L15.329 19.2856L14.4788 7.12782Z" fill="#E8EFFD"/>
|
||||
<path d="M8.67136 4.71455L3.25625 7.91258L4.10641 20.0704L9.52151 16.8724M8.67136 4.71455L14.4788 7.12782M8.67136 4.71455L9.52151 16.8724M14.4788 7.12782L19.894 3.92979L20.7441 16.0876L15.329 19.2856M14.4788 7.12782L15.329 19.2856M15.329 19.2856L9.52151 16.8724" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_39400_7686">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,14 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentFill" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="3" fill="none"/>
|
||||
<g clip-path="url(#clip0_36855_127138)">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/>
|
||||
<path d="M15.4792 7.99748C15.4098 7.00534 14.9491 6.08139 14.1985 5.4289C13.4479 4.77641 12.4688 4.44882 11.4767 4.5182C10.4846 4.58758 9.56062 5.04824 8.90813 5.79884C8.25564 6.54945 7.92805 7.52851 7.99743 8.52065L8.06282 9.45587C8.1322 10.448 8.59286 11.3719 9.34347 12.0244C10.0941 12.6769 11.0731 13.0045 12.0653 12.9351C13.0574 12.8658 13.9814 12.4051 14.6338 11.6545C15.2863 10.9039 15.6139 9.92483 15.5446 8.93269" fill="#E8EFFD"/>
|
||||
<path d="M8.5206 16.0024C8.58998 16.9945 9.05064 17.9185 9.80124 18.571C10.5518 19.2234 11.5309 19.551 12.5231 19.4817C13.5152 19.4123 14.4391 18.9516 15.0916 18.201C15.7441 17.4504 16.0717 16.4713 16.0023 15.4792L15.4792 7.99748" fill="none"/>
|
||||
<path d="M15.5446 8.93269C15.6139 9.92483 15.2863 10.9039 14.6338 11.6545C13.9814 12.4051 13.0574 12.8658 12.0653 12.9351C11.0731 13.0045 10.0941 12.6769 9.34347 12.0244C8.59286 11.3719 8.1322 10.448 8.06282 9.45587L7.99743 8.52065C7.92805 7.52851 8.25564 6.54945 8.90813 5.79884C9.56062 5.04824 10.4846 4.58758 11.4767 4.5182C12.4688 4.44882 13.4479 4.77641 14.1985 5.4289C14.9491 6.08139 15.4098 7.00534 15.4792 7.99748L16.0023 15.4792C16.0717 16.4713 15.7441 17.4504 15.0916 18.201C14.4391 18.9516 13.5152 19.4123 12.5231 19.4817C11.5309 19.551 10.5518 19.2234 9.80124 18.571C9.05064 17.9185 8.58998 16.9945 8.5206 16.0024" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_36855_127138">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" fill="currentFill"/>
|
||||
<path d="M7.69334 10.456L8.62855 10.3906L8.89014 14.1315" fill="#E8EFFD"/>
|
||||
<path d="M14.5014 13.7391L14.2399 9.99822L17.3071 13.5429L17.0455 9.80203" fill="currentFill"/>
|
||||
<path d="M11.4669 10.662L11.4676 10.6714L11.4669 10.662Z" fill="#E8EFFD"/>
|
||||
<path d="M11.6631 13.4677L11.6637 13.477L11.6631 13.4677Z" fill="#E8EFFD"/>
|
||||
<path d="M7.69334 10.456L8.62855 10.3906L8.89014 14.1315M14.5014 13.7391L14.2399 9.99822L17.3071 13.5429L17.0455 9.80203M11.4669 10.662L11.4676 10.6714M11.6631 13.4677L11.6637 13.477M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" fill="#E8EFFD"/>
|
||||
<path d="M8.62855 10.3906L9.56377 10.3252L9.82536 14.0661" fill="#E8EFFD"/>
|
||||
<path d="M15.1751 9.93282L16.1103 9.86743L16.3719 13.6083" fill="#E8EFFD"/>
|
||||
<path d="M12.4021 10.5966L12.4028 10.606L12.4021 10.5966Z" fill="#E8EFFD"/>
|
||||
<path d="M12.5983 13.4023L12.599 13.4116L12.5983 13.4023Z" fill="#E8EFFD"/>
|
||||
<path d="M8.62855 10.3906L9.56377 10.3252L9.82536 14.0661M15.1751 9.93282L16.1103 9.86743L16.3719 13.6083M12.4021 10.5966L12.4028 10.606M12.5983 13.4023L12.599 13.4116M3.75628 7.91194C3.72159 7.41587 3.88539 6.92633 4.21163 6.55103C4.53788 6.17573 4.99985 5.9454 5.49592 5.91071L18.5889 4.99516C19.085 4.96047 19.5746 5.12426 19.9499 5.45051C20.3252 5.77675 20.5555 6.23873 20.5902 6.7348L21.2441 16.087C21.2788 16.583 21.115 17.0726 20.7888 17.4479C20.4625 17.8232 20.0006 18.0535 19.5045 18.0882L6.41147 19.0037C5.9154 19.0384 5.42587 18.8746 5.05057 18.5484C4.67527 18.2221 4.44494 17.7602 4.41025 17.2641L3.75628 7.91194Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,12 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="3" fill="none"/>
|
||||
<g clip-path="url(#clip0_36855_127302)">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/>
|
||||
<path d="M4.93049 4.97614L8.67136 4.71455L10.8688 9.25984L8.62883 10.8262C9.77242 12.787 11.531 14.3157 13.6319 15.1753L14.8712 12.7391L19.6781 14.2826L19.9397 18.0234C19.9744 18.5195 19.8106 19.009 19.4843 19.3843C19.1581 19.7596 18.6961 19.99 18.2 20.0247C14.5365 20.0581 10.9874 18.7495 8.2224 16.3459C5.45738 13.9423 3.66764 10.6099 3.19085 6.97737C3.15616 6.4813 3.31996 5.99176 3.6462 5.61646C3.97245 5.24116 4.43442 5.01083 4.93049 4.97614Z" fill="currentFill" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_36855_127302">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 974 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.38754 12.4777C5.42223 11.9816 5.65256 11.5196 6.02786 11.1934C6.40316 10.8671 6.89269 10.7033 7.38876 10.738L16.7409 11.392C17.237 11.4267 17.699 11.657 18.0252 12.0323C18.3515 12.4076 18.5153 12.8971 18.4806 13.3932L18.0882 19.0045C18.0535 19.5006 17.8232 19.9625 17.4479 20.2888C17.0726 20.615 16.583 20.7788 16.087 20.7441L6.7348 20.0902C6.23873 20.0555 5.77675 19.8252 5.45051 19.4499C5.12426 19.0746 4.96047 18.585 4.99516 18.0889L5.38754 12.4777Z" fill="#E8EFFD"/>
|
||||
<path d="M10.8026 15.6757C10.7853 15.9237 10.8672 16.1685 11.0303 16.3561C11.1934 16.5438 11.4244 16.6589 11.6725 16.6763C11.9205 16.6936 12.1653 16.6117 12.3529 16.4486C12.5406 16.2855 12.6557 16.0545 12.6731 15.8065C12.6904 15.5584 12.6085 15.3137 12.4454 15.126C12.2823 14.9384 12.0513 14.8232 11.8033 14.8059C11.5552 14.7885 11.3105 14.8704 11.1228 15.0335C10.9352 15.1967 10.82 15.4276 10.8026 15.6757Z" fill="currentFill"/>
|
||||
<path d="M8.32398 10.8034L8.58557 7.06254C8.65494 6.0704 9.1156 5.14646 9.86621 4.49397C10.6168 3.84148 11.5959 3.51389 12.588 3.58327C13.5802 3.65264 14.5041 4.1133 15.1566 4.86391C15.8091 5.61451 16.1367 6.59358 16.0673 7.58572L15.8057 11.3266" fill="#E8EFFD"/>
|
||||
<path d="M8.32398 10.8034L8.58557 7.06254C8.65494 6.0704 9.1156 5.14646 9.86621 4.49397C10.6168 3.84148 11.5959 3.51389 12.588 3.58327C13.5802 3.65264 14.5041 4.1133 15.1566 4.86391C15.8091 5.61451 16.1367 6.59358 16.0673 7.58572L15.8057 11.3266M5.38754 12.4777C5.42223 11.9816 5.65256 11.5196 6.02786 11.1934C6.40316 10.8671 6.89269 10.7033 7.38876 10.738L16.7409 11.392C17.237 11.4267 17.699 11.657 18.0252 12.0323C18.3515 12.4076 18.5153 12.8971 18.4806 13.3932L18.0882 19.0045C18.0535 19.5006 17.8232 19.9625 17.4479 20.2888C17.0726 20.615 16.583 20.7788 16.087 20.7441L6.7348 20.0902C6.23873 20.0555 5.77675 19.8252 5.45051 19.4499C5.12426 19.0746 4.96047 18.585 4.99516 18.0889L5.38754 12.4777ZM10.8026 15.6757C10.7853 15.9237 10.8672 16.1685 11.0303 16.3561C11.1934 16.5438 11.4244 16.6589 11.6725 16.6763C11.9205 16.6936 12.1653 16.6117 12.3529 16.4486C12.5406 16.2855 12.6557 16.0545 12.6731 15.8065C12.6904 15.5584 12.6085 15.3137 12.4454 15.126C12.2823 14.9384 12.0513 14.8232 11.8033 14.8059C11.5552 14.7885 11.3105 14.8704 11.1228 15.0335C10.9352 15.1967 10.82 15.4276 10.8026 15.6757Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_39321_100605)">
|
||||
<path d="M10.6518 4.4387C11.0177 3.18817 12.7418 3.06761 13.2782 4.25504L15.0487 8.17475C15.2173 8.54805 15.5406 8.82907 15.9337 8.9441L20.0617 10.1519C21.3122 10.5177 21.4328 12.2418 20.2453 12.7782L16.3256 14.5487C15.9523 14.7173 15.6713 15.0406 15.5563 15.4337L14.3485 19.5617C13.9826 20.8122 12.2585 20.9328 11.7222 19.7454L9.95166 15.8257C9.78304 15.4524 9.45976 15.1713 9.06662 15.0563L4.93866 13.8485C3.68814 13.4827 3.56757 11.7586 4.75501 11.2222L8.67471 9.4517C9.04801 9.28308 9.32903 8.9598 9.44406 8.56666L10.6518 4.4387Z" fill="currentFill" stroke="currentColor" stroke-width="1.5"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_39321_100605">
|
||||
<rect width="20.6124" height="20.6124" fill="white" transform="translate(1.5 2.43799) rotate(-4)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 908 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.06327 9.89091C9.57978 9.85479 9.96921 9.4068 9.93309 8.8903C9.89697 8.37379 9.44898 7.98436 8.93248 8.02048C8.41597 8.05659 8.02654 8.50458 8.06266 9.02109C8.09878 9.53759 8.54677 9.92703 9.06327 9.89091Z" fill="currentFill"/>
|
||||
<path d="M4.69131 7.84715L4.94367 11.4562C4.97879 11.9584 5.21167 12.4261 5.5919 12.7566L13.7129 19.8161C13.901 19.9796 14.1196 20.1046 14.356 20.1837C14.5925 20.2628 14.8422 20.2946 15.0909 20.2772C15.3396 20.2598 15.5825 20.1936 15.8056 20.0823C16.0287 19.9711 16.2278 19.8169 16.3913 19.6288L20.596 14.7918C20.7596 14.6036 20.8846 14.3851 20.9637 14.1487C21.0428 13.9122 21.0746 13.6625 21.0572 13.4138C21.0398 13.1651 20.9736 12.9222 20.8623 12.6991C20.7511 12.4759 20.5969 12.2769 20.4088 12.1133L12.2868 5.05395C11.9071 4.72385 11.4117 4.55804 10.9098 4.59295L7.30077 4.84531C6.55666 4.89735 5.8637 5.24284 5.37434 5.8058C4.88497 6.36875 4.63927 7.10305 4.69131 7.84715Z" fill="currentFill"/>
|
||||
<path d="M9.06327 9.89091C9.57978 9.85479 9.96921 9.4068 9.93309 8.8903C9.89697 8.37379 9.44898 7.98436 8.93248 8.02048C8.41597 8.05659 8.02654 8.50458 8.06266 9.02109C8.09878 9.53759 8.54677 9.92703 9.06327 9.89091Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.69131 7.84715L4.94367 11.4562C4.97879 11.9584 5.21167 12.4261 5.5919 12.7566L13.7129 19.8161C13.901 19.9796 14.1196 20.1046 14.356 20.1837C14.5925 20.2628 14.8422 20.2946 15.0909 20.2772C15.3396 20.2598 15.5825 20.1936 15.8056 20.0823C16.0287 19.9711 16.2278 19.8169 16.3913 19.6288L20.596 14.7918C20.7596 14.6036 20.8846 14.3851 20.9637 14.1487C21.0428 13.9122 21.0746 13.6625 21.0572 13.4138C21.0398 13.1651 20.9736 12.9222 20.8623 12.6991C20.7511 12.4759 20.5969 12.2769 20.4088 12.1133L12.2868 5.05395C11.9071 4.72385 11.4117 4.55804 10.9098 4.59295L7.30077 4.84531C6.55666 4.89735 5.8637 5.24284 5.37434 5.8058C4.88497 6.36875 4.63927 7.10305 4.69131 7.84715Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.23485 6.65934L5.58444 6.84467C5.08217 6.87979 4.61443 7.113 4.2841 7.493C3.95378 7.87299 3.78794 8.36864 3.82306 8.87091L4.00839 11.5213C4.04351 12.0235 4.27639 12.4912 4.65662 12.8218L10.7764 18.1416C10.9645 18.3052 11.1831 18.4301 11.4195 18.5092C11.656 18.5883 11.9057 18.6201 12.1544 18.6027C12.4031 18.5853 12.646 18.5191 12.8691 18.4079C13.0922 18.2966 13.2913 18.1425 13.4548 17.9543L15.9199 15.1185C16.0835 14.9304 16.2084 14.7118 16.2875 14.4754C16.3667 14.239 16.3984 13.9892 16.381 13.7405C16.3636 13.4918 16.2974 13.2489 16.1862 13.0258C16.0749 12.8027 15.9208 12.6037 15.7326 12.4401L9.61192 7.12034C9.23213 6.79024 8.73683 6.62443 8.23485 6.65934Z" fill="#E8EFFD"/>
|
||||
<path d="M18.1301 17.6281L20.5952 14.7923C20.7587 14.6042 20.8837 14.3856 20.9628 14.1492C21.0419 13.9127 21.0737 13.663 21.0563 13.4143C21.0389 13.1656 20.9727 12.9227 20.8614 12.6996C20.7502 12.4765 20.596 12.2774 20.4079 12.1139L13.2866 5.9243" fill="none"/>
|
||||
<path d="M6.69086 9.58667L6.68151 9.58732L6.69086 9.58667Z" fill="#E8EFFD"/>
|
||||
<path d="M18.1301 17.6281L20.5952 14.7923C20.7587 14.6042 20.8837 14.3856 20.9628 14.1492C21.0419 13.9127 21.0737 13.663 21.0563 13.4143C21.0389 13.1656 20.9727 12.9227 20.8614 12.6996C20.7502 12.4765 20.596 12.2774 20.4079 12.1139L13.2866 5.9243M6.69086 9.58667L6.68151 9.58732M8.23485 6.65934L5.58444 6.84467C5.08217 6.87979 4.61443 7.113 4.2841 7.493C3.95378 7.87299 3.78794 8.36864 3.82306 8.87091L4.00839 11.5213C4.04351 12.0235 4.27639 12.4912 4.65662 12.8218L10.7764 18.1416C10.9645 18.3052 11.1831 18.4301 11.4195 18.5092C11.656 18.5883 11.9057 18.6201 12.1544 18.6027C12.4031 18.5853 12.646 18.5191 12.8691 18.4079C13.0922 18.2966 13.2913 18.1425 13.4548 17.9543L15.9199 15.1185C16.0835 14.9304 16.2084 14.7118 16.2875 14.4754C16.3667 14.239 16.3984 13.9892 16.381 13.7405C16.3636 13.4918 16.2974 13.2489 16.1862 13.0258C16.0749 12.8027 15.9208 12.6037 15.7326 12.4401L9.61192 7.12034C9.23213 6.79024 8.73683 6.62443 8.23485 6.65934Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,17 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="3" fill="none"/>
|
||||
<g clip-path="url(#clip0_36855_127272)">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="none"/>
|
||||
<path d="M3.75727 18.6752L6.55436 18.9691L3.75727 18.6752Z" fill="#E8EFFD"/>
|
||||
<path d="M13.0809 19.6551L19.6075 20.3411L13.0809 19.6551Z" fill="#E8EFFD"/>
|
||||
<path d="M6.94965 14.2974L13.383 14.9735L6.94965 14.2974Z" fill="#E8EFFD"/>
|
||||
<path d="M10.8797 6.50999L14.9448 19.8518L10.8797 6.50999Z" fill="#E8EFFD"/>
|
||||
<path d="M4.68963 18.7731L11.8517 4.44329L13.7165 4.63928L18.6751 20.2431" fill="none"/>
|
||||
<path d="M3.75727 18.6752L6.55436 18.9691M13.0809 19.6551L19.6075 20.3411M6.94965 14.2974L13.383 14.9735M10.8797 6.50999L14.9448 19.8518M4.68963 18.7731L11.8517 4.44329L13.7165 4.63928L18.6751 20.2431" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_36855_127272">
|
||||
<rect x="0.75" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_39321_100602)">
|
||||
<path d="M14.3703 11.869C14.405 12.3651 14.6354 12.8271 15.0107 13.1533C15.386 13.4796 15.8755 13.6433 16.3716 13.6087C16.8676 13.574 17.3296 13.3436 17.6559 12.9683C17.9821 12.593 18.1459 12.1035 18.1112 11.6074C18.0765 11.1114 17.8462 10.6494 17.4709 10.3231C17.0956 9.9969 16.6061 9.8331 16.11 9.86779C15.6139 9.90248 15.1519 10.1328 14.8257 10.5081C14.4995 10.8834 14.3357 11.3729 14.3703 11.869Z" fill="currentFill"/>
|
||||
<path d="M3.14775 12.6538C3.04369 11.1656 3.53507 9.69697 4.51381 8.57107C5.49255 7.44516 6.87846 6.75417 8.36667 6.6501L15.8484 6.12693C17.3366 6.02286 18.8052 6.51425 19.9311 7.49298C21.057 8.47172 21.748 9.85764 21.8521 11.3458C21.9561 12.8341 21.4648 14.3026 20.486 15.4286C19.5073 16.5545 18.1214 17.2455 16.6332 17.3495L9.15143 17.8727C7.66322 17.9768 6.19463 17.4854 5.06872 16.5066C3.94281 15.5279 3.25182 14.142 3.14775 12.6538Z" fill="currentFill"/>
|
||||
<path d="M14.3703 11.869C14.405 12.3651 14.6354 12.8271 15.0107 13.1533C15.386 13.4796 15.8755 13.6433 16.3716 13.6087C16.8676 13.574 17.3296 13.3436 17.6559 12.9683C17.9821 12.593 18.1459 12.1035 18.1112 11.6074C18.0765 11.1114 17.8462 10.6494 17.4709 10.3231C17.0956 9.9969 16.6061 9.8331 16.11 9.86779C15.6139 9.90248 15.1519 10.1328 14.8257 10.5081C14.4995 10.8834 14.3357 11.3729 14.3703 11.869Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M3.14775 12.6538C3.04369 11.1656 3.53507 9.69697 4.51381 8.57107C5.49255 7.44516 6.87846 6.75417 8.36667 6.6501L15.8484 6.12693C17.3366 6.02286 18.8052 6.51425 19.9311 7.49298C21.057 8.47172 21.748 9.85764 21.8521 11.3458C21.9561 12.8341 21.4648 14.3026 20.486 15.4286C19.5073 16.5545 18.1214 17.2455 16.6332 17.3495L9.15143 17.8727C7.66322 17.9768 6.19463 17.4854 5.06872 16.5066C3.94281 15.5279 3.25182 14.142 3.14775 12.6538Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_39321_100602">
|
||||
<rect x="1.25" y="0.75" width="22.5" height="22.5" rx="2.25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="25" height="26" viewBox="0 0 25 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.50317 7.59525C4.56818 6.85217 4.92571 6.16535 5.49712 5.68588C6.06853 5.20641 6.80701 4.97357 7.55009 5.03858L18.7573 6.01908C19.5004 6.0841 20.1872 6.44163 20.6667 7.01304C21.1461 7.58445 21.379 8.32292 21.314 9.06601L20.4969 18.4053C20.4319 19.1484 20.0743 19.8352 19.5029 20.3147C18.9315 20.7942 18.193 21.027 17.4499 20.962L6.24275 19.9815C5.49967 19.9165 4.81285 19.559 4.33338 18.9875C3.85391 18.4161 3.62107 17.6777 3.68608 16.9346L4.50317 7.59525Z" fill="currentFill"/>
|
||||
<path d="M7.99377 10.7239C7.95043 11.2193 8.10566 11.7116 8.4253 12.0925C8.74495 12.4735 9.20283 12.7118 9.69822 12.7552C10.1936 12.7985 10.6859 12.6433 11.0669 12.3236C11.4478 12.004 11.6862 11.5461 11.7295 11.0507C11.7728 10.5553 11.6176 10.063 11.298 9.68208C10.9783 9.30114 10.5204 9.06278 10.0251 9.01944C9.52966 8.9761 9.03735 9.13132 8.65641 9.45097C8.27547 9.77062 8.03711 10.2285 7.99377 10.7239Z" fill="currentFill"/>
|
||||
<path d="M15.6286 9.50969L17.4965 9.67311L15.6286 9.50969Z" fill="#E8EFFD"/>
|
||||
<path d="M15.3018 13.2454L17.1697 13.4088L15.3018 13.2454Z" fill="#E8EFFD"/>
|
||||
<path d="M7.50352 16.3275L16.8428 17.1446L7.50352 16.3275Z" fill="#E8EFFD"/>
|
||||
<path d="M15.6286 9.50969L17.4965 9.67311M15.3018 13.2454L17.1697 13.4088M7.50352 16.3275L16.8428 17.1446M4.50317 7.59525C4.56818 6.85217 4.92571 6.16535 5.49712 5.68588C6.06853 5.20641 6.80701 4.97357 7.55009 5.03858L18.7573 6.01908C19.5004 6.0841 20.1872 6.44163 20.6667 7.01304C21.1461 7.58445 21.379 8.32292 21.314 9.06601L20.4969 18.4053C20.4319 19.1484 20.0743 19.8352 19.5029 20.3147C18.9315 20.7942 18.193 21.027 17.4499 20.962L6.24275 19.9815C5.49967 19.9165 4.81285 19.559 4.33338 18.9875C3.85391 18.4161 3.62107 17.6777 3.68608 16.9346L4.50317 7.59525ZM7.99377 10.7239C7.95043 11.2193 8.10566 11.7116 8.4253 12.0925C8.74495 12.4735 9.20283 12.7118 9.69822 12.7552C10.1936 12.7985 10.6859 12.6433 11.0669 12.3236C11.4478 12.004 11.6862 11.5461 11.7295 11.0507C11.7728 10.5553 11.6176 10.063 11.298 9.68208C10.9783 9.30114 10.5204 9.06278 10.0251 9.01944C9.52966 8.9761 9.03735 9.13132 8.65641 9.45097C8.27547 9.77062 8.03711 10.2285 7.99377 10.7239Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.08295 12.5883C4.16025 13.6937 4.45449 14.7729 4.94889 15.7646C5.44329 16.7562 6.12816 17.6407 6.9644 18.3676C7.80064 19.0946 8.77187 19.6497 9.82264 20.0012C10.8734 20.3528 11.9831 20.494 13.0885 20.4167C14.1938 20.3394 15.2731 20.0452 16.2647 19.5508C17.2563 19.0564 18.1408 18.3715 18.8678 17.5353C19.5947 16.699 20.1498 15.7278 20.5014 14.677C20.853 13.6263 20.9941 12.5165 20.9168 11.4112C20.8396 10.3059 20.5453 9.22658 20.0509 8.23497C19.5565 7.24336 18.8716 6.35883 18.0354 5.6319C17.1992 4.90497 16.2279 4.34987 15.1772 3.99828C14.1264 3.6467 13.0167 3.50552 11.9113 3.58282C10.806 3.66011 9.72672 3.95435 8.73511 4.44875C7.74349 4.94315 6.85897 5.62803 6.13204 6.46427C5.40511 7.3005 4.85 8.27174 4.49842 9.32251C4.14684 10.3733 4.00566 11.483 4.08295 12.5883Z" fill="none"/>
|
||||
<path d="M9.56346 10.3255C9.61549 11.0696 9.96099 11.7626 10.5239 12.252C11.0869 12.7413 11.8212 12.987 12.5653 12.935C13.3094 12.8829 14.0024 12.5375 14.4917 11.9745C14.9811 11.4115 15.2268 10.6772 15.1748 9.93314C15.1227 9.18904 14.7772 8.49608 14.2143 8.00671C13.6513 7.51734 12.917 7.27165 12.1729 7.32368C11.4288 7.37571 10.7359 7.72121 10.2465 8.28416C9.75712 8.84712 9.51143 9.58142 9.56346 10.3255Z" fill="#E8EFFD"/>
|
||||
<path d="M7.49359 18.7865C7.6712 17.9999 8.09763 17.2915 8.70962 16.7664C9.32162 16.2413 10.0866 15.9274 10.891 15.8714L14.6319 15.6098C15.4373 15.5532 16.2395 15.7581 16.9192 16.194C17.5989 16.6299 18.1197 17.2735 18.4042 18.0291" fill="currentFill"/>
|
||||
<path d="M7.49359 18.7865C7.6712 17.9999 8.09763 17.2915 8.70962 16.7664C9.32162 16.2413 10.0866 15.9274 10.891 15.8714L14.6319 15.6098C15.4373 15.5532 16.2395 15.7581 16.9192 16.194C17.5989 16.6299 18.1197 17.2735 18.4042 18.0291M4.08295 12.5883C4.16025 13.6937 4.45449 14.7729 4.94889 15.7646C5.44329 16.7562 6.12816 17.6407 6.9644 18.3676C7.80064 19.0946 8.77187 19.6497 9.82264 20.0012C10.8734 20.3528 11.9831 20.494 13.0885 20.4167C14.1938 20.3394 15.2731 20.0452 16.2647 19.5508C17.2563 19.0564 18.1408 18.3715 18.8678 17.5353C19.5947 16.699 20.1498 15.7278 20.5014 14.677C20.853 13.6263 20.9941 12.5165 20.9168 11.4112C20.8396 10.3059 20.5453 9.22658 20.0509 8.23497C19.5565 7.24336 18.8716 6.35883 18.0354 5.6319C17.1992 4.90497 16.2279 4.34987 15.1772 3.99828C14.1264 3.6467 13.0167 3.50552 11.9113 3.58282C10.806 3.66011 9.72672 3.95435 8.73511 4.44875C7.7435 4.94315 6.85897 5.62803 6.13204 6.46427C5.40511 7.3005 4.85 8.27174 4.49842 9.32251C4.14684 10.3733 4.00566 11.483 4.08295 12.5883ZM9.56346 10.3255C9.61549 11.0696 9.96099 11.7626 10.5239 12.252C11.0869 12.7413 11.8212 12.987 12.5653 12.935C13.3094 12.8829 14.0024 12.5375 14.4917 11.9745C14.9811 11.4115 15.2268 10.6772 15.1748 9.93314C15.1227 9.18904 14.7772 8.49608 14.2143 8.00671C13.6513 7.51734 12.917 7.27165 12.1729 7.32368C11.4288 7.37571 10.7359 7.72121 10.2465 8.28416C9.75712 8.84712 9.51143 9.58142 9.56346 10.3255Z" stroke="currentColor" stroke-width="1.49625" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,19 @@
|
||||
<svg width="42" height="42" viewBox="0 0 42 42" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_41725_330814)">
|
||||
<rect x="2" width="40" height="40" rx="20" fill="white"/>
|
||||
<rect x="3" y="1" width="38" height="38" rx="19" stroke="#333333" stroke-width="2"/>
|
||||
<path d="M18 19V15C18 13.9391 18.4214 12.9217 19.1716 12.1716C19.9217 11.4214 20.9391 11 22 11C23.0609 11 24.0783 11.4214 24.8284 12.1716C25.5786 12.9217 26 13.9391 26 15V19M15 21C15 20.4696 15.2107 19.9609 15.5858 19.5858C15.9609 19.2107 16.4696 19 17 19H27C27.5304 19 28.0391 19.2107 28.4142 19.5858C28.7893 19.9609 29 20.4696 29 21V27C29 27.5304 28.7893 28.0391 28.4142 28.4142C28.0391 28.7893 27.5304 29 27 29H17C16.4696 29 15.9609 28.7893 15.5858 28.4142C15.2107 28.0391 15 27.5304 15 27V21ZM21 24C21 24.2652 21.1054 24.5196 21.2929 24.7071C21.4804 24.8946 21.7348 25 22 25C22.2652 25 22.5196 24.8946 22.7071 24.7071C22.8946 24.5196 23 24.2652 23 24C23 23.7348 22.8946 23.4804 22.7071 23.2929C22.5196 23.1054 22.2652 23 22 23C21.7348 23 21.4804 23.1054 21.2929 23.2929C21.1054 23.4804 21 23.7348 21 24Z" stroke="#333333" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_41725_330814" x="0" y="0" width="42" height="42" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feMorphology radius="2" operator="erode" in="SourceAlpha" result="effect1_dropShadow_41725_330814"/>
|
||||
<feOffset dx="-4" dy="4"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.2 0 0 0 0 0.2 0 0 0 0 0.2 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_41725_330814"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_41725_330814" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,17 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M3 5m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z" />
|
||||
<path d="M16 10h1v4" />
|
||||
<path d="M7 14v-4l3 4v-4" />
|
||||
<path d="M13 10.5l0 .01" />
|
||||
<path d="M13 13.5l0 .01" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 419 B |
@@ -0,0 +1,28 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="63.3336 29.3504 384.3334 418.3166" width="512px" height="512px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd">
|
||||
<g><path style="opacity:0.995" fill="#53d9fe" d="M 159.5,63.5 C 159.667,77.504 159.5,91.504 159,105.5C 153.578,116.468 145.412,119.301 134.5,114C 131.567,111.736 129.4,108.902 128,105.5C 127.5,91.504 127.333,77.504 127.5,63.5C 127.2,55.7767 127.533,48.1101 128.5,40.5C 133.149,32.1837 140.149,29.3504 149.5,32C 154,33.8333 157.167,37 159,41.5C 159.5,48.8258 159.666,56.1591 159.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:0.995" fill="#53d9fe" d="M 383.5,63.5 C 383.667,77.504 383.5,91.504 383,105.5C 377.578,116.468 369.412,119.301 358.5,114C 355.567,111.736 353.4,108.902 352,105.5C 351.5,91.504 351.333,77.504 351.5,63.5C 351.2,55.7767 351.533,48.1101 352.5,40.5C 357.149,32.1837 364.149,29.3504 373.5,32C 378,33.8333 381.167,37 383,41.5C 383.5,48.8258 383.666,56.1591 383.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:0.997" fill="#076cb3" d="M 116.5,63.5 C 116.5,74.5 116.5,85.5 116.5,96.5C 98.8499,99.275 81.1832,101.942 63.5,104.5C 63.3336,95.4938 63.5002,86.4938 64,77.5C 66.5,71 71,66.5 77.5,64C 90.4957,63.5001 103.496,63.3334 116.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#066bb3" d="M 170.5,63.5 C 225.167,63.5 279.833,63.5 334.5,63.5C 280.02,72.1889 225.353,80.5222 170.5,88.5C 170.5,80.1667 170.5,71.8333 170.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#0566b1" d="M 334.5,63.5 C 336.5,63.5 338.5,63.5 340.5,63.5C 340.333,77.504 340.5,91.504 341,105.5C 347.935,125.883 361.435,132.049 381.5,124C 386.876,120.429 390.709,115.595 393,109.5C 394.435,94.2246 394.935,78.8913 394.5,63.5C 407.504,63.3334 420.504,63.5001 433.5,64C 440,66.5 444.5,71 447,77.5C 447.5,90.8292 447.667,104.163 447.5,117.5C 379.316,127.478 311.316,137.811 243.5,148.5C 183.5,148.5 123.5,148.5 63.5,148.5C 63.5,133.833 63.5,119.167 63.5,104.5C 81.1832,101.942 98.8499,99.275 116.5,96.5C 116.99,118.074 127.99,128.24 149.5,127C 160.88,123.621 167.714,116.121 170,104.5C 170.499,99.1771 170.666,93.8437 170.5,88.5C 225.353,80.5222 280.02,72.1889 334.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#0662a7" d="M 116.5,63.5 C 120.167,63.5 123.833,63.5 127.5,63.5C 127.333,77.504 127.5,91.504 128,105.5C 129.4,108.902 131.567,111.736 134.5,114C 145.412,119.301 153.578,116.468 159,105.5C 159.5,91.504 159.667,77.504 159.5,63.5C 163.167,63.5 166.833,63.5 170.5,63.5C 170.5,71.8333 170.5,80.1667 170.5,88.5C 170.666,93.8437 170.499,99.1771 170,104.5C 167.714,116.121 160.88,123.621 149.5,127C 127.99,128.24 116.99,118.074 116.5,96.5C 116.5,85.5 116.5,74.5 116.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#055fa6" d="M 340.5,63.5 C 344.167,63.5 347.833,63.5 351.5,63.5C 351.333,77.504 351.5,91.504 352,105.5C 353.4,108.902 355.567,111.736 358.5,114C 369.412,119.301 377.578,116.468 383,105.5C 383.5,91.504 383.667,77.504 383.5,63.5C 387.167,63.5 390.833,63.5 394.5,63.5C 394.935,78.8913 394.435,94.2246 393,109.5C 390.709,115.595 386.876,120.429 381.5,124C 361.435,132.049 347.935,125.883 341,105.5C 340.5,91.504 340.333,77.504 340.5,63.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#0462af" d="M 447.5,117.5 C 447.5,127.833 447.5,138.167 447.5,148.5C 379.5,148.5 311.5,148.5 243.5,148.5C 311.316,137.811 379.316,127.478 447.5,117.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#2cb4ec" d="M 63.5,149.5 C 178.167,149.333 292.834,149.5 407.5,150C 292.823,163.168 178.157,176.335 63.5,189.5C 63.5,176.167 63.5,162.833 63.5,149.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#2ab1ea" d="M 63.5,149.5 C 63.5,149.167 63.5,148.833 63.5,148.5C 123.5,148.5 183.5,148.5 243.5,148.5C 311.5,148.5 379.5,148.5 447.5,148.5C 447.5,164.167 447.5,179.833 447.5,195.5C 430.821,197.15 414.154,198.983 397.5,201C 396.944,201.383 396.611,201.883 396.5,202.5C 387.161,202.334 377.827,202.5 368.5,203C 367.016,203.662 365.683,204.496 364.5,205.5C 364.44,204.957 364.107,204.624 363.5,204.5C 348.897,206.604 334.23,208.271 319.5,209.5C 317.691,206.861 315.358,204.694 312.5,203C 302.833,202.333 293.167,202.333 283.5,203C 279.002,205.494 276.668,209.327 276.5,214.5C 262.551,216.457 248.551,218.124 234.5,219.5C 235.834,212.344 233.5,206.844 227.5,203C 217.5,202.333 207.5,202.333 197.5,203C 195.291,204.873 193.458,207.04 192,209.5C 191.501,214.489 191.334,219.489 191.5,224.5C 148.802,229.355 106.135,234.355 63.5,239.5C 63.5,222.833 63.5,206.167 63.5,189.5C 178.157,176.335 292.823,163.168 407.5,150C 292.834,149.5 178.167,149.333 63.5,149.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fdfefe" d="M 234.5,219.5 C 234.666,225.176 234.499,230.843 234,236.5C 232.895,239.937 230.728,242.437 227.5,244C 217.5,244.667 207.5,244.667 197.5,244C 191.992,238.726 189.992,232.226 191.5,224.5C 191.334,219.489 191.501,214.489 192,209.5C 193.458,207.04 195.291,204.873 197.5,203C 207.5,202.333 217.5,202.333 227.5,203C 233.5,206.844 235.834,212.344 234.5,219.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fdfefe" d="M 319.5,209.5 C 319.666,218.506 319.5,227.506 319,236.5C 317.613,240.721 314.779,243.388 310.5,244.5C 300.727,244.948 291.061,244.448 281.5,243C 279.383,241.269 277.883,239.102 277,236.5C 276.5,229.174 276.334,221.841 276.5,214.5C 276.668,209.327 279.002,205.494 283.5,203C 293.167,202.333 302.833,202.333 312.5,203C 315.358,204.694 317.691,206.861 319.5,209.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fefefe" d="M 396.5,202.5 C 399.87,203.432 402.37,205.432 404,208.5C 404.667,218.167 404.667,227.833 404,237.5C 403.167,241 401,243.167 397.5,244C 387.833,244.667 378.167,244.667 368.5,244C 365.619,242.749 363.786,240.583 363,237.5C 362.333,227.833 362.333,218.167 363,208.5C 363.513,207.473 364.013,206.473 364.5,205.5C 365.683,204.496 367.016,203.662 368.5,203C 377.827,202.5 387.161,202.334 396.5,202.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#28ade9" d="M 276.5,214.5 C 276.334,221.841 276.5,229.174 277,236.5C 277.883,239.102 279.383,241.269 281.5,243C 291.061,244.448 300.727,244.948 310.5,244.5C 228.201,252.385 145.867,261.385 63.5,271.5C 63.5,260.833 63.5,250.167 63.5,239.5C 106.135,234.355 148.802,229.355 191.5,224.5C 189.992,232.226 191.992,238.726 197.5,244C 207.5,244.667 217.5,244.667 227.5,244C 230.728,242.437 232.895,239.937 234,236.5C 234.499,230.843 234.666,225.176 234.5,219.5C 248.551,218.124 262.551,216.457 276.5,214.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#26aae8" d="M 447.5,195.5 C 447.5,215.167 447.5,234.833 447.5,254.5C 374.963,262.277 302.63,270.61 230.5,279.5C 229.118,278.199 227.452,277.366 225.5,277C 216.833,276.333 208.167,276.333 199.5,277C 195.65,278.353 192.983,280.853 191.5,284.5C 190.903,283.861 190.07,283.528 189,283.5C 176.142,285.128 163.309,286.795 150.5,288.5C 149.833,295.655 149.167,302.655 148.5,309.5C 148.945,300.06 148.445,290.726 147,281.5C 145.269,279.383 143.102,277.883 140.5,277C 131.833,276.333 123.167,276.333 114.5,277C 111.898,277.883 109.731,279.383 108,281.5C 106.555,290.726 106.055,300.06 106.5,309.5C 105.512,304.36 105.179,299.026 105.5,293.5C 91.4044,294.732 77.4044,296.399 63.5,298.5C 63.5,289.5 63.5,280.5 63.5,271.5C 145.867,261.385 228.201,252.385 310.5,244.5C 314.779,243.388 317.613,240.721 319,236.5C 319.5,227.506 319.666,218.506 319.5,209.5C 334.23,208.271 348.897,206.604 363.5,204.5C 364.107,204.624 364.44,204.957 364.5,205.5C 364.013,206.473 363.513,207.473 363,208.5C 362.333,218.167 362.333,227.833 363,237.5C 363.786,240.583 365.619,242.749 368.5,244C 378.167,244.667 387.833,244.667 397.5,244C 401,243.167 403.167,241 404,237.5C 404.667,227.833 404.667,218.167 404,208.5C 402.37,205.432 399.87,203.432 396.5,202.5C 396.611,201.883 396.944,201.383 397.5,201C 414.154,198.983 430.821,197.15 447.5,195.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#22a5e6" d="M 447.5,254.5 C 447.5,274.167 447.5,293.833 447.5,313.5C 431.469,314.874 415.469,316.54 399.5,318.5C 401.168,316.66 402.668,314.66 404,312.5C 404.95,302.067 404.617,291.734 403,281.5C 401.269,279.383 399.102,277.883 396.5,277C 387.833,276.333 379.167,276.333 370.5,277C 367.063,278.105 364.563,280.272 363,283.5C 362.333,293.167 362.333,302.833 363,312.5C 364.5,315.333 366.667,317.5 369.5,319C 375.157,319.499 380.824,319.666 386.5,319.5C 296.491,330.094 206.491,340.76 116.5,351.5C 114.784,351.629 113.117,351.962 111.5,352.5C 111.083,351.876 110.416,351.543 109.5,351.5C 94.2179,353.66 78.8845,355.327 63.5,356.5C 63.5,337.167 63.5,317.833 63.5,298.5C 77.4044,296.399 91.4044,294.732 105.5,293.5C 105.179,299.026 105.512,304.36 106.5,309.5C 107.07,313.912 109.403,317.078 113.5,319C 123.574,319.923 133.574,319.59 143.5,318C 146.596,315.971 148.262,313.138 148.5,309.5C 149.167,302.655 149.833,295.655 150.5,288.5C 163.309,286.795 176.142,285.128 189,283.5C 190.07,283.528 190.903,283.861 191.5,284.5C 191.077,294.58 191.577,304.58 193,314.5C 194.543,316.378 196.376,317.878 198.5,319C 207.5,319.667 216.5,319.667 225.5,319C 229.896,318.27 232.73,315.77 234,311.5C 234.667,302.5 234.667,293.5 234,284.5C 233.003,282.677 231.836,281.01 230.5,279.5C 302.63,270.61 374.963,262.277 447.5,254.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fdfefe" d="M 148.5,309.5 C 148.262,313.138 146.596,315.971 143.5,318C 133.574,319.59 123.574,319.923 113.5,319C 109.403,317.078 107.07,313.912 106.5,309.5C 106.055,300.06 106.555,290.726 108,281.5C 109.731,279.383 111.898,277.883 114.5,277C 123.167,276.333 131.833,276.333 140.5,277C 143.102,277.883 145.269,279.383 147,281.5C 148.445,290.726 148.945,300.06 148.5,309.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fcfdfe" d="M 230.5,279.5 C 231.836,281.01 233.003,282.677 234,284.5C 234.667,293.5 234.667,302.5 234,311.5C 232.73,315.77 229.896,318.27 225.5,319C 216.5,319.667 207.5,319.667 198.5,319C 196.376,317.878 194.543,316.378 193,314.5C 191.577,304.58 191.077,294.58 191.5,284.5C 192.983,280.853 195.65,278.353 199.5,277C 208.167,276.333 216.833,276.333 225.5,277C 227.452,277.366 229.118,278.199 230.5,279.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fbfdfe" d="M 284.5,276.5 C 293.506,276.334 302.506,276.5 311.5,277C 314.937,278.105 317.437,280.272 319,283.5C 319.667,292.833 319.667,302.167 319,311.5C 318.31,314.196 316.81,316.363 314.5,318C 304.574,319.59 294.574,319.923 284.5,319C 280.667,317.833 278.167,315.333 277,311.5C 276.333,302.5 276.333,293.5 277,284.5C 279.028,281.308 281.528,278.641 284.5,276.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fdfefe" d="M 399.5,318.5 C 395.215,319.295 390.881,319.628 386.5,319.5C 380.824,319.666 375.157,319.499 369.5,319C 366.667,317.5 364.5,315.333 363,312.5C 362.333,302.833 362.333,293.167 363,283.5C 364.563,280.272 367.063,278.105 370.5,277C 379.167,276.333 387.833,276.333 396.5,277C 399.102,277.883 401.269,279.383 403,281.5C 404.617,291.734 404.95,302.067 404,312.5C 402.668,314.66 401.168,316.66 399.5,318.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#1e9fe3" d="M 447.5,313.5 C 447.5,332.833 447.5,352.167 447.5,371.5C 404.459,376.542 361.459,381.875 318.5,387.5C 319.998,377.114 319.831,366.78 318,356.5C 316.363,354.19 314.196,352.69 311.5,352C 302.167,351.333 292.833,351.333 283.5,352C 280.272,353.563 278.105,356.063 277,359.5C 276.333,368.167 276.333,376.833 277,385.5C 277.564,387.887 278.73,389.887 280.5,391.5C 208.167,399.5 135.833,407.5 63.5,415.5C 63.5,395.833 63.5,376.167 63.5,356.5C 78.8845,355.327 94.2179,353.66 109.5,351.5C 110.416,351.543 111.083,351.876 111.5,352.5C 110.207,354.296 108.707,355.963 107,357.5C 106.048,368.265 106.381,378.932 108,389.5C 109.731,391.617 111.898,393.117 114.5,394C 123.167,394.667 131.833,394.667 140.5,394C 143.937,392.895 146.437,390.728 148,387.5C 148.667,377.5 148.667,367.5 148,357.5C 146.039,354.865 143.539,353.031 140.5,352C 132.507,351.5 124.507,351.334 116.5,351.5C 206.491,340.76 296.491,330.094 386.5,319.5C 390.881,319.628 395.215,319.295 399.5,318.5C 415.469,316.54 431.469,314.874 447.5,313.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fdfefe" d="M 116.5,351.5 C 124.507,351.334 132.507,351.5 140.5,352C 143.539,353.031 146.039,354.865 148,357.5C 148.667,367.5 148.667,377.5 148,387.5C 146.437,390.728 143.937,392.895 140.5,394C 131.833,394.667 123.167,394.667 114.5,394C 111.898,393.117 109.731,391.617 108,389.5C 106.381,378.932 106.048,368.265 107,357.5C 108.707,355.963 110.207,354.296 111.5,352.5C 113.117,351.962 114.784,351.629 116.5,351.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fbfdfe" d="M 198.5,351.5 C 207.506,351.334 216.506,351.5 225.5,352C 229.896,352.73 232.73,355.23 234,359.5C 241.167,389.667 229.667,401.167 199.5,394C 195.23,392.73 192.73,389.896 192,385.5C 191.333,376.5 191.333,367.5 192,358.5C 193.694,355.642 195.861,353.309 198.5,351.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fbfdfe" d="M 318.5,387.5 C 317.32,390.845 314.987,393.011 311.5,394C 302.5,394.667 293.5,394.667 284.5,394C 283.016,393.338 281.683,392.504 280.5,391.5C 278.73,389.887 277.564,387.887 277,385.5C 276.333,376.833 276.333,368.167 277,359.5C 278.105,356.063 280.272,353.563 283.5,352C 292.833,351.333 302.167,351.333 311.5,352C 314.196,352.69 316.363,354.19 318,356.5C 319.831,366.78 319.998,377.114 318.5,387.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#199ae1" d="M 447.5,371.5 C 447.5,382.5 447.5,393.5 447.5,404.5C 324.677,418.554 202.01,432.887 79.5,447.5C 71.5584,445.392 66.3917,440.392 64,432.5C 63.5006,426.843 63.3339,421.176 63.5,415.5C 135.833,407.5 208.167,399.5 280.5,391.5C 281.683,392.504 283.016,393.338 284.5,394C 293.5,394.667 302.5,394.667 311.5,394C 314.987,393.011 317.32,390.845 318.5,387.5C 361.459,381.875 404.459,376.542 447.5,371.5 Z"/></g>
|
||||
<g><path style="opacity:0.999" fill="#1797e0" d="M 447.5,404.5 C 447.666,414.172 447.5,423.839 447,433.5C 444.406,440.428 439.573,444.928 432.5,447C 314.834,447.5 197.167,447.667 79.5,447.5C 202.01,432.887 324.677,418.554 447.5,404.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="none">
|
||||
<path fill="#F35325" d="M1 1h6.5v6.5H1V1z"/>
|
||||
<path fill="#81BC06" d="M8.5 1H15v6.5H8.5V1z"/>
|
||||
<path fill="#05A6F0" d="M1 8.5h6.5V15H1V8.5z"/>
|
||||
<path fill="#FFBA08" d="M8.5 8.5H15V15H8.5V8.5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 355 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.92783 8.88101H13.357V13.3088H17.7861V17.738H17.7835H22.2152V13.3088H26.6418V8.88101H31.0722V26.5949H35.5V31.0241H22.2139V26.5962H17.7861V22.1671H13.3557V26.5949L17.7861 26.5962V31.0241H4.5V26.5949H8.92783V8.88101ZM22.2139 26.5962H26.6418V22.1671H22.2152V26.5962H22.2139Z" fill="#FF7000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 392 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M32.8377 17.282C33.2127 16.25 33.3072 15.218 33.2127 14.1875C33.1197 13.1571 32.7447 12.1251 32.2752 11.1876C31.4322 9.78209 30.2127 8.6571 28.8072 8.0001C27.3072 7.34461 25.7127 7.15711 24.1197 7.53211C23.3698 6.78212 22.5253 6.12512 21.5878 5.65713C20.6503 5.18913 19.5253 5.00013 18.4948 5.00013C16.8851 4.99074 15.3125 5.48246 13.9948 6.40712C12.6824 7.34311 11.7449 8.6571 11.2754 10.1571C10.1504 10.4376 9.21289 10.9071 8.27539 11.4696C7.4324 12.1251 6.77541 12.9696 6.21291 13.8126C5.36992 15.2195 5.08792 16.8125 5.27542 18.407C5.46399 19.9968 6.11605 21.496 7.1504 22.718C6.79608 23.7086 6.66795 24.7659 6.77541 25.8124C6.86991 26.8444 7.2449 27.8749 7.7129 28.8124C8.55739 30.2194 9.77538 31.3444 11.1824 31.9999C12.6824 32.6569 14.2753 32.8444 15.8698 32.4694C16.6198 33.2194 17.4628 33.8749 18.4003 34.3444C19.3378 34.8139 20.4628 34.9999 21.4948 34.9999C23.1043 35.0097 24.6769 34.5185 25.9947 33.5944C27.3072 32.6569 28.2447 31.3444 28.7127 29.8444C29.7719 29.6432 30.7682 29.1934 31.6197 28.5319C32.4627 27.8749 33.2127 27.1249 33.6822 26.1874C34.5251 24.7819 34.8071 23.1875 34.6196 21.5945C34.4322 20 33.8697 18.5015 32.8377 17.282ZM21.5878 33.0304C20.0878 33.0304 18.9628 32.5609 17.9323 31.7179C17.9323 31.7179 18.0253 31.6234 18.1198 31.6234L24.1197 28.1554C24.2862 28.0803 24.4196 27.9469 24.4947 27.7804C24.5698 27.636 24.6021 27.4731 24.5877 27.3109V18.875L27.1197 20.375V27.3124C27.1455 28.0547 27.0215 28.7945 26.755 29.4878C26.4885 30.181 26.085 30.8134 25.5687 31.3473C25.0523 31.8811 24.4337 32.3054 23.7497 32.5949C23.0658 32.8843 22.3305 33.0314 21.5878 33.0304ZM9.49488 27.8749C8.83789 26.7499 8.55739 25.4374 8.83789 24.125C8.83789 24.125 8.93239 24.2195 9.02539 24.2195L15.0253 27.6874C15.1693 27.7638 15.3325 27.7966 15.4948 27.7819C15.6823 27.7819 15.8698 27.7819 15.9628 27.6874L23.2753 23.4695V26.3749L17.1823 29.9374C16.5506 30.3042 15.8527 30.5427 15.1287 30.6393C14.4046 30.7358 13.6686 30.6884 12.9629 30.4999C11.4629 30.1249 10.2449 29.1874 9.49488 27.8749ZM7.9004 14.8445C8.56239 13.7234 9.58826 12.8627 10.8074 12.4056V19.532C10.8074 19.718 10.8074 19.907 10.9004 20C10.9755 20.1665 11.1089 20.2998 11.2754 20.375L18.5878 24.5944L16.0573 26.0944L10.0574 22.625C9.41842 22.2639 8.85742 21.7797 8.40684 21.2004C7.95627 20.6211 7.62506 19.9582 7.4324 19.25C7.05741 17.8445 7.1504 16.157 7.9004 14.8445ZM28.6197 19.625L21.3073 15.407L23.8377 13.9071L29.8377 17.375C30.7752 17.9375 31.5252 18.6875 31.9947 19.625C32.4642 20.5625 32.7447 21.5945 32.6502 22.7195C32.5603 23.7755 32.1699 24.7837 31.5252 25.6249C30.8697 26.4694 30.0252 27.1249 28.9947 27.4999V20.375C28.9947 20.1875 28.9947 20 28.9002 19.907C28.9002 19.907 28.8072 19.718 28.6197 19.625ZM31.1502 15.875C31.1502 15.875 31.0572 15.782 30.9627 15.782L24.9627 12.3126C24.7752 12.2196 24.6822 12.2196 24.4947 12.2196C24.3072 12.2196 24.1197 12.2196 24.0252 12.3126L16.7128 16.532V13.6251L22.8073 10.0626C23.7448 9.50009 24.7752 9.31259 25.9002 9.31259C26.9322 9.31259 27.9627 9.68759 28.9002 10.3446C29.7447 11.0001 30.4947 11.8446 30.8697 12.7821C31.2447 13.7196 31.3377 14.8445 31.1502 15.875ZM15.4003 21.125L12.8699 19.625V12.5946C12.8699 11.5626 13.1503 10.4376 13.7128 9.59459C14.2753 8.6571 15.1198 8.0001 16.0573 7.53211C17.0127 7.05249 18.0956 6.88812 19.1503 7.06261C20.1823 7.15711 21.2128 7.62511 22.0573 8.2821C22.0573 8.2821 21.9628 8.3751 21.8698 8.3751L15.8698 11.8446C15.7033 11.9197 15.57 12.0531 15.4948 12.2196C15.4003 12.4071 15.4003 12.5001 15.4003 12.6876V21.125ZM16.7128 18.125L19.9948 16.25L23.2753 18.125V21.875L19.9948 23.75L16.7128 21.875V18.125Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-trash-x ">
|
||||
<path d="M3 3l18 18"></path>
|
||||
<path d="M4 7h16"></path>
|
||||
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12"></path>
|
||||
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"></path>
|
||||
<path d="M10 12l4 4m0 -4l-4 4"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 457 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
|
||||
<path d="M6.06216 1.53416C6.38434 0.663593 7.61566 0.663591 7.93784 1.53416L9.00134 4.40789C9.10263 4.68158 9.31842 4.89737 9.59211 4.99866L12.4658 6.06216C13.3364 6.38434 13.3364 7.61566 12.4658 7.93784L9.59211 9.00134C9.31842 9.10263 9.10263 9.31842 9.00134 9.59211L7.93784 12.4658C7.61566 13.3364 6.38434 13.3364 6.06216 12.4658L4.99866 9.59211C4.89737 9.31842 4.68158 9.10263 4.40789 9.00134L1.53416 7.93784C0.663593 7.61566 0.663591 6.38434 1.53416 6.06216L4.40789 4.99866C4.68158 4.89737 4.89737 4.68158 4.99866 4.40789L6.06216 1.53416Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 668 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.4673 3.06709C10.9938 1.64431 13.0062 1.6443 13.5327 3.06709L15.2708 7.76367C15.4364 8.21097 15.789 8.56364 16.2363 8.72917L20.9329 10.4673C22.3557 10.9938 22.3557 13.0062 20.9329 13.5327L16.2363 15.2708C15.789 15.4364 15.4364 15.789 15.2708 16.2363L13.5327 20.9329C13.0062 22.3557 10.9938 22.3557 10.4673 20.9329L8.72917 16.2363C8.56364 15.789 8.21097 15.4364 7.76367 15.2708L3.06709 13.5327C1.64431 13.0062 1.6443 10.9938 3.06709 10.4673L7.76367 8.72917C8.21097 8.56364 8.56364 8.21097 8.72917 7.76367L10.4673 3.06709Z" stroke="currentColor" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 663 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.4579 15.6036L26.1529 35H20.0656L6.37059 15.6036H12.4579ZM12.4524 26.3764L15.4974 30.6909L12.4551 35H6.36377L12.4524 26.3764ZM33.6365 7.15727V35H28.647V14.2236L33.6365 7.15727ZM33.6365 5L20.0656 24.2205L17.0206 19.9073L27.5451 5H33.6365Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 364 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="8" height="32" xmlns="http://www.w3.org/2000/svg" fill="none">
|
||||
<path stroke="null" id="svg_1" fill="#D6D6D6" d="m0,7.5l4.5,0c0.82843,0 1.5,0.67157 1.5,1.5c0,0.82843 -0.67157,1.5 -1.5,1.5l-4.5,0l0,-3z"/>
|
||||
<path id="svg_2" fill="#D6D6D6" d="m0,14.5l4.5,0c0.82843,0 1.5,0.6716 1.5,1.5c0,0.8284 -0.67157,1.5 -1.5,1.5l-4.5,0l0,-3z"/>
|
||||
<path id="svg_3" fill="#D6D6D6" d="m0,21.5l4.5,0c0.82843,0 1.5,0.6716 1.5,1.5c0,0.8284 -0.67157,1.5 -1.5,1.5l-4.5,0l0,-3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 478 B |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,15 @@
|
||||
.pill {
|
||||
align-items: center;
|
||||
background: var(--t-background-transparent-light);
|
||||
border-radius: var(--t-border-radius-pill);
|
||||
color: var(--t-font-color-light);
|
||||
display: inline-flex;
|
||||
font-size: var(--t-font-size-xs);
|
||||
font-style: normal;
|
||||
font-weight: var(--t-font-weight-medium);
|
||||
gap: var(--t-spacing-1);
|
||||
height: var(--t-spacing-4);
|
||||
justify-content: flex-end;
|
||||
line-height: var(--t-text-line-height-lg);
|
||||
padding: 0 var(--t-spacing-2);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare const classNames: {
|
||||
readonly pill: 'pill';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,19 @@
|
||||
import { type IconComponent } from '@ui/display';
|
||||
import { clsx } from 'clsx';
|
||||
|
||||
import styles from './Pill.module.scss';
|
||||
|
||||
type PillProps = {
|
||||
className?: string;
|
||||
label?: string;
|
||||
Icon?: IconComponent;
|
||||
};
|
||||
|
||||
export const Pill = ({ className, label, Icon }: PillProps) => {
|
||||
return (
|
||||
<span className={clsx(styles.pill, className)}>
|
||||
{Icon && <Icon size={12} />}
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
|
||||
import { Pill } from '@ui/components/Pill/Pill';
|
||||
import { ComponentDecorator } from '../../../testing/decorators/ComponentDecorator';
|
||||
|
||||
const meta: Meta<typeof Pill> = {
|
||||
title: 'UI/Display/Pill',
|
||||
component: Pill,
|
||||
decorators: [ComponentDecorator],
|
||||
args: {
|
||||
label: 'Soon',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Pill>;
|
||||
|
||||
export const Default: Story = {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
parameters: { a11y: { test: 'todo' } },
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
.iconWithBackgroundContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 4px;
|
||||
background-color: var(
|
||||
--avatar-or-icon-background,
|
||||
var(--t-background-inverted-secondary)
|
||||
);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
cursor: inherit;
|
||||
display: flex;
|
||||
|
||||
&[data-clickable] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
declare const classNames: {
|
||||
readonly iconWithBackgroundContainer: 'iconWithBackgroundContainer';
|
||||
readonly wrapper: 'wrapper';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,91 @@
|
||||
import { Avatar } from '@ui/display/avatar/components/Avatar';
|
||||
import { type AvatarType } from '@ui/display/avatar/types/AvatarType';
|
||||
import { type IconComponent } from '@ui/display/icon/types/IconComponent';
|
||||
import { ThemeContext } from '@ui/theme-constants';
|
||||
import { type Nullable } from '@ui/utilities';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from '@ui/utilities/utils/isDefined';
|
||||
|
||||
import styles from './AvatarOrIcon.module.scss';
|
||||
|
||||
export type AvatarOrIconProps = {
|
||||
placeholder?: string;
|
||||
avatarUrl?: string;
|
||||
avatarType?: Nullable<AvatarType>;
|
||||
Icon?: IconComponent;
|
||||
IconColor?: string;
|
||||
IconBackgroundColor?: string;
|
||||
isIconInverted?: boolean;
|
||||
placeholderColorSeed?: string;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export const AvatarOrIcon = ({
|
||||
Icon,
|
||||
placeholderColorSeed,
|
||||
avatarType,
|
||||
avatarUrl,
|
||||
placeholder,
|
||||
isIconInverted = false,
|
||||
IconColor,
|
||||
IconBackgroundColor,
|
||||
onClick,
|
||||
}: AvatarOrIconProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
if (!isDefined(Icon)) {
|
||||
return (
|
||||
<Avatar
|
||||
avatarUrl={avatarUrl}
|
||||
placeholderColorSeed={placeholderColorSeed}
|
||||
placeholder={placeholder}
|
||||
size="sm"
|
||||
type={avatarType}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const isClickable = isDefined(onClick);
|
||||
|
||||
if (isIconInverted || isDefined(IconBackgroundColor)) {
|
||||
return (
|
||||
<div
|
||||
className={styles.wrapper}
|
||||
data-clickable={isClickable || undefined}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div
|
||||
className={styles.iconWithBackgroundContainer}
|
||||
style={
|
||||
isDefined(IconBackgroundColor)
|
||||
? ({
|
||||
'--avatar-or-icon-background': IconBackgroundColor,
|
||||
} as React.CSSProperties)
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
color={theme.font.color.inverted}
|
||||
size={theme.icon.size.sm}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.wrapper}
|
||||
data-clickable={isClickable || undefined}
|
||||
onClick={onClick}
|
||||
>
|
||||
<Icon
|
||||
size={theme.icon.size.sm}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
color={IconColor || 'currentColor'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { IconBuildingSkyscraper, IconUser } from '@ui/display';
|
||||
import { ComponentDecorator, JotaiRootDecorator } from '@ui/testing';
|
||||
import { AvatarOrIcon } from '../AvatarOrIcon';
|
||||
|
||||
const meta: Meta<typeof AvatarOrIcon> = {
|
||||
title: 'UI/Components/AvatarOrIcon',
|
||||
component: AvatarOrIcon,
|
||||
decorators: [ComponentDecorator, JotaiRootDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof AvatarOrIcon>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
placeholder: 'JD',
|
||||
placeholderColorSeed: 'John Doe',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithAvatar: Story = {
|
||||
args: {
|
||||
avatarUrl: 'https://i.pravatar.cc/300',
|
||||
placeholder: 'JD',
|
||||
placeholderColorSeed: 'John Doe',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithIcon: Story = {
|
||||
args: {
|
||||
Icon: IconUser,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithIconBackground: Story = {
|
||||
args: {
|
||||
Icon: IconBuildingSkyscraper,
|
||||
isIconInverted: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithInvertedIcon: Story = {
|
||||
args: {
|
||||
Icon: IconUser,
|
||||
isIconInverted: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const Clickable: Story = {
|
||||
args: {
|
||||
placeholder: 'JD',
|
||||
placeholderColorSeed: 'John Doe',
|
||||
onClick: () => alert('AvatarOrIcon clicked'),
|
||||
},
|
||||
};
|
||||
|
||||
export const ClickableIcon: Story = {
|
||||
args: {
|
||||
Icon: IconBuildingSkyscraper,
|
||||
isIconInverted: true,
|
||||
onClick: () => alert('Icon AvatarOrIcon clicked'),
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,110 @@
|
||||
.chip {
|
||||
--chip-horizontal-padding: var(--t-spacing-1);
|
||||
--chip-vertical-padding: var(--t-spacing-1);
|
||||
|
||||
// Height and max-width are sized against the content box.
|
||||
box-sizing: content-box;
|
||||
text-decoration: none;
|
||||
align-items: center;
|
||||
cursor: inherit;
|
||||
display: inline-flex;
|
||||
justify-content: flex-start;
|
||||
gap: var(--t-spacing-1);
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
padding: var(--chip-vertical-padding) var(--chip-horizontal-padding);
|
||||
user-select: none;
|
||||
font-weight: inherit;
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
border-radius: var(--t-border-radius-sm);
|
||||
|
||||
& > svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sizeLarge {
|
||||
height: var(--t-spacing-4);
|
||||
}
|
||||
|
||||
.sizeSmall {
|
||||
height: var(--t-spacing-3);
|
||||
}
|
||||
|
||||
.accentTextPrimary {
|
||||
color: var(--t-font-color-primary);
|
||||
}
|
||||
|
||||
.accentTextSecondary {
|
||||
color: var(--t-font-color-secondary);
|
||||
}
|
||||
|
||||
// Disabled color wins over accent colors, matching the Linaria ternary order.
|
||||
.disabled {
|
||||
color: var(--t-font-color-light);
|
||||
}
|
||||
|
||||
.fontMedium {
|
||||
font-weight: var(--t-font-weight-medium);
|
||||
}
|
||||
|
||||
.cursorPointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cursorNotAllowed {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.backgroundHighlighted {
|
||||
background-color: var(--t-background-transparent-light);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--t-background-transparent-medium);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--t-background-transparent-strong);
|
||||
}
|
||||
}
|
||||
|
||||
.backgroundStatic {
|
||||
background-color: var(--t-background-transparent-light);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--t-background-transparent-light);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--t-background-transparent-light);
|
||||
}
|
||||
}
|
||||
|
||||
// Applied only when variant is regular, clickable and not disabled.
|
||||
.interactiveRegular {
|
||||
&:hover {
|
||||
background-color: var(--t-background-transparent-light);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--t-background-transparent-medium);
|
||||
}
|
||||
}
|
||||
|
||||
.hasMaxWidth {
|
||||
max-width: calc(var(--chip-max-width) - 2 * var(--chip-horizontal-padding));
|
||||
}
|
||||
|
||||
.paddingLeftNone {
|
||||
padding-left: var(--t-spacing-0);
|
||||
}
|
||||
|
||||
.emptyLabel {
|
||||
color: var(--t-font-color-tertiary);
|
||||
}
|
||||
|
||||
.rightComponentDivider {
|
||||
align-self: stretch;
|
||||
border-left: 1px solid var(--t-border-color-light);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
declare const classNames: {
|
||||
readonly chip: 'chip';
|
||||
readonly sizeLarge: 'sizeLarge';
|
||||
readonly sizeSmall: 'sizeSmall';
|
||||
readonly accentTextPrimary: 'accentTextPrimary';
|
||||
readonly accentTextSecondary: 'accentTextSecondary';
|
||||
readonly disabled: 'disabled';
|
||||
readonly fontMedium: 'fontMedium';
|
||||
readonly cursorPointer: 'cursorPointer';
|
||||
readonly cursorNotAllowed: 'cursorNotAllowed';
|
||||
readonly backgroundHighlighted: 'backgroundHighlighted';
|
||||
readonly backgroundStatic: 'backgroundStatic';
|
||||
readonly interactiveRegular: 'interactiveRegular';
|
||||
readonly hasMaxWidth: 'hasMaxWidth';
|
||||
readonly paddingLeftNone: 'paddingLeftNone';
|
||||
readonly emptyLabel: 'emptyLabel';
|
||||
readonly rightComponentDivider: 'rightComponentDivider';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,149 @@
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { OverflowingTextWithTooltip } from '@ui/display/tooltip/OverflowingTextWithTooltip';
|
||||
import { clsx } from 'clsx';
|
||||
import { isDefined } from '@ui/utilities/utils/isDefined';
|
||||
|
||||
import styles from './Chip.module.scss';
|
||||
|
||||
export enum ChipSize {
|
||||
Large = 'large',
|
||||
Small = 'small',
|
||||
}
|
||||
|
||||
export enum ChipAccent {
|
||||
TextPrimary = 'text-primary',
|
||||
TextSecondary = 'text-secondary',
|
||||
}
|
||||
|
||||
export enum ChipVariant {
|
||||
Highlighted = 'highlighted',
|
||||
Regular = 'regular',
|
||||
Transparent = 'transparent',
|
||||
Rounded = 'rounded',
|
||||
Static = 'static',
|
||||
}
|
||||
|
||||
export type ChipProps = {
|
||||
size?: ChipSize;
|
||||
disabled?: boolean;
|
||||
clickable?: boolean;
|
||||
label: string;
|
||||
tooltipLabel?: string;
|
||||
alwaysShowTooltip?: boolean;
|
||||
isLabelHidden?: boolean;
|
||||
isBold?: boolean;
|
||||
maxWidth?: number;
|
||||
variant?: ChipVariant;
|
||||
accent?: ChipAccent;
|
||||
leftComponent?: ReactNode | null;
|
||||
rightComponent?: (() => ReactNode) | ReactNode | null;
|
||||
rightComponentDivider?: boolean;
|
||||
className?: string;
|
||||
forceEmptyText?: boolean;
|
||||
emptyLabel?: string;
|
||||
};
|
||||
|
||||
const renderRightComponent = (
|
||||
rightComponent: (() => ReactNode) | ReactNode | null,
|
||||
rightComponentDivider?: boolean,
|
||||
) => {
|
||||
if (!rightComponent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rendered =
|
||||
typeof rightComponent === 'function' ? rightComponent() : rightComponent;
|
||||
|
||||
if (rightComponentDivider === true) {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.rightComponentDivider} />
|
||||
{rendered}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return rendered;
|
||||
};
|
||||
|
||||
export const Chip = ({
|
||||
size = ChipSize.Small,
|
||||
label,
|
||||
tooltipLabel,
|
||||
alwaysShowTooltip = false,
|
||||
isLabelHidden = false,
|
||||
isBold = false,
|
||||
disabled = false,
|
||||
clickable = true,
|
||||
variant = ChipVariant.Regular,
|
||||
leftComponent = null,
|
||||
rightComponent = null,
|
||||
rightComponentDivider = false,
|
||||
accent = ChipAccent.TextPrimary,
|
||||
className,
|
||||
maxWidth,
|
||||
forceEmptyText = false,
|
||||
emptyLabel = 'Untitled',
|
||||
}: ChipProps) => {
|
||||
// Cursor precedence mirrors the Linaria ternary:
|
||||
// transparent > clickable > disabled > inherit.
|
||||
const cursorClass =
|
||||
variant === ChipVariant.Transparent
|
||||
? undefined
|
||||
: clickable
|
||||
? styles.cursorPointer
|
||||
: disabled
|
||||
? styles.cursorNotAllowed
|
||||
: undefined;
|
||||
|
||||
const backgroundClass =
|
||||
variant === ChipVariant.Highlighted
|
||||
? styles.backgroundHighlighted
|
||||
: variant === ChipVariant.Static
|
||||
? styles.backgroundStatic
|
||||
: variant === ChipVariant.Regular && !disabled && clickable
|
||||
? styles.interactiveRegular
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="chip"
|
||||
className={clsx(
|
||||
styles.chip,
|
||||
size === ChipSize.Large ? styles.sizeLarge : styles.sizeSmall,
|
||||
accent === ChipAccent.TextPrimary
|
||||
? styles.accentTextPrimary
|
||||
: styles.accentTextSecondary,
|
||||
disabled && styles.disabled,
|
||||
(isBold || accent === ChipAccent.TextSecondary) && styles.fontMedium,
|
||||
cursorClass,
|
||||
backgroundClass,
|
||||
maxWidth ? styles.hasMaxWidth : undefined,
|
||||
variant === ChipVariant.Transparent && styles.paddingLeftNone,
|
||||
className,
|
||||
)}
|
||||
style={
|
||||
maxWidth
|
||||
? ({ '--chip-max-width': `${maxWidth}px` } as React.CSSProperties)
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{leftComponent}
|
||||
{!isLabelHidden && isDefined(label) && isNonEmptyString(label) ? (
|
||||
<OverflowingTextWithTooltip
|
||||
size={size}
|
||||
text={label}
|
||||
tooltipContent={tooltipLabel}
|
||||
alwaysShowTooltip={alwaysShowTooltip}
|
||||
/>
|
||||
) : !forceEmptyText && !isLabelHidden ? (
|
||||
<div className={styles.emptyLabel}>{emptyLabel}</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{renderRightComponent(rightComponent, rightComponentDivider)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
.linkContainer {
|
||||
display: inline-flex;
|
||||
min-width: 0;
|
||||
vertical-align: middle;
|
||||
|
||||
& > a {
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare const classNames: {
|
||||
readonly linkContainer: 'linkContainer';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,82 @@
|
||||
import {
|
||||
Chip,
|
||||
ChipAccent,
|
||||
type ChipProps,
|
||||
ChipSize,
|
||||
ChipVariant,
|
||||
} from '@ui/components/chip/Chip';
|
||||
import { LINK_CHIP_CLICK_OUTSIDE_ID } from '@ui/components/chip/constants/LinkChipClickOutsideId';
|
||||
import { type TriggerEventType, useMouseDownNavigation } from '@ui/utilities';
|
||||
import { type MouseEvent } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import styles from './LinkChip.module.scss';
|
||||
|
||||
export type LinkChipProps = Omit<
|
||||
ChipProps,
|
||||
'onClick' | 'disabled' | 'clickable'
|
||||
> & {
|
||||
to: string;
|
||||
onClick?: (event: MouseEvent<HTMLElement>) => void;
|
||||
onMouseDown?: (event: MouseEvent<HTMLElement>) => void;
|
||||
triggerEvent?: TriggerEventType;
|
||||
target?: '_blank' | '_self';
|
||||
};
|
||||
|
||||
export const LinkChip = ({
|
||||
to,
|
||||
size = ChipSize.Small,
|
||||
label,
|
||||
isLabelHidden = false,
|
||||
isBold = false,
|
||||
variant = ChipVariant.Regular,
|
||||
leftComponent = null,
|
||||
rightComponent = null,
|
||||
rightComponentDivider = false,
|
||||
accent = ChipAccent.TextPrimary,
|
||||
className,
|
||||
maxWidth,
|
||||
onClick,
|
||||
triggerEvent,
|
||||
target,
|
||||
emptyLabel,
|
||||
}: LinkChipProps) => {
|
||||
const { onClick: onClickHandler, onMouseDown: onMouseDownHandler } =
|
||||
useMouseDownNavigation({
|
||||
to: to,
|
||||
onClick: onClick,
|
||||
triggerEvent,
|
||||
});
|
||||
|
||||
return (
|
||||
<span className={styles.linkContainer}>
|
||||
<Link
|
||||
to={to}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onClickHandler(event);
|
||||
}}
|
||||
onMouseDown={onMouseDownHandler}
|
||||
data-click-outside-id={LINK_CHIP_CLICK_OUTSIDE_ID}
|
||||
target={target}
|
||||
rel={target === '_blank' ? 'noopener noreferrer' : undefined}
|
||||
>
|
||||
<Chip
|
||||
size={size}
|
||||
label={label}
|
||||
isLabelHidden={isLabelHidden}
|
||||
isBold={isBold}
|
||||
clickable={true}
|
||||
variant={variant}
|
||||
leftComponent={leftComponent}
|
||||
rightComponent={rightComponent}
|
||||
rightComponentDivider={rightComponentDivider}
|
||||
accent={accent}
|
||||
className={className}
|
||||
maxWidth={maxWidth}
|
||||
emptyLabel={emptyLabel}
|
||||
/>
|
||||
</Link>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,204 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { IconUser, IconX } from '@ui/display';
|
||||
import { Avatar } from '@ui/display/avatar/components/Avatar';
|
||||
|
||||
import {
|
||||
CatalogDecorator,
|
||||
type CatalogStory,
|
||||
ComponentDecorator,
|
||||
} from '@ui/testing';
|
||||
|
||||
import { Chip, ChipAccent, ChipSize, ChipVariant } from '../Chip';
|
||||
|
||||
const meta: Meta<typeof Chip> = {
|
||||
title: 'UI/Components/Chip/Chip',
|
||||
component: Chip,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Chip>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: 'Chip test',
|
||||
size: ChipSize.Small,
|
||||
variant: ChipVariant.Highlighted,
|
||||
accent: ChipAccent.TextPrimary,
|
||||
disabled: false,
|
||||
clickable: true,
|
||||
maxWidth: 200,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const WithLeftAvatar: Story = {
|
||||
args: {
|
||||
label: 'John Doe',
|
||||
clickable: true,
|
||||
variant: ChipVariant.Regular,
|
||||
leftComponent: (
|
||||
<Avatar
|
||||
placeholder="JD"
|
||||
placeholderColorSeed="John Doe"
|
||||
size="sm"
|
||||
type="rounded"
|
||||
/>
|
||||
),
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const WithLeftIcon: Story = {
|
||||
args: {
|
||||
label: 'Company',
|
||||
clickable: true,
|
||||
variant: ChipVariant.Regular,
|
||||
leftComponent: <IconUser size={14} />,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const EmptyLabel: Story = {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
parameters: { a11y: { test: 'todo' } },
|
||||
args: {
|
||||
label: '',
|
||||
clickable: true,
|
||||
variant: ChipVariant.Regular,
|
||||
leftComponent: (
|
||||
<Avatar placeholder="?" placeholderColorSeed="empty" size="sm" />
|
||||
),
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof Chip> = {
|
||||
args: { clickable: true, label: 'Hello' },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
className: { control: false },
|
||||
rightComponent: { control: false },
|
||||
leftComponent: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
pseudo: { hover: ['.hover'], active: ['.active'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'variants',
|
||||
values: Object.values(ChipVariant),
|
||||
props: (variant: ChipVariant) => ({ variant }),
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: Object.values(ChipSize),
|
||||
props: (size: ChipSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: ['default', 'hover', 'active', 'disabled'],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'hover':
|
||||
case 'active':
|
||||
return { className: state };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: Object.values(ChipAccent),
|
||||
props: (accent: ChipAccent) => ({ accent }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const WithAvatarCatalog: CatalogStory<Story, typeof Chip> = {
|
||||
args: {
|
||||
clickable: true,
|
||||
label: 'John Doe',
|
||||
leftComponent: (
|
||||
<Avatar
|
||||
placeholder="JD"
|
||||
placeholderColorSeed="John Doe"
|
||||
size="sm"
|
||||
type="rounded"
|
||||
/>
|
||||
),
|
||||
},
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
disabled: { control: false },
|
||||
className: { control: false },
|
||||
rightComponent: { control: false },
|
||||
leftComponent: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
pseudo: { hover: ['.hover'], active: ['.active'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'variants',
|
||||
values: Object.values(ChipVariant),
|
||||
props: (variant: ChipVariant) => ({ variant }),
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: Object.values(ChipSize),
|
||||
props: (size: ChipSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: ['default', 'hover', 'active', 'disabled'],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'hover':
|
||||
case 'active':
|
||||
return { className: state };
|
||||
case 'disabled':
|
||||
return { disabled: true };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const WithRightComponentDivider: Story = {
|
||||
args: {
|
||||
label: 'document.pdf',
|
||||
variant: ChipVariant.Static,
|
||||
clickable: false,
|
||||
leftComponent: (
|
||||
<Avatar
|
||||
placeholder="D"
|
||||
placeholderColorSeed="document"
|
||||
size="sm"
|
||||
type="squared"
|
||||
/>
|
||||
),
|
||||
rightComponent: <IconX size={14} />,
|
||||
rightComponentDivider: true,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
@@ -0,0 +1,190 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { IconUser, IconX } from '@ui/display';
|
||||
import { Avatar } from '@ui/display/avatar/components/Avatar';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
type CatalogStory,
|
||||
ComponentDecorator,
|
||||
} from '@ui/testing';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
import { ChipAccent, ChipSize, ChipVariant } from '../Chip';
|
||||
import { LinkChip } from '../LinkChip';
|
||||
|
||||
const meta: Meta<typeof LinkChip> = {
|
||||
title: 'UI/Components/Chip/LinkChip',
|
||||
component: LinkChip,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof LinkChip>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: 'Link Chip',
|
||||
to: '/example',
|
||||
size: ChipSize.Small,
|
||||
variant: ChipVariant.Regular,
|
||||
accent: ChipAccent.TextPrimary,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const WithAvatar: Story = {
|
||||
args: {
|
||||
label: 'John Doe',
|
||||
to: '/users/john-doe',
|
||||
variant: ChipVariant.Regular,
|
||||
leftComponent: (
|
||||
<Avatar
|
||||
placeholder="JD"
|
||||
placeholderColorSeed="John Doe"
|
||||
size="sm"
|
||||
type="rounded"
|
||||
/>
|
||||
),
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const WithIcon: Story = {
|
||||
args: {
|
||||
label: 'Company',
|
||||
to: '/companies/1',
|
||||
variant: ChipVariant.Regular,
|
||||
leftComponent: <IconUser size={14} />,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof LinkChip> = {
|
||||
args: { label: 'Link Chip', to: '/example' },
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
className: { control: false },
|
||||
rightComponent: { control: false },
|
||||
leftComponent: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
pseudo: { hover: ['.hover'], active: ['.active'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'variants',
|
||||
values: Object.values(ChipVariant),
|
||||
props: (variant: ChipVariant) => ({ variant }),
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: Object.values(ChipSize),
|
||||
props: (size: ChipSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: ['default', 'hover', 'active'],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'hover':
|
||||
case 'active':
|
||||
return { className: state };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'accents',
|
||||
values: Object.values(ChipAccent),
|
||||
props: (accent: ChipAccent) => ({ accent }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const WithAvatarCatalog: CatalogStory<Story, typeof LinkChip> = {
|
||||
args: {
|
||||
label: 'John Doe',
|
||||
to: '/users/john-doe',
|
||||
leftComponent: (
|
||||
<Avatar
|
||||
placeholder="JD"
|
||||
placeholderColorSeed="John Doe"
|
||||
size="sm"
|
||||
type="rounded"
|
||||
/>
|
||||
),
|
||||
},
|
||||
argTypes: {
|
||||
size: { control: false },
|
||||
variant: { control: false },
|
||||
accent: { control: false },
|
||||
className: { control: false },
|
||||
rightComponent: { control: false },
|
||||
leftComponent: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
pseudo: { hover: ['.hover'], active: ['.active'] },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'variants',
|
||||
values: Object.values(ChipVariant),
|
||||
props: (variant: ChipVariant) => ({ variant }),
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: Object.values(ChipSize),
|
||||
props: (size: ChipSize) => ({ size }),
|
||||
},
|
||||
{
|
||||
name: 'states',
|
||||
values: ['default', 'hover', 'active'],
|
||||
props: (state: string) => {
|
||||
switch (state) {
|
||||
case 'hover':
|
||||
case 'active':
|
||||
return { className: state };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const WithRightComponentDivider: Story = {
|
||||
args: {
|
||||
label: 'document.pdf',
|
||||
to: '/files/document.pdf',
|
||||
variant: ChipVariant.Static,
|
||||
leftComponent: (
|
||||
<Avatar
|
||||
placeholder="D"
|
||||
placeholderColorSeed="document"
|
||||
size="sm"
|
||||
type="squared"
|
||||
/>
|
||||
),
|
||||
rightComponent: <IconX size={14} />,
|
||||
rightComponentDivider: true,
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export const LINK_CHIP_CLICK_OUTSIDE_ID = 'link-chip-click-outside-id';
|
||||
@@ -7,4 +7,13 @@
|
||||
* |___/
|
||||
*/
|
||||
|
||||
export {};
|
||||
export type { AvatarOrIconProps } from './avatar-or-icon/AvatarOrIcon';
|
||||
export { AvatarOrIcon } from './avatar-or-icon/AvatarOrIcon';
|
||||
export type { ChipProps } from './chip/Chip';
|
||||
export { ChipSize, ChipAccent, ChipVariant, Chip } from './chip/Chip';
|
||||
export { LINK_CHIP_CLICK_OUTSIDE_ID } from './chip/constants/LinkChipClickOutsideId';
|
||||
export type { LinkChipProps } from './chip/LinkChip';
|
||||
export { LinkChip } from './chip/LinkChip';
|
||||
export { Pill } from './Pill/Pill';
|
||||
export type { TagColor } from './tag/Tag';
|
||||
export { Tag } from './tag/Tag';
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
.tag {
|
||||
box-sizing: content-box;
|
||||
align-items: center;
|
||||
background: var(--tag-background);
|
||||
border-radius: var(--t-border-radius-sm);
|
||||
color: var(--tag-text);
|
||||
display: inline-flex;
|
||||
font-size: var(--t-font-size-md);
|
||||
font-style: normal;
|
||||
font-weight: var(--t-font-weight-regular);
|
||||
height: var(--t-spacing-5);
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0 var(--t-spacing-2);
|
||||
border: none;
|
||||
gap: var(--t-spacing-1);
|
||||
// 'none' is not a valid min-width value; kept for byte-equivalence with the
|
||||
// deprecated Linaria styles where the declaration was equally inert.
|
||||
min-width: none;
|
||||
}
|
||||
|
||||
.weightMedium {
|
||||
font-weight: var(--t-font-weight-medium);
|
||||
}
|
||||
|
||||
.variantOutline {
|
||||
border: 1px dashed var(--t-border-color-strong);
|
||||
}
|
||||
|
||||
.variantBorder {
|
||||
border: 1px solid var(--t-border-color-strong);
|
||||
}
|
||||
|
||||
.preventShrink {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.preventPadding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nonShrinkableText {
|
||||
white-space: nowrap;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.iconContainer {
|
||||
display: flex;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
declare const classNames: {
|
||||
readonly tag: 'tag';
|
||||
readonly weightMedium: 'weightMedium';
|
||||
readonly variantOutline: 'variantOutline';
|
||||
readonly variantBorder: 'variantBorder';
|
||||
readonly preventShrink: 'preventShrink';
|
||||
readonly preventPadding: 'preventPadding';
|
||||
readonly content: 'content';
|
||||
readonly nonShrinkableText: 'nonShrinkableText';
|
||||
readonly iconContainer: 'iconContainer';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,87 @@
|
||||
import { type IconComponent } from '@ui/display/icon/types/IconComponent';
|
||||
import { OverflowingTextWithTooltip } from '@ui/display/tooltip/OverflowingTextWithTooltip';
|
||||
import { type ThemeColor } from '@ui/theme';
|
||||
import { ThemeContext, themeCssVariables } from '@ui/theme-constants';
|
||||
import { clsx } from 'clsx';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from '@ui/utilities/utils/isDefined';
|
||||
|
||||
import styles from './Tag.module.scss';
|
||||
|
||||
type TagWeight = 'regular' | 'medium';
|
||||
type TagVariant = 'solid' | 'outline' | 'border';
|
||||
export type TagColor = ThemeColor | 'transparent';
|
||||
|
||||
type TagProps = {
|
||||
className?: string;
|
||||
color: TagColor;
|
||||
text: string;
|
||||
Icon?: IconComponent;
|
||||
onClick?: () => void;
|
||||
weight?: TagWeight;
|
||||
variant?: TagVariant;
|
||||
preventShrink?: boolean;
|
||||
preventPadding?: boolean;
|
||||
};
|
||||
|
||||
export const Tag = ({
|
||||
className,
|
||||
color,
|
||||
text,
|
||||
Icon,
|
||||
onClick,
|
||||
weight = 'regular',
|
||||
variant = 'solid',
|
||||
preventShrink,
|
||||
preventPadding,
|
||||
}: TagProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const tagBackground =
|
||||
color === 'transparent'
|
||||
? 'transparent'
|
||||
: (themeCssVariables.tag.background[color] ??
|
||||
themeCssVariables.tag.background.gray);
|
||||
|
||||
const tagText =
|
||||
color === 'transparent'
|
||||
? themeCssVariables.font.color.secondary
|
||||
: (themeCssVariables.tag.text[color] ??
|
||||
themeCssVariables.font.color.secondary);
|
||||
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
styles.tag,
|
||||
weight === 'medium' && styles.weightMedium,
|
||||
variant === 'outline' && styles.variantOutline,
|
||||
variant === 'border' && styles.variantBorder,
|
||||
preventShrink && styles.preventShrink,
|
||||
preventPadding && styles.preventPadding,
|
||||
className,
|
||||
)}
|
||||
onClick={onClick}
|
||||
style={
|
||||
{
|
||||
'--tag-background': tagBackground,
|
||||
'--tag-text': tagText,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{isDefined(Icon) ? (
|
||||
<div className={styles.iconContainer}>
|
||||
<Icon size={theme.icon.size.sm} stroke={theme.icon.stroke.sm} />
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{preventShrink ? (
|
||||
<span className={styles.nonShrinkableText}>{text}</span>
|
||||
) : (
|
||||
<span className={styles.content}>
|
||||
<OverflowingTextWithTooltip text={text} />
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,113 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { expect, fn, userEvent, within } from 'storybook/test';
|
||||
|
||||
import { IconUser } from '@ui/display/icon/components/TablerIcons';
|
||||
import {
|
||||
CatalogDecorator,
|
||||
type CatalogStory,
|
||||
ComponentDecorator,
|
||||
} from '@ui/testing';
|
||||
import { type ThemeColor, MAIN_COLOR_NAMES } from '@ui/theme';
|
||||
|
||||
import { Tag } from '../Tag';
|
||||
|
||||
const meta: Meta<typeof Tag> = {
|
||||
title: 'UI/Display/Tag/Tag',
|
||||
component: Tag,
|
||||
args: {
|
||||
text: 'Urgent',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Tag>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
color: 'red',
|
||||
onClick: fn(),
|
||||
},
|
||||
decorators: [ComponentDecorator],
|
||||
play: async ({ canvasElement, args }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const tag = canvas.getByText('Urgent');
|
||||
|
||||
await userEvent.click(tag);
|
||||
await expect(args.onClick).toHaveBeenCalled();
|
||||
},
|
||||
};
|
||||
|
||||
export const WithLongText: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
args: {
|
||||
color: 'green',
|
||||
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
container: { width: 100 },
|
||||
},
|
||||
};
|
||||
|
||||
export const WithIcon: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
args: {
|
||||
color: 'green',
|
||||
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
Icon: IconUser,
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
container: { width: 100 },
|
||||
},
|
||||
};
|
||||
|
||||
export const DontShrink: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
args: {
|
||||
color: 'green',
|
||||
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
preventShrink: true,
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
container: { width: 100 },
|
||||
},
|
||||
};
|
||||
|
||||
export const Catalog: CatalogStory<Story, typeof Tag> = {
|
||||
argTypes: {
|
||||
color: { control: false },
|
||||
},
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'colors',
|
||||
values: MAIN_COLOR_NAMES,
|
||||
props: (color: ThemeColor) => ({ color }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
};
|
||||
|
||||
export const EmptyTag: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
args: {
|
||||
color: 'transparent',
|
||||
text: 'No Value',
|
||||
variant: 'outline',
|
||||
weight: 'medium',
|
||||
},
|
||||
parameters: {
|
||||
container: { width: 'auto' },
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
// Size values mirror AVATAR_PROPERTIES_BY_SIZE (constants/AvatarPropertiesBySize.ts)
|
||||
.root {
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
border-radius: 2px;
|
||||
border: var(--avatar-border, none);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
color: var(--avatar-color);
|
||||
background: var(--avatar-background);
|
||||
|
||||
&[data-type='icon'] {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&[data-type='rounded'] {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&[data-clickable]:hover {
|
||||
box-shadow: 0 0 0 4px var(--t-background-transparent-light);
|
||||
}
|
||||
}
|
||||
|
||||
.xl {
|
||||
font-size: 16px;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.lg {
|
||||
font-size: 13px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.md {
|
||||
font-size: 12px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.sm {
|
||||
font-size: 10px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.xs {
|
||||
font-size: 8px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.image {
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.placeholderChar {
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
declare const classNames: {
|
||||
readonly root: 'root';
|
||||
readonly xl: 'xl';
|
||||
readonly lg: 'lg';
|
||||
readonly md: 'md';
|
||||
readonly sm: 'sm';
|
||||
readonly xs: 'xs';
|
||||
readonly image: 'image';
|
||||
readonly placeholderChar: 'placeholderChar';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,146 @@
|
||||
import { isNonEmptyString, isNull, isUndefined } from '@sniptt/guards';
|
||||
import { clsx } from 'clsx';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { invalidAvatarUrlsAtomV2 } from '@ui/display/avatar/components/states/invalidAvatarUrlsAtomV2';
|
||||
import { type AvatarSize } from '@ui/display/avatar/types/AvatarSize';
|
||||
import { type AvatarType } from '@ui/display/avatar/types/AvatarType';
|
||||
import { type IconComponent } from '@ui/display/icon/types/IconComponent';
|
||||
import { ThemeContext } from '@ui/theme-constants';
|
||||
import { stringToThemeColorP3String } from '@ui/utilities';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '@ui/utilities/config';
|
||||
import { type Nullable } from '@ui/utilities/types/Nullable';
|
||||
import { getImageAbsoluteURI } from '@ui/utilities/utils/getImageAbsoluteURI';
|
||||
|
||||
import styles from './Avatar.module.scss';
|
||||
|
||||
export type AvatarProps = {
|
||||
avatarUrl?: string | null;
|
||||
className?: string;
|
||||
size?: AvatarSize;
|
||||
placeholder: string | undefined;
|
||||
placeholderColorSeed?: string;
|
||||
Icon?: IconComponent;
|
||||
iconColor?: string;
|
||||
type?: Nullable<AvatarType>;
|
||||
color?: string;
|
||||
backgroundColor?: string;
|
||||
borderColor?: string;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export const Avatar = ({
|
||||
avatarUrl,
|
||||
className,
|
||||
size = 'md',
|
||||
placeholder,
|
||||
placeholderColorSeed = placeholder,
|
||||
Icon,
|
||||
iconColor,
|
||||
onClick,
|
||||
type = 'squared',
|
||||
color,
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
}: AvatarProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const [invalidAvatarUrls, setInvalidAvatarUrls] = useAtom(
|
||||
invalidAvatarUrlsAtomV2,
|
||||
);
|
||||
|
||||
const avatarImageURI = isNonEmptyString(avatarUrl)
|
||||
? getImageAbsoluteURI({
|
||||
imageUrl: avatarUrl,
|
||||
baseUrl: REACT_APP_SERVER_BASE_URL,
|
||||
})
|
||||
: null;
|
||||
|
||||
const placeholderFirstChar = placeholder?.trim()?.charAt(0);
|
||||
const isPlaceholderFirstCharEmpty =
|
||||
!placeholderFirstChar || placeholderFirstChar === '';
|
||||
const placeholderChar = placeholderFirstChar?.toUpperCase() || '-';
|
||||
|
||||
const showPlaceholder =
|
||||
isNull(avatarImageURI) || invalidAvatarUrls.includes(avatarImageURI);
|
||||
|
||||
const handleImageError = () => {
|
||||
if (isNonEmptyString(avatarImageURI)) {
|
||||
setInvalidAvatarUrls((prev) => [...prev, avatarImageURI]);
|
||||
}
|
||||
};
|
||||
|
||||
const fixedColor = isPlaceholderFirstCharEmpty
|
||||
? theme.font.color.tertiary
|
||||
: (color ??
|
||||
stringToThemeColorP3String({
|
||||
string: placeholderColorSeed ?? '',
|
||||
variant: 12,
|
||||
theme,
|
||||
}));
|
||||
const fixedBackgroundColor = isPlaceholderFirstCharEmpty
|
||||
? theme.background.transparent.light
|
||||
: (backgroundColor ??
|
||||
stringToThemeColorP3String({
|
||||
string: placeholderColorSeed ?? '',
|
||||
variant: type === 'app' ? 5 : 4,
|
||||
theme,
|
||||
}));
|
||||
|
||||
const fixedBorderColor =
|
||||
type === 'app'
|
||||
? (borderColor ??
|
||||
(isPlaceholderFirstCharEmpty
|
||||
? undefined
|
||||
: stringToThemeColorP3String({
|
||||
string: placeholderColorSeed ?? '',
|
||||
variant: 6,
|
||||
theme,
|
||||
})))
|
||||
: undefined;
|
||||
|
||||
const showBackgroundColor = showPlaceholder;
|
||||
|
||||
const showBorderColor = showPlaceholder;
|
||||
|
||||
const appliedBorderColor = showBorderColor ? fixedBorderColor : undefined;
|
||||
|
||||
const avatarStyle = {
|
||||
'--avatar-color': fixedColor,
|
||||
'--avatar-background': Icon
|
||||
? 'inherit'
|
||||
: showBackgroundColor
|
||||
? fixedBackgroundColor
|
||||
: 'none',
|
||||
...(type === 'app' && appliedBorderColor
|
||||
? { '--avatar-border': `1px solid ${appliedBorderColor}` }
|
||||
: {}),
|
||||
} as React.CSSProperties;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(styles.root, styles[size], className)}
|
||||
data-type={type ?? undefined}
|
||||
data-clickable={!isUndefined(onClick) ? true : undefined}
|
||||
onClick={onClick}
|
||||
style={avatarStyle}
|
||||
>
|
||||
{Icon ? (
|
||||
<Icon
|
||||
color={iconColor ? iconColor : 'currentColor'}
|
||||
size={theme.icon.size.xl}
|
||||
/>
|
||||
) : showPlaceholder ? (
|
||||
<span className={styles.placeholderChar}>{placeholderChar}</span>
|
||||
) : (
|
||||
<img
|
||||
className={styles.image}
|
||||
src={avatarImageURI}
|
||||
onError={handleImageError}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
.container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.itemContainer {
|
||||
margin-right: -3px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
declare const classNames: {
|
||||
readonly container: 'container';
|
||||
readonly itemContainer: 'itemContainer';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,23 @@
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import styles from './AvatarGroup.module.scss';
|
||||
|
||||
export type AvatarGroupProps = {
|
||||
avatars: ReactNode[];
|
||||
};
|
||||
|
||||
const MAX_AVATARS_NB = 4;
|
||||
|
||||
export const AvatarGroup = ({ avatars }: AvatarGroupProps) => {
|
||||
if (!avatars.length) return null;
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
{avatars.slice(0, MAX_AVATARS_NB).map((avatar, index) => (
|
||||
<div className={styles.itemContainer} key={index}>
|
||||
{avatar}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
|
||||
import {
|
||||
AVATAR_URL_MOCK,
|
||||
ComponentDecorator,
|
||||
JotaiRootDecorator,
|
||||
} from '@ui/testing';
|
||||
|
||||
import { Avatar } from '../Avatar';
|
||||
|
||||
const meta: Meta<typeof Avatar> = {
|
||||
title: 'Modules/Users/Avatar',
|
||||
component: Avatar,
|
||||
decorators: [ComponentDecorator, JotaiRootDecorator],
|
||||
args: {
|
||||
avatarUrl: AVATAR_URL_MOCK,
|
||||
size: 'md',
|
||||
placeholder: 'E',
|
||||
type: 'rounded',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Avatar>;
|
||||
|
||||
export const Rounded: Story = {};
|
||||
|
||||
export const Squared: Story = {
|
||||
args: { type: 'squared' },
|
||||
};
|
||||
|
||||
export const NoAvatarPictureRounded: Story = {
|
||||
args: { avatarUrl: '' },
|
||||
};
|
||||
|
||||
export const NoAvatarPictureSquared: Story = {
|
||||
args: {
|
||||
...NoAvatarPictureRounded.args,
|
||||
...Squared.args,
|
||||
},
|
||||
};
|
||||
|
||||
export const App: Story = {
|
||||
args: {
|
||||
type: 'app',
|
||||
avatarUrl: '',
|
||||
placeholder: 'Acme',
|
||||
placeholderColorSeed: 'acme-app',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
|
||||
import { Avatar, type AvatarProps } from '@ui/display/avatar/components/Avatar';
|
||||
import { type AvatarSize } from '@ui/display/avatar/types/AvatarSize';
|
||||
import { type AvatarType } from '@ui/display/avatar/types/AvatarType';
|
||||
import {
|
||||
AVATAR_URL_MOCK,
|
||||
CatalogDecorator,
|
||||
ComponentDecorator,
|
||||
JotaiRootDecorator,
|
||||
} from '@ui/testing';
|
||||
|
||||
import { AvatarGroup, type AvatarGroupProps } from '../AvatarGroup';
|
||||
|
||||
const makeAvatar = (userName: string, props: Partial<AvatarProps> = {}) => (
|
||||
// oxlint-disable-next-line react/jsx-props-no-spreading
|
||||
<Avatar placeholder={userName} placeholderColorSeed={userName} {...props} />
|
||||
);
|
||||
|
||||
const getAvatars = (commonProps: Partial<AvatarProps> = {}) => [
|
||||
makeAvatar('Matthew', { avatarUrl: AVATAR_URL_MOCK, ...commonProps }),
|
||||
makeAvatar('Sophie', commonProps),
|
||||
makeAvatar('Jane', commonProps),
|
||||
makeAvatar('Lily', commonProps),
|
||||
makeAvatar('John', commonProps),
|
||||
];
|
||||
|
||||
const meta: Meta<
|
||||
AvatarGroupProps & AvatarProps & { numberOfAvatars?: number }
|
||||
> = {
|
||||
title: 'Modules/Users/AvatarGroup',
|
||||
component: AvatarGroup,
|
||||
render: ({ numberOfAvatars = 5, ...args }) => (
|
||||
<AvatarGroup avatars={getAvatars(args).slice(0, numberOfAvatars)} />
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof AvatarGroup>;
|
||||
|
||||
export const Default: Story = {
|
||||
decorators: [ComponentDecorator, JotaiRootDecorator],
|
||||
};
|
||||
|
||||
export const Catalog: Story = {
|
||||
parameters: {
|
||||
// TODO(a11y): violations inherited from deprecated story; fix during a11y pass
|
||||
a11y: { test: 'todo' },
|
||||
catalog: {
|
||||
dimensions: [
|
||||
{
|
||||
name: 'number of avatars',
|
||||
values: [1, 2, 3, 4, 5],
|
||||
props: (numberOfAvatars: number) => ({ numberOfAvatars }),
|
||||
},
|
||||
{
|
||||
name: 'types',
|
||||
values: ['rounded', 'squared'] as AvatarType[],
|
||||
props: (type: AvatarType) => ({ type }),
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
values: ['xs', 'sm', 'md', 'lg', 'xl'] as AvatarSize[],
|
||||
props: (size: AvatarSize) => ({ size }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
decorators: [CatalogDecorator, JotaiRootDecorator],
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
export const invalidAvatarUrlsAtomV2 = atom<string[]>([]);
|
||||
invalidAvatarUrlsAtomV2.debugLabel = 'invalidAvatarUrlsAtomV2';
|
||||
@@ -0,0 +1,22 @@
|
||||
export const AVATAR_PROPERTIES_BY_SIZE = {
|
||||
xl: {
|
||||
fontSize: '16px',
|
||||
width: '40px',
|
||||
},
|
||||
lg: {
|
||||
fontSize: '13px',
|
||||
width: '24px',
|
||||
},
|
||||
md: {
|
||||
fontSize: '12px',
|
||||
width: '16px',
|
||||
},
|
||||
sm: {
|
||||
fontSize: '10px',
|
||||
width: '14px',
|
||||
},
|
||||
xs: {
|
||||
fontSize: '8px',
|
||||
width: '12px',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export type AvatarSize = 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||
@@ -0,0 +1 @@
|
||||
export type AvatarType = 'squared' | 'rounded' | 'icon' | 'app';
|
||||
@@ -0,0 +1,39 @@
|
||||
.banner {
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
font-family: Inter;
|
||||
font-size: var(--t-font-size-md);
|
||||
font-style: normal;
|
||||
font-weight: var(--t-font-weight-medium);
|
||||
gap: var(--t-spacing-3);
|
||||
justify-content: center;
|
||||
line-height: 150%;
|
||||
min-height: 40px;
|
||||
padding: var(--t-spacing-2);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.primaryBlue {
|
||||
backdrop-filter: blur(5px);
|
||||
background: var(--t-color-blue);
|
||||
color: var(--t-font-color-inverted);
|
||||
}
|
||||
|
||||
.primaryDanger {
|
||||
backdrop-filter: blur(5px);
|
||||
background: var(--t-color-red);
|
||||
color: var(--t-font-color-inverted);
|
||||
}
|
||||
|
||||
.secondaryBlue {
|
||||
backdrop-filter: none;
|
||||
background: var(--t-background-transparent-blue);
|
||||
color: var(--t-color-blue);
|
||||
}
|
||||
|
||||
.secondaryDanger {
|
||||
backdrop-filter: none;
|
||||
background: var(--t-background-transparent-danger);
|
||||
color: var(--t-color-red);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
declare const classNames: {
|
||||
readonly banner: 'banner';
|
||||
readonly primaryBlue: 'primaryBlue';
|
||||
readonly primaryDanger: 'primaryDanger';
|
||||
readonly secondaryBlue: 'secondaryBlue';
|
||||
readonly secondaryDanger: 'secondaryDanger';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { clsx } from 'clsx';
|
||||
|
||||
import styles from './Banner.module.scss';
|
||||
|
||||
export type BannerColor = 'blue' | 'danger';
|
||||
|
||||
export type BannerVariant = 'primary' | 'secondary';
|
||||
|
||||
const BANNER_VARIANT_COLOR_CLASS_NAMES = {
|
||||
primary: {
|
||||
blue: styles.primaryBlue,
|
||||
danger: styles.primaryDanger,
|
||||
},
|
||||
secondary: {
|
||||
blue: styles.secondaryBlue,
|
||||
danger: styles.secondaryDanger,
|
||||
},
|
||||
} as const;
|
||||
|
||||
type BannerProps = {
|
||||
color?: BannerColor;
|
||||
variant?: BannerVariant;
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export const Banner = ({
|
||||
color = 'blue',
|
||||
variant = 'primary',
|
||||
className,
|
||||
children,
|
||||
}: BannerProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
styles.banner,
|
||||
BANNER_VARIANT_COLOR_CLASS_NAMES[variant][color],
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
.banner {
|
||||
border-radius: var(--t-border-radius-md);
|
||||
margin-bottom: var(--t-spacing-4);
|
||||
}
|
||||
|
||||
.bannerContent {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: var(--t-spacing-2);
|
||||
}
|
||||
|
||||
.bannerText {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
declare const classNames: {
|
||||
readonly banner: 'banner';
|
||||
readonly bannerContent: 'bannerContent';
|
||||
readonly bannerText: 'bannerText';
|
||||
};
|
||||
export default classNames;
|
||||
@@ -0,0 +1,53 @@
|
||||
import { clsx } from 'clsx';
|
||||
import { useContext } from 'react';
|
||||
import { ThemeContext } from '@ui/theme-constants';
|
||||
import { Button } from '@ui/input/button/components/Button/Button';
|
||||
import { type IconComponent } from '@ui/display/icon/types/IconComponent';
|
||||
import { IconInfoCircle } from '@ui/display/icon/components/TablerIcons';
|
||||
import { Banner, type BannerColor } from './Banner';
|
||||
|
||||
import styles from './InlineBanner.module.scss';
|
||||
|
||||
type InlineBannerProps = {
|
||||
color?: BannerColor;
|
||||
message: string;
|
||||
button?: {
|
||||
title?: string;
|
||||
onClick?: () => void;
|
||||
hidden?: boolean;
|
||||
};
|
||||
LeftIcon?: IconComponent;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const InlineBanner = ({
|
||||
color,
|
||||
message,
|
||||
button,
|
||||
LeftIcon = IconInfoCircle,
|
||||
className,
|
||||
}: InlineBannerProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<Banner
|
||||
className={clsx(styles.banner, className)}
|
||||
color={color}
|
||||
variant={'secondary'}
|
||||
>
|
||||
<div className={styles.bannerContent}>
|
||||
<LeftIcon size={theme.icon.size.md} />
|
||||
<span className={styles.bannerText}>{message}</span>
|
||||
</div>
|
||||
{button && !button.hidden && (
|
||||
<Button
|
||||
size="small"
|
||||
variant="secondary"
|
||||
accent={color}
|
||||
title={button?.title}
|
||||
onClick={button?.onClick}
|
||||
/>
|
||||
)}
|
||||
</Banner>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
.banner {
|
||||
align-items: center;
|
||||
background-color: var(--t-accent-secondary);
|
||||
border-radius: var(--t-border-radius-md);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
gap: var(--t-spacing-2);
|
||||
padding: var(--t-spacing-2);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.iconContainer {
|
||||
align-items: center;
|
||||
color: var(--t-color-blue);
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
height: 16px;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.message {
|
||||
color: var(--t-color-blue);
|
||||
flex-grow: 1;
|
||||
font-family: var(--t-font-family);
|
||||
font-size: var(--t-font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--t-font-weight-medium);
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
}
|
||||